 Hey everybody, it's Brian. Welcome to the 19th C-sharp tutorial. We're just going to do a little more advanced file I.O., so let's just do using system.io. I'm going to kind of whip through this because, well, we've already covered this, so I'll just say static. Now, if some of you are wondering, why are we saying static? Well, because our main is static, you can't call a non-static from a static. Say right file. If you don't know what static is, I suggest you watch the other tutorials. Basically, static just means you can have only one instance of it. All right, so we got our right file. And now we want to do read file. And then, of course, we're just going to call these one at a time. I forgot to make our variable here. Oops, we put this in the usual location. And you don't have to name it a text file. I mean, it can really be named anything. I'm just whipping through the basics here. Of course, we want our console.read. That way our console window stays open. Now we can get to the nitty gritty here. And let's just unpin that. We want to write our file. So really what we need to do is make what's called a file stream. Think of a stream much like a stream. That's why it's called a stream. It's like a river or a stream. It's just data that constantly flows. So we're going to say file stream. And then we'll just call it fs equal new file stream. And notice how we got a lot and a lot and a lot of options here. Well, we're going to keep it simple. We're going to say file name. And then we need a file mode. And file mode, I don't know if you can see it in the video, but you get like a pen to create blah blah blah blah blah. Well, you should read the documentation for these. A pen will open it and write to the end. Create will create the file. If it exists, it's overwritten. Create new. We'll throw an error if it already exists. Open will open it. Open or create will open or create it. Truncate it. Just wipes the file clean and starts over. So what we're going to do here is we are going to say create. That way it is just completely overwritten every single time. And then we want a file access. And file access, I don't know if you can see in the video, determines what you're doing here. We're saying file access read, read, write or write. What we want to write. So what we're saying is we're making a stream that we're creating. See file mode create. And the mode is right, meaning we're only going to write. We cannot read from the stream. And it makes it much simpler, much faster because, well, you're only going to write to it. So it just keeps going and going and ignores what you've already done. I know that sounds funky, but trust me, it works and it's very good. One thing you should always do when you're writing is call flush. Flush is well like flushing the toilet. You flush everything down to the stream and make sure it gets written down to the desk. Some people would argue that calling close flushes it. But I found from personal experience sometimes that's not necessarily true. So I would just caution you to use flush. Now that we've got our stream, we want to do something to it. Well, we're in write mode. So if we attempt to read, it's going to throw an error. So what we do is we say fs. And you notice how we can write, write byte, write timeout, begin write, etc., etc. Well, we're just going to write. And what you should do is say can write. Just to determine. So we'll say if fs can write, and then we'll say fs write. And notice how it wants a byte array and offset an account. Well, this is the tricky part about working with streams is that it takes byte arrays. So let's say we want to write a string down to this file stream. How do we convert a string to a byte array and vice versa? Well, let's comment that out for a minute. And let's just, well, create a byte array, say byte. And we'll call this buffer equal encoding. And we'll just say ascii.getbytes. And what encoding ascii.getbytes does and I should back up for a minute and say, well, you can use any type of encoding. A lot of people, instead of using ascii, will just use default, which is, you know, pretty good. Encoding determines the characters and how they're flushed out to the disk. I like using ascii just so I know what to expect. And we can say getbytes. And then you can convert things. For example, a string, characters, anything you want. So we're just going to say, hello world. That converts this string hello world into a byte array, which we can use with a stream. Now there are easier ways of doing this, but I'm showing you the hardcore. This is how you get stuff done. Now the offset, this is the position in the byte array that we just created. So if you wanted to start at, say the fifth position, you would count zero, one, two, three, four, five. So it would start right there. That's the offset. We want to start at the beginning. So it's going to be zero. And then it wants to count. How many bytes total do you want to write out? Well, we want to write them all. So we're just going to say buffer dot length. Pretty simple stuff. Now, why would you do it this way? Well, very simple. Sometimes you need absolute control over what's getting written to the disk and in what order and how. So you would convert everything into a byte array. A byte is the simplest, smallest, logical value that you're going to have in C sharp. And then you write that out to the disk as raw bytes. Now, reading is actually pretty similar. We're just going to say file stream fs equal new file stream. And we want to give it a file name that we want to open. So we're just going to give it our variable here. Help if I could type. And then we want file access. We want to read. Oops, let me back up here. I want to make this as similar to the old one as possible. So file mode. And we want to do open because we want to open the file. And then a file access. And then we want to read. There we go. So what we're saying here is we're creating a new file stream from the file name. We want to open the file. We're not creating a pending or trunking. So we want to open. And then we want to read from it. Now, if that file doesn't exist, and we try to open it, it's going to throw a humongous error and say, ain't file not found. That's why you use file mode open. So if the file doesn't exist, you can catch it with an exemption. And then we're just going to say fs.close because you always want to close a stream or resource when you open it. Now we actually need to read it. So I'll say fs read. And this is where you get the number of bytes you've actually read from this thing. So let's just say it bytes read equal fs read. And then we need a buffer. So you see how everything works with this byte array. I know that can be incredibly frustrating. But what we need to do here is make a buffer. So let's just say byte. Call this buffer equal new byte. And we'll just give it 1k. So we're going to have a buffer of, you know, 1024 bytes. And we want to begin reading at the zero position in the stream and read the block of bytes from blah, blah, blah. So this is the maximum number of bytes we're going to allow this to read. That way we don't have a buffer overflow. Buffer overflow, if you know anything about hacking and penetration testing is a bad thing to have in your software. So we're just going to say buffer.length. From this, we get bytes read. So we actually have a buffer of 1024. But you can see in our file we don't have 1024 bytes going into this file. We have like maybe what 10, 11, 12. So we're going to get the number of bytes read out of here. And it's going to fill in this buffer. The buffer will still be 1024. But we'll know exactly how many we've gotten. And then we'll just say console.writeLine. Actually you could just say write. And let's see. Yep. There's that. Try to see if they've got a byte in there. No, they don't. Well, what you can do here is say console. And we'll just say writeLine. Maybe if my keyboard would quit flipping out on me. Sorry, I've got it geared towards gaming. And then we can just say encoding. Aske and we'll say getString. That will convert the bytes into a string. And you notice how it also has an index and account. So we'll say buffer index. This is the position of the first byte. So we want to start at the zero position or the first byte. And then we want to know how many bytes to actually process. Well, we want the bytes read because we want to know exactly how many of these to do. So let's see what's wrong here. Sorry, my cat's distracting me. Quick review before we run this. When we write the file, we're creating a new file stream. Think of a stream as a highway. It goes all the way behind you farther than you can see. And it goes all the way in front of you further than you can see. And there's data all along here. That's a file stream. Now I'm not saying it's infinite. A stream has a length. I'm just saying it can be a very, very long road. It's much simpler and easier than using then an array. As you can see with an array, you've got to say a number of bytes you want to put into it. Now we create our file stream. We give it a file name. We're telling it how to create the file stream, meaning how to create the file. Then we give it an access mode where we're going to write, read or read and write. And then we're saying if we can write, then do something. And in this case, we're just making a buffer bytes. And we're using encoding ascii.git bytes to turn hello world into an array of bytes. Then we're just simply writing that out to the disk, flushing the contents and closing the stream. And then with read, we could have done the can read. And just for sanity's sake, let's just say if fs, sorry, can read. And let's just copy and paste that in there. So same thing, we're just opening the file. We're saying open, so the file must exist or this will throw an error. And then file access read. Then we're saying if we can read, then we're going to make a buffer, make it big enough to hold the contents of the file. Then we're going to read that in. Now you may be asking, how do I know how big to make that buffer? Well, let me show you a little trick here. You can go fs.length. And that'll get the length of the file stream or the length of the file. So we're just making a buffer big enough to hold the entire file. And then we're just going to read it in. Then we're going to take that buffer, convert it into a string using encoding ascii.git string and throw it back out into the console. And then our program will simply just sit there and wait. So run this, and of course it says hello world. So that is more advanced file input output. I realize I kind of whipped through this pretty quickly, but really what you need to understand are the concepts of streams. A lot of the underlying mechanisms in .NETs use streams, so you should get very comfortable with them. A stream is just a class. You see how when you hover over it says class system IO dot file stream, it's just a class. It's just an object, a blueprint. You've worked with these before, so don't be intimidated. Anyways, I'm battling. This is Brian. I hope you found this tutorial educational entertaining. And I'm going to try and whip out more of these, not just C-Sharp, but also QC++, but uploading video right now that kind of chronicles how I've been very busy. So bear with me. Thank you for watching.