Understanding File System | Understanding Node.js Core Concepts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey welcome back now that we understand binary data buffers and character encodings we're now ready to move on and discuss how to deal with files inside of nodes now before I start to talk about what exactly a file is and how your operating system handles files and where exactly node will come to play here I just let me just quickly show you an example of how to deal with a file inside of node so what I want to do is to open up my terminal and I have created an empty folder called app and inside of it I'm going to create a new file called app.js and I'm just going to open up this folder inside of my code editor like this all right now before I write any code I'm going to go ahead and create a file in that folder in that app folder and I'm just going to call it text.txt and inside of this file I'm just going to put some random text so some random text now what I'm going to do inside of node I'm going to grab the concept of this file and lock that onto the screen so it's a pretty straightforward process so all we have to do is to require the fs module so I'm going to say const FS equals require FS using this module we could deal with files we could write files we could read files search and directories and all of that kind of good stuff so with this in place I am now going to read that file so I'm going to say FS that read file and let's search synchronously in this case we're going to talk a lot more about these Concepts but let's just stick with the synchronous manner so read final sync and right here I have to specify a path now my path is in the same directory so I'm just going to say text.txt like so and I'm also going to save the content inside of a variable like this constants equals the content of this read file and sync function now with this in place we could now lock this content onto the screen so I'm going to say console.log contents all right let's now run this and see what we're dealing with sounds of my terminal I'm going to say node app.js and as you can see here we're getting back a buffer now if you recall from the previous video that we talked greatly about buffers and binary data you should know that everything you have on your computer is just the reason once and a node we have this buffer module to deal with those and ones so when you try to read a file you are getting zeros and ones and with this buffer module here you could actually well read them you could do encodings on it convert it back to string or maybe convert a string to Binary and a lot more that we talked greatly in the previous video so if you don't understand what this buffer is please go ahead and watch that previous video on this playlist now each one of these zeros and ones so they are representing those irrescent ones in hexadecimal formats each sequence of bits represents a capture so this sum here might be I don't I'm not sure but maybe this 0 isn't once this o might mean another sequence of bits now what we could do is to use character encodings to convert this binary data remember this contents just holds some zeros and ones we could convert it into a string so what I can do here is to run the two string method on that buffer on that series and ones and just specify character incoming in this case I'm going to specify it as utf-8 now if I go back to my terminal and run that file again in this case I am getting some random text all right now in this video we're going to create a complete application and while doing it we're going to learn a lot more about the fs module so I just want to show you a quick demo of the application that we're going to build so what we're going to do right now is to go ahead and create this application together and by doing that we'll learn a lot more about the flying system in node.js and also some more node.js Concepts so let me just show you this quick demo this is the application we're going to build this is the code and we're going to clean this up a little bit this is just what I did right now I need to clean this up before we write it but anyway let me just show you what this application does now what it does is that it constantly watches a file that I created here and it's called command.txt and what it does is that I I just throw some command in here and the application is going to watch them and it's going to do those commands so I could create files here I could delete a file I could add to a file and all of that kind of good stuff so let me show you just some examples of how this works so what I can do here is to just write some commands so I'm going to say create a file and then name I could just say test.txt or I could specify the whole path and in this case I'm going to specify the whole path so I'm going to right click here and I'm going to click on copy path because I'm going to create this file in my directory because we could see it that the file appears right here so I'm going to paste that in users Joseph desktop app and then in this folder Which is my working directory this app folder I'm going to create a file called I don't know my new file Dot txt and if I save it notice it's going to watch this and it's actually watching it right now it's going to see this command create a file and then it's going to create a file with this path name so if I save actually sorry I need to start the application first so I'm going to say node app.js and now if I save here I'm gonna get that file here on my directory now some of the other things that I could do is to delete that file so I could just say delete file and then if I save the file is gone and then create it create it again so create file in this case I'm just going to name it test Dot txt we have the file right there we could actually rename the file if you want so we could say rename the file this and then to this case I'm going to say the new name and if I save if you watch here the file name is going to change now we have the file with the name the new name and what else we could do we could also if I take a look at the commands we could also add to the file so I could say add to the file this and then I guess it was what let me just take a look at the commands uh yeah it was disk content so I could say I have to Define this this content and then here I just specify some things maybe hi there and then on a new line I could say let's go out and I'm also going to change the file name to the new file name so the new name actually it's the name of this file that we have right now in our current working directory and now notice now this file is now empty but if I save here if I go back to the file I now have those two lines that I added it could add new stuff here if I wanted to I don't know maybe some texts and then some more text let me only add in some gibberish like this more and then some more doesn't make any sense but anyway if I save it if I go back to my file I see that I have now those stuff that I specified here so yeah this is pretty much it about this application and we're gonna build this application together in this video now one thing I'm going to point out is that in this application we're just using the fs module so we're not going to use any third-party packages we're not going to use any other native node.js modules we're just using this FS module so we're using this to watch that file whenever we save the file and then we're reading those commands and then we're executing them and yeah this is pretty much it now before we start to write this program before we start to build it uh let's take some time and try to understand what exactly files are so what in the world of file is what does a file represent so now we're going to take a moment and have a small discussion about files in general so we're going to step away from node.js for just a second and try to understand some Concepts in the operating system itself so let's first talk about what exactly is a file now the concept of file is very general but we could say that a file is a sequence of bits meaning which is defined by the user maybe someone who has created the file or you as someone who wants to open that file and I say the meaning because each sequence of bits might mean a different thing depending upon how you want to decode that data so in the case of a text file a certain sequence of bits might mean a character maybe character C now the same sequence of bits the same day data if the file is an image might mean a completely different thing so it might mean something that's associated with an image maybe like a color code or the location of a pixel so it's important that we say how we want to open the file how we want to decode those zeros and ones now everything you have on your computer is just a file so your storage device your hard drive as a steep anything really your flash disk your USB they're all divided to files in other words a search units of a storage device is a file now file could represent different things it could represent a program or they could represent maybe some data datum could be an image a video file or something that's in a free form like a text file like a Javascript file so that's really what a file is and now let's take a look at a diagram so you have your hard drive and you have written some data on it remember data is just some zeros and ones in a computer so this is your hard drive and this is all of your data now each sequence of bits here means a file so this sequence of bits is a file now each file also has some other data associated with it now they're usually saved in some other file which is called a file data which corresponds to a file so in that file data we have stuff like the name of that file of the protection protection means whether or not you could write to a file or maybe you could just read the file and you can't write to it or also if someone else on your computer so another user can open that file or not so these are things related to protection of the file saved onto that file data we also have the location of a file which is just a path name we also have to type and again using these types we could actually know how to interpret the file either it's an image or if it's a text or anything else so depending upon the type of the file we open that file differently we use different decodings to open it we might use a character decoding if it's a text file or we might use an image decoding if it's an image file or video decoding if it's a video or any other types of decodings we also have some time stamps associated with a file one was the file last opened when was it last modified when was it created and things that sort and also some other stuff which is really not important so we're not really going to dig too deep into this so this is what a file is it's a sequence of bits and now maybe another sequence of bits here is another file and actually every bit that I pick here belongs to a file okay so your whole hard drive is divided into different files you cannot write anything on your hard drive unless you write it to a file so everything you have on your drive is just a file and actually your whole operating system itself is just different files okay everything you have on your computer they're all just files in fact let me show you some examples so if I open up my terminal now right here I could run some commands like LS or mkdir to create some directories if I run a witch mkdir now the switch itself is also another file another program but if I run this which mkdir it's going to give me a path and then mkdr and let me just go ahead and open that path up real quick okay so here's a bin folder and as you can see here I have all different kinds of commands that I execute on my terminal like the echo commands or the ls commands if I run last year I could list all the files and folders which is when I'm running this I'm actually getting this I'm actually executing this file okay so it's part of my operating system I cannot delete these but they are just files and if I right click and say get info well here I could see the file data it's kind in this case it's Unix executable file and I could see the size I could see its location when was it last created and some other timestamps and other data associated with it so everything you have on your computer is just a file and actually your operating system itself could only execute the executable files so my operating system itself does not have any idea whatsoever how to open an image file or how to open a PDF file now what happens is that in a lot of cases my case I have Mac OS operating system there are also some other applications shipped with it my case preview right here uh it's just an application that I could use to open image files so it's not really something related to my operating system well actually it's related but it's not really my opening system at its core now my operating system itself only knows how to open executable files right here as you can see Unix execute will fly so I could just double click on them and without the use of any other decoder or any other application my computer is going to run it so each executable file is specific to a specific operating system and a specific CPU type all right well that's a little bit more information that you need to know but the point is everything is just a file in fact my applications that are just they're all just files if I go to my applications well my calendar app if I right click and click on show package Contents I want to see a whole bunch of different files that when I execute that application are going to come into play so I have another Unix executable file here some data associated with a file and many other things so everything is just a file now let's now talk about how node.js deals with files because while dealing with files is very important everything we have is a file and we need to have a way to deal with them node.js is a server-side technology and is a server-side technology you need to have a way to deal with files right so how what exactly happens when you try to I don't know maybe delete a file using node.js or when you try to append some data to a file or you try to rename a file how exactly node.js does that so let's go back to the slides and talk about this for a minute [Music] so we have our hard drive again and then on top of this hard drive we're running our operating system now if this kind of sounds weird to you you gotta go ahead and watch my video about uh the video that's called notice under the hoods I really talked about how these kind of work so you have your hardware and then you're running your operating system on top of it so your operating system is a managing the hardware you also have different processes running in this case we have node.js so when you run into this application you're actually opening a new process on your operating system now what happens is that when you're dealing with files using nodes node just doesn't have any idea how to go to your hard drive and then find a file and modify the bits there it doesn't really have any idea how to do it so it's not going to go directly into your hard drive so what happens is that node.js is talking to your operating system so the way that happens is using some things called system calls so node.js using system calls talks to your operating system and then your operating system goes to the hardware and do some different things now imagine you want to open a file and note so you want to open a text file you're going to call a system call you're going to tell the operating system that I want to do that I want to open that file now in this case we're going to use the open system call so you're going to run that open call which is an operating system commands and then your operating system is going to go to the hard drive find that file fetch those zeros and ones and give you the data and then you could do whatever you want with it you could maybe open different files using this open system command actually you're not directly calling this open what you're doing is that you are running a function in node and then node.js using libuv is actually calling this open system call okay it's actually very simple so you're just talking to the operating system and operating system here is kind of like a middle map so it's going to go ahead fetch those files that you want and give you those files and then maybe you are going to go ahead and then add them together and create a new file containing those three files and then write that file again onto the hard drive so you might use another system call I actually don't remember what is a system called for writing a file but you could use that system call to write that new file onto your hard drive so we have different system calls we also have a rename system call so you could call this rename and then change the name of a file you don't have to memorize these system calls but it's kind of good to know what is happening behind the scenes so node.js is using libuv to do these it's using yellow buv to call these system calls and to get those errors and ones or to write those words and ones onto the hard drive and there's also this thing inside of Lobby called threadpool which we're not going to get into it right now but later on in the course we will get into it so node.js is using different threats to deal with the files if you are really doing some heavy calculations on the files you're actually uh really exhausting that thread pull and you might want to come up with different solutions actually you know what we're going to get into it later but right now I just want you to be familiar with the terminology and that's thread pull which we will get into later on but that is inside of Lobby and one of the things that it does is handling the files all right all right so now that we understand the file system in general and how files are handled in the operating system and what really node.js does when you try to deal with the files using the fs module now that we have some kind of rough idea about them let's now go ahead and start to write some codes but before we do it before we try to create a file or delete a file or something like that it's important to know that in node.js we have three different ways to do the exact same thing so we could either use the promises API or we could use the Callback API or we could use the synchronous API so three different ways to do the same thing and note using the file system actually so if you want to create a file you could either use the prompts API so you could create the file using promises or you could use the Callback API or you could do it synchronously so we have these three ways of doing the same thing now we might be asking how do they differ well actually in terms of functionality they don't meaning that if you want to delete a file it doesn't matter if you use the promise API or the Callback API or the other one the file is actually going to get deleted and in turn it doesn't really matter which one of these you use if you just want to delete a file now in terms of how they do it well it's a little bit different now you might be asking how and which one of these should I use in my applications now to answer your question I should say that in general maybe 90 of the time or 99 of the time especially when you're just starting out stick with the promises API okay so if you're just starting out use the promises API as much as you possibly could it's a lot cleaner and they are I think they have implemented all of the functionalities using the promises API I'm not quite sure but I think as I was reading the documentation I didn't see any function that wasn't implemented using a promises API and when you really want to have the maximum amount of performance now in very rare cases when you're doing something really complex and it takes a ton amount of CPU computational power in those cases you might want to stick with the Callback API and I'm saying this actually based on what node.js documentation says it says the Callback API defines as a module is faster than the promises API and use this callback version when performance is really critical to you and you want to have the maximum amount of it now I haven't really done any benchmarking in this regard but I'll make sure to do some and later on post something on the channel to show you how much faster the Callback API is comparing to the promises API at least in the file system module now about the synchronous API you just try to stay away from it as much as you possibly could only use it when you are dead sure that you have to use it for example one case that you might want to use it is that you are trying to read a configuration file before you actually start your application so you need some of the data in that configuration file to really start your application and without them you can't proceed you can't really run your application and you're going to run into so many different errors so in a case like that and it's actually going to happen only once when you're starting your application it makes sense to use this synchronous API actually you have to use a synchronous API you it will be really daunting to won't do something like that using the Callback API or the promises API but in general in 99 of the time stay away from the synchronous API there are some cases that you might want to use it and I'm sure you will figure them out whether or not you should use the synchronous API but promises API and callback API are a lot faster than this one actually they're not faster but what happens is that when you are using the synchronous API you are blocking your main thread so for example if someone is uploading a file and you are saving a file using the synchronous API when someone starts to upload a file your whole application will freeze so if you're running only one instance of your node.js application only one process that process is going to get freezed until it's done with the uploading which is of course not ideal and you don't want that to happen but if you use one of these two two different asynchronous ways of doing that same thing saving the file your application will continue to work just as normal so it will handle that file uploading and at the same time it will respond to different requests and it could actually handle many more file uploadings at the same time but if you want to do that same thing using the synchronous API your whole application will just become unresponsive until that task finishes so you really want to be careful whenever you want to use the synchronous API okay so we have three ways of doing the same thing and notes and now let's jump into my code editor and let me show you the same thing but using these three different ways all right so here I'm in my code editor and I have actually copied this code in so you don't have to watch me typing these so I have the exact same function copy file but I'm doing it using these three different apis so the first two are asynchronous ways of doing it using the promise API and the Callback API and the last one is using the synchronous API so what I'm doing is that I'm copying this file actually the name is file.txt so let me just quickly change this so I have a file here in the same directory called file.txt and I'm going to copy this file to a new file and I'm going to name it something like copied and then the name of the API so in this case copied promise copied callback and copied sync and we're going to see how do they do further do they actually differ or not so let's go ahead and try to run some of these so I'm going to first comment out the synchronous API version and the Callback version and let's just go ahead and run it using the promise API so I'm going to open up my terminal and I'm going to run node app.js and we're not logging anything but if you take a look here we have copied the file over so now we have a new file called copied promise which has the exact same contents as the file.txt so so far so good right and now let's go ahead and do the same thing using the Callback API and I want you to just take a look at these syntax and see how do they differ if you take a look at the name of the functions are the same so fs.copify now in this case we are requiring out of the fs module but in this case we are requiring out of f is slash promises which again something to keep in mind when you want to use the promise API but in terms of the function itself they do the exact same thing I mean they even have the same arguments so the first one is my source and then my second argument is my destination now in this case we are catching the error using try and catch and in this case we are catching the error using a callback function and here we have the error first as an argument which is pretty common one where you are using callbacks in node.js so you're passing a call back to the function and always the first argument is an error and maybe the second argument could be something else maybe I don't know something but and when you're used dealing with node.js callbacks it's this error first as arguments is very common and you're going to see it a lot and also one more point I said stick with the promise API because it's a lot cleaner now in this case well the Callback version looks cleaner but the reason is it's just uh I'm doing this immediately invoked function because I want to make use of this weight and a async syntax but in a lot of cases you don't actually have to do this and you are already inside of a function so you just mark it with async and then you're good to go so we have these try and catch but again it's it gets a lot cleaner as time goes by comparing to the Callback API because you might run into callback hell you might have maybe another callback function here and another inside of it so in general just try to stick with the promise API and only try to do this callback API when you are when performance is really important to you and you want to have the maximum amount of it okay so we ran the promise API version so I'm just now going to comment this one out and now let's go ahead and run the Callback API so I'm just going to say no dot app note app.js and again we're not logging anything but if you take a look here in my directory now I have another file called copied callback and again I have the exact same contents so these two are doing the exact same thing it doesn't matter if I want to do it using the Callback version or using the promise version the accept the same arguments the parameters are the same and well what they do is the same even the name of the functions are the same now let's go ahead and do it using the synchronous API now in this case well we're requiring the fs module just like here in the Callback API put the name of the function is slightly different so what's different is that we in the synchronous API we usually have to actually I think in all of the cases we have this sync think at the end of the name of the functions so copy file sync unlink sync or create file sync so we'd have this in the synchronous API because as I said before you really got to be cautious whenever you want to use this function so no just kind of wants to make it super clear that you are using the synchronous API so you have to be careful and you will know that you are using this synchronous API so only use it when you are 100 sure that you have to use it now in this case we don't have any kind of error handling in place if it goes wrong my whole application is going to quit but as you can see here it's really the same thing as this one so copy file and then source and destination so let's just go ahead and run this one too so I'm just going to say node AP adjust and again sure enough we have copied Dash sync which has the exact same contents so I copy the file a note using the fs module but using three different ways either using the promise API or the Callback API or the synchronous API okay now we might be asking uh what happens if we have an error so let's go ahead and try that out too so I'm just going to change the name of my file or I might delete it actually I'm just going to add one to it because in this case our source is now is not going to be found now let's try the promise API first and see what kind of error we're going to get so we're catching the error here and then we're logging it onto the screen simple enough I'm going to run it and as you can see we're getting an object back which says which has the code of this so it says that no such file or directory at this source so it cannot proceed with the copy operation now let's go ahead and try the same thing using the Callback API I'm going to run it and as you can see we're getting the exact same error within the same exact same error number code and it's just the real really exact same thing now let's try it with the synchronous API now in this case it's a little bit different but again the error code and all the rest of data is the same thing now the difference here is that it is coming differently so here we are catching the error and we could handle it we couldn't we could do something to maybe proceed with our application if that error happens and not quit but in this case my whole application will quit the whole process will quit as soon as something goes wrong here so it's kind of like if I try to reference a variable that does not exist like this if I run this I'm going to get the an error just like here okay so three different ways to do the same thing a note now in our application that we're going to create we're going to stick with the promise API so we're not going to use any synchronous API or callback API but you should know that they do exist and I can't comment this out okay so let me also show you how to notice documentation is indicating these three different ways now I'm just going to search for node.js file system oops typo but here it found it okay so if you scroll uh actually right at the top here you could see that it has three different examples using the proms example the Callback example and the synchronous example so right on behalf you could see that node.js is saying that you have these three different ways of doing the same thing so if you see that the file system documentation is super long it's actually because it's describing the same thing but using these three different ways which actually there are really similar and nothing really different now in the real world whenever you want to use one of these functions you might want to come to the documentation so you really don't have to memorize anything to know that hey the promise API uses this set of arguments and maybe the Callback API uses those set of arguments actually again in a lot of cases they're the same thing I didn't see anything that was different but there might be so it's always good to come here and take a look at the function that you want to work with for example if you want to create a directory click on it and in this case it's the Callback version if we want to see the promise version just search for that like this and then you could find the here we found the synchronous version if we keep going uh I don't know where it is but I think it is somewhere around here if you just keep looking hopefully I could find it ah here it's actually FS promises I didn't know that so the prompt is it's called FS promises and in the Callback you know this is calling it f is but anyway you could see that it's the exact same function using the exact set of arguments and then you can also see an example so always whenever you want to use a function in the flying system module and actually anything that we want to use in node.js any kind of function just come to the documentation and read that through okay and now let's start creating our application so what I have done is I have just created an empty directory and I highly encourage you to follow along as well so go ahead create an empty directory call it whatever you want and open that up in your code editor and now I'm going to create two different files one is app.js from where we're going to write our node.js code and another one which is command Dot txt and in this file we're going to write our commands so what we are going to do is that we are going to watch this file and look for events Okay so and the top events that we're actually looking for is the change event so whenever I change this file I'm going to get that but get the content of the file and see what the user has specified with the user has commanded to do what are the instructions and just go ahead and do that so the first step for us is to start to kind of watch this file all right so let's see how we can do it now if you go ahead and open up the documentation of node.js and start your look for how you could watch a file so what you can do is just search for watch and right here we could find some examples so if I start from the first one which is in the promises section so in the promises API we have this function available to us called prompt fspromises dot watch so I'm going to use this function to watch for changes that happen in that file and I actually read this before so I'm not going to do it right now but let's just go ahead and do it so what we can do is just first of all we have to include the fs module so require f is and we would want to use the promise version so f is slash promises and then I'm going to create an immediately invoked function just so that I could use the async await syntax and also just one point that I want to say it's a JavaScript note when we're doing this we're actually it's not the only benefit is not that we could use the async wage syntax it's also that we are limiting our scope so if I Define a variable here sample const a equals this I cannot do it again here I'm going to get an error that it's a const and you cannot redefine it but if I move it out of this function I could do it no problem so the variables that I have here variables functions objects whatever are completely separated from the ones that I have here so it's a nice technique to use to limit your scope and I'm not really going to teach you what scope is in JavaScript if you don't know what it is you need to learn about it you need to research because it's very important and you've got to learn how scoping Works in JavaScript as someone who wants to use node.js so I'm just going to say scope okay so if you don't know that go ahead and search for it and see what you could learn about it because it's really important okay anyway so let's now go ahead and start to use that function so I'm going to say episode watch and here we could either specify a file name or we could specify a directory in this case I'm going to watch my whole directory so I'm just going to say dot slash and then I'm going to save it into variable called watcher now what this Watcher is is that it's an async iterator okay uh if you're not familiar with async in order and async Generator let's just write the code and then I'm going to explain it pretty quick so now we have our async iterator we could go ahead and iterate through it so I'm going to save four weights cons event of watcher and then right here I'm just going to lock the event to see what we're dealing with okay and I made a mistake somewhere let me just put in this semicolon so that my formatting won't be messed up all right so with this in place we're now watching this whole directory and we are logging all the events that happen again this is an async iterator so if you go ahead and search for that in the JavaScript it's an actual es6 functionality so it was it's just recently came to JavaScript as you can see this is how you use that for a weight up statement to Loop through those that the function that returns data asynchronously so you'll see this function here and there in JavaScript it is usually used for whenever we want to read a data and data is coming asynchronously so this async generators and async iterators are used in those cases this is as much as I'm going to talk about this because it's really related to JavaScript and nothing related to node.js although in the link that I have included in the description box that I say learn this JavaScript concept here or learn that one there I have included a section called async generators and async iterators so if you want to learn about it go ahead open that link up and find that section and read those articles and watch some of the videos that I have included but if you really don't understand this async generator in iterator and you don't care to go ahead and learn about it you could just as easily change this to a callback version and to be honest it could look cleaner if you are not really familiar with this async generator concept so you could do that but I'm not going to do it in this video so really it's up to you if this doesn't make sense to you and if you don't care to go ahead and learn about it just change the syntax to the Callback syntax and you could just learn about it here in the documentation so I think it's called fs.watch let's see if we can find that function yeah it's right here so f is the watch and then you could see the syntax right here so we just say watch some directory or a file name and then you specify the Callback but I'm going to stick with the promise version okay so with this in place let's now go on ahead and run it and just get some events okay so I'm going to say node app.js and now this is running and because this function keeps running we're not quitting so what I'm going to do right now is to come to my command.txt file and I want to issue an event and if I change this now and keep in mind that if you're typing right here in your code editor or your text editor application you're not actually changing the contents of the file so whatever you're doing here you're doing it in your memory in your RAM as soon as you say if you are saving those changes onto the file so you are going to the to your hard drive to your disk and then you're saving the content there and at that point you are changing the file so right now no events as soon as I save I'm going to get an event right here and as you can see it has two different properties it's an object we have the event type which is change and the filing that was changed in this case it's command.txt now let's go ahead and play around with it a little bit so I'm going to create a new file I'm just going to call it new file.txt and if I create this one go back to my code editor excuse me to my terminal I can see that this time around event type is renamed and the file name is this one so whenever you delete the file or you rename a file or you create a file you're going to get this renamed event so if I for example delete this now I'm going to get another rename event type now if you're wondering how in the world how we could figure out if it was an actual rename or if it was creating that file or if it was deleted what you could do is to just use other FS module functions to look for that so if you see the event type you could just check see if that file still exists or you know some things like that to figure out if it was deleted or if it was renamed or just recently created but for our application we don't really care about this rename events all we care about is the change events so if I come to this file or actually any file so if I create a new file and I start to change the contents of this file I'm going to get the change event so if I save I'm going to get the event type of change and this is a filing that was changed file.txt and one thing that's kind of weird is that whenever I'm saving I'm getting this event type change twice so I don't have anything and if I just do one save actually this time I got one but sometimes I inside in this case I got two so what really happens is that I don't know but I do know that it has nothing to do with node.js it is something related with the visual studio code so if you try to change the content of the file but maybe using the another application like Nano which is the simplest possible way that you can imagine to edit a file so if I just try to change the content of that file using Nano and just say something and then try to save it if I go back I'm only going to get that event type once so it's just something that's going on with the Visual Studio code and honestly I don't know what this is but we're not going to care about that because the node.js is watching and every time the content file changes it's going to get that event so I don't know maybe Visual Studio code is doing a double save or something like that but it's not really important at this point so this is how we are going to watch that file we're watching this directory and we're looking for really any changes that happened but we don't need to watch for everything we just need to watch for the event type that is of change and the file name which is command.txt so what I can do is to say if events.event type is equal to change and events.file name is equal to command dot txt now at this point well the file was changed and we're going to do our operations so let's just do a quick look so I'm going to say consonant blog file was changed so let's go ahead and try this out and run the application and now if I delete this file.txt file I'm not going to see anything in my terminal so nothing happens but as soon as I change this file like this and I save I'll get that block and again as I said before we're sometimes going to get that event twice that change event twice but it really has nothing to do with note and it's something that Visual Studio code does behind the scenes but the point is at this point we are now ready to read the contents of this file and actually do something with it so we could watch and see if it says create a file or rename a file or whatever else that we might want to do now one more point is that this Watcher this episode watch function it could either accept a directory or just a file name so if you accept the directory it's going to watch this whole directory if I create a new file or if I change really any file it's going to kick in but I don't need to do this all I want to do in this case is to watch this command.txt file so what I'm going to do is to change this from watching the whole directory to change it to only watch that command dot txt file and if I save if I run my application again and I save I'm going to get that change event again and also we don't need to now check for the filing because at this point we reach this point the file name is this one because we're only watching that file so what I'm going to do is just go ahead and remove this second condition now what happens is that we are watching that file and whenever this event type of change happens now here we are going to do our work okay try this one more time I'm going to save and there we go all right so now let's try to read the contents of that file when we change that file so what we need to do is right here in this if statement when we reach this point we want to read the content file right so that we could see what command has users specified now let's see how we could approach this problem how do you think we could read the content at this point now the way that it works whenever you want to read something when we want to read a file is that you first have to open it so you're first going to open the file and then once the file is opened you could either read from that file or you could write to that file or append to it or get the status of that file and by status I mean that file data for example you want to see when that file was last modified so you could do all that sort of stuff after you open the file okay and it's not really anything specific to node.js it works the same way and your whole operating system in Python it's the same thing in C plus plus it's the same thing if you want to read the contents of a file you first have to open it and then you could read from it now what really happens when you open a file is that you are you're not actually moving the whole contents of that file to your memory what happens is that you are just saving a number regarding that file it's called a file a descriptor descriptor okay and this is really you you're going to see this term a lot in the notice documentation well a file descriptor is just a number that has been assigned to an opened file so each open file has a unique file descriptor think of it like an ID so when you open a file you're going to have this unique number regarding that file so later on you could read from it or write to it or do anything else that we want to do with it so let's just try to do this now let's first try to open the file and then let's try to read the file the way we can do it is like this we could either open the file right here before we start to watch the file or we could do it after we started watching that file and again at this point what you want to do is to refer to the documentation and figure out how a node you could open a file I already know how to do this so I'm just going to write the code but if I were coming here from another program language what I would do is to just refer to the documentation and I would just as easily learn how to do it it's really nothing too complicated super simple if you understand the concept it's really the same thing in different programming languages so python C plus plus the way you work with files it's really similar between them so the way you could open a file is to use the open function available in the fs module so I'm just going to say fs.open and then I'm going to specify the path in this case it's command Dot txt and then I'm going to specify a flag we're going to talk more about what different options we have to specify as flag but in this case I'm just going to specify R meaning that I'm only going to read from this opened file I'm not going to write to it I'm not going to append to it I'm just going to read from it and this is this returns a promise so I'm going to say wait and then I'm going to save this one to a variable so that I could reference it later on here in this if statement so I'm going to say file actually I'm going to say just name it command file Handler okay so right now we have this object and we have some methods available to call on it now let's go ahead and take a look at the documentation and see what we're dealing with real quick so let's see what this file Handler is so I'm going to open up the documentation and right here in the promises API just at the top you could see a class that says class file handle so it's a very important class in the node.jsfs module so right here let's just try to click on it so as you can see here it says it's just an object with a numeric file descriptor and you could create this class by this function that we just used so it really isn't the content of the file when you're opening a file you're not actually reading the file you're just saving a number to your memory so later on you could read or write or do whatever you want okay so this is the file handle class and also one more Point whenever you are opening a file it's very important that you close it when you're done with it so right here we're opening a file but we need to close it at the ends when we're done because you are occupying your memory and if you forget to do it you're going to run into some memory issues so you're going to have some memory leaks if you really try to open a lot of files and then forget to close them so it's important to close a file after you're done with it and again it's the same thing in other program languages as well you open a file you're done and then you close it it's like that you are allocating a resource to something and then when you're done with that resource you're going to free that resource okay let's now go ahead let's actually again go back to the documentation and see some of the other functions that we have available so in the file handle class the method that I'm going to use to read the contents is actually this one file handle dot reads and as you can see here we have three different options but really they all do the same thing so the name of the functions are just the same the way that they differ is in the arguments that we pass to those functions so if you read the description of each one of these methods you can see that they are literally the same thing so reads data from the file and stores that in the given buffer the same thing here and then the same thing right here so really the argument is the only thing that's different between these three right here could specify the buffer offset length and position and right here again we could specify them all but in an object which is a little bit different but again it's really the same thing the last one you could specify the buffer as the first argument and then specify the rest of them in an object again they return the same thing they return a promise in each one of these cases with the exact same data that we're going to talk about in just a second so I'm going to read the contents right here if I go back to my code editor now that I have the file opened right here I'm going to say FS actually not FS but that file handle which is command file Handler so I'm going to say command file Handler dot read I will just read it and don't specify anything to it and see what we have so I'm going to say wait because it's a promise and I'm going to save it to a variable called contents and then I'm going to log that content to my console there's a constant.lock contents okay so I have this file with this text and now I'm going to run my application save and as you can see right now we have now an object that has two different properties one is bytes red and another one is a buffer now white thread indicate how many bytes we have read from that file in this case and the first log it's 11 and in the second log it's zero and the reason is we're actually moving the position each time we read from that file so in the first read we are starting from position zero meaning the first character and then we're going all the way to the end which is 11 which is our last character so if I move back to my code editor and as you can see here I have 11 characters so I select all and right here at the bottom you can see that Visual Studio code says that I have selected 11 characters so for each character one byte will be allocated and again if I go back here if you take a look at the buffer we have occupied 11 bytes so if you start to count these they will be 11 so one two three four five six seven eight nine ten eleven okay and remember each byte is eight bits so this very first byte here 6E if I open up my calculator and I switch to hexadecimal and then I just put that number 6E if I take a look here these eight bits are what that number is so this buffer is just holding some zeros and ones and if I switch to Unicode you could see that this code is for a character n and if you recall our text is new content so our first character is n so this is our first read we're reading all the data in that file which is 11 bytes now one issue with this is that we're allocating a huge buffer just to store 11 bytes as you can see here a buffer with a size of more than 16 000 bytes has been allocated just to store these 11 bytes and don't mind this it's just something that I did at copy paste was a mistake but so let's go ahead and try to fix this issue first so let's first try to allocate a buffer that has the size that we actually need so we don't allocate a buffer that's too large in that case we were occupying our memory but we're not actually using that memory or we also need to make sure that we don't allocate a buffer that's too small in that case we're losing some data so if we have let's say 30 bytes of data in that file and we allocate a buffer with the size of 8 bytes we're losing 22 bytes here so we don't want to allocate a buffer that's too large or a buffer that's too small we need to allocate a buffer that's just the right size and the way that we can do it is to get the size of our file so we'll first have to figure out how many bytes we have in this file and then allocate a buffer that has that size so let's go ahead and see how we could do this so the way that we could actually specify the size of our buffer is using one of the arguments of capacity to this read method so if we go back to the documentation here in the read functions you could see that here we could specify it as the first arguments or here we could just specify it as an option over here we could just specify it again as the first option excuse me as the first arguments and then specify the rest in the options object so let's first go ahead and allocate our buffer so that then we could use it right here and then lock the contents now before we allocate our buffer what we need to do is to figure out the size of that buffer and if you recall from our video about buffer the way that we could allocate a buffer is just like this so call Buffer and then dot Alec and then right here I specify the size in bytes so if I want buffer of size 8 I just specify eight anything I could just specify here but I can just specify a number and then to get the number of bytes that we need what I'm going to do is to first of all find out the size of my file so this command.txt I need to find its size now remember we already have this file opened right using when we called this method we have opened this file and we could just access this file handle right here and then get the size so what I'm going to do right here is to just say get the size of our file and we could just do it by calling our Command file Handler object or class and then call the stat methods on it if you want to go to the documentation and read what this method does I'm not really going to explain it too much but in short it just returns some of the stats that we have available on that file meaning that file data that we talked about in the slides the size of the file some of the timestamps type and some other data like that so let's just go ahead and log this to the console and see some of the data we have available so I'm just going to save this and going to come now this line now let's go ahead and run this to run my application I'm going to do a save to trigger this change event if I go back here you can see that now we have some data available to us now one of these things that is really of interest to us is this size property as you can see it's 11. it's just the right size we need to use to allocate our buffer now again we have some other data here available we have some of the other we have some time stamps now there are a couple but some of them one of them is for example the time that the file was created another one the last time that the file was modified and so on and so forth so let's go ahead and use the size and allocate our buffer so what I'm going to do is to right here that I am allocating my buffer I'm going to specify this size so I'm going to save this into a variable called size and I'm going to get the size of this thing so I'm just going to call Dot size like this and then I'm going to pass this size which is the number again remember the size is this one the size of our file which in this case it's only 11 bytes so I'm going to pass the size right here and with this in place we're now allocating a buffer that's just the right size and if I go ahead and log the content again if I save and if I go back to my terminal and run the application again I'm going to come here save uh we have an error I think I think we're doing something wrong here oh it's not actually a function I'm calling it as a function but it should be just a property like this let's go ahead and run again save go back over and now as you can see we're allocating a buffer that's just the right size it's only 11 bytes but as you can see here they're all zeros and the reason is we have actually moved our position when we're reading from that file so what we need to do is to now change the position of that of that method so right here if I can go back to the documentation you could see that in the options we could specify the position the offset and the length so let's now go ahead and quickly allocate these right here and I'm actually going to use the first option that we have so for the second arguments I'm going to specify our offset which is the location and the buffer that we start to fill so in our case we always want it to be zero the length is number of bytes to read again this should be the length of our file because in each read we just want to read the whole contents of the file because our file is pretty small we're only throwing one command at it at a time so we need to read everything that we have available and then the position is a location that we want to start reading from that file again in this case we always want it to be zero so let's go ahead and specify these three arguments so I'm going to head back over to my code editor and I'm going to create three more variables here so const the first one was offset which is going to be zero all the time then we have our length s and our length is going to be the size the size actually you know we could do it a little bit differently let's let's just move this buffer into its own variable as well so I'm going to say const buff equals buffer dot Alec and size and then I'm going to pass this one right right here and then I'm going to pass my offset with the length and then oh length if I can type and then the last one was position again position should always be zero up so let's also go ahead and specify our position which will be always zero and for the length I'm going to specify my buffer size because so I could just say buffer dot bytes length okay so now put this in place we should always be reading from the first character of the file so let's go ahead and give this a shot and see if we're doing it correctly so I'm going to run this application I'm going to do a save and again as you can see here the bytes red is now always the length of our file and we have a buffer that's filled with the data that we need so again I want to just say this one more time in the previous slides we got buffers that had no data in them so we had buffer zero zero zero zero but in this case we have some data and the thing that we changed about our method was this position so this position indicates from what position in this file we want to read the file now if we don't specify it it's going to be always updated so if you in one read you only read the first three characters in the next read it's going to start from the fourth character and moves forward so in our case we we're reading the whole file so it started at the zero and then it got all the way to the end so in our next read it started to read from the end which means that we don't have any more data afterwards so it was an empty buffer but in this case we are always reading from the first character which is of course what we want all right so let me now try to clean this code up a little bit because it now looks really messy so what I want to do is to uh remove these three lines and I'm just going to write some comments here this one is get the size of our file and then allocate our buffer with the size of file and then here is our offset the location at which we want to start filling our buffer which is going to be always zero now how many bytes we want to read and the position is the position that we want to start reading the file from and then right here for the contents I'm just going to say we always want to read the whole contents from beginning all the way to the end and there's something else that we can do and that is that if you go back to the documentation and you come to this class file handle so you just click on this class file handle you could see that the documentation says that all file handle objects are event emitters and we already learned about this event emitter object so this object file handle object is inheriting from this object so what I can do is to again clean this up a little bit more and make use of that vent mirror object so what I'm going to do is to just look for a custom event so I'm going to say command file Handler dot on and I could name my events anything that I want in this case I'm just going to name it change because it makes sense and then I'm just going to pass in a function and the place that I'm going to emit this event is right here so every time this change event happens I'm going to Omit an event so that this function here will run if this does not make sense to you you gotta go ahead and watch my video about Advanced emitters you need to understand event emitters in order to understand this part so I'll assume that you know this so I'm not really going to explain this much and right here I'm going to call actually emit this event so I'm going to say command file Handler that emit and then that change events so what I can do right now is to cut all this code out and then move it to this function I need to make it Market this function as async and there we go so right here we are having our watcher and then here we are emitting this change events which will happen right here so this function here will handle this change event which is getting emitted from this place now let's go ahead and give it a shot and see if we don't have any errors so I'm going to head over to my terminal and run the application I'm going to save and as you can see we're getting the exact same result so this code works well and I think this looks a lot cleaner than what we had before so if you want you could always make use of this event center object and clean up your code a little bit so here this code is only responsible for triggering that change event and then we're doing all of our competition right here so the next thing that we have to do is to actually read the contents so what kind of reading gets put what cannot make sense out of it at this point because we're just getting some zeros and ones right so what we need to do is to run these zeros and ones through a decoder so that we have some meaningful data and I'm just going to say this right here decoder so a decoder gets some zeros and ones and then it gives us something meaningful now an encoder gets something meaningful and turns it into some zeros and ones okay so they're actually doing the exact opposites of each other a decoder will take some data that we can't understand as humans and turns it into something meaningful like a character decoder or an image decoder now node.js only understands a character decoder and a character D encoder it does not understand an image encoder it does not understand the video decoder alright so if you want to do something like that maybe make sense out of a file that's an image you can't do it natively with notes but what you can do is to install some third-party packages that have these decoders in place these decoders and encoders so that you could decode and encode images and then maybe combine them together or edit them resize them or do whatever you want with them but node.js itself only comes in with a character encoder and a character decoder so you can't really read an image and note well again unless you install a third party package or you try to implement those decoders and encoders yourself which could be well quite a job to do but well if you want you could do it alright so in this case what we need to do is to run this zeros and ones through a decoder and another thing that I can do actually is to because we're allocating our buffer right here and then we're filling it using this function we don't actually need to save anything so I'm going to remove this part I'm not going to save this promise to anything so right now I have my buffer and when I reach this point I'm sure that I have filled that buffer so what I can do instead of logging the contents I'm going to log our buffer and let me just remove these two lines and I'm going to run this again and see our buffer I'm going to do a save and as you can see right now we're getting our buffer which is exactly the same thing as this one so I assume that you know how to work with buffers and you should now be able to go ahead and turn this buffer into a meaningful data meaning into some characters now the way you can do it is to just run it again through a decoder and decoder we could use is the two string Methods and right here I specify the character encoding which is utf-8 and utf-8 is default once so I could just really emit this part but for the sake of clarity I'm Gonna Keep it right there so I'm going to save try this out again and as you can see in this case instead of getting a buffer with some zeros and ones we're actually getting a string back so cool we managed to get our data and what we could do right now is to try to do some checkings so for example we want to check to see if we have included phrase a certain phrase like create a file we want to run a certain function so that we could go ahead and create a file we will grab the path that the user has specified in this file along with that command and then do some stuff with that so a command might be like this create file and then the path so the path could be like this users could be an absolute path or it could be a relative path it doesn't really matter but in this case we're going to stick with absolute path now an absolute path is a path that's relative to your whole operating system so I say something like this I start from the birth minimum which is the slash routes which you can't really go up any higher so if I go to my terminal and show it to you I could go to City actually I'm going to open a new tab you could just see the into slash and right here I cannot really go any higher so this is the root folder and we are going to specify our paths relative to this one which are called absolute paths I could also specify a relative path to my working directory which is app so I could just go ahead and say create a file this.txt and the file is going to get created right here in my directory but if I specify an absolute path I could create that file anywhere that I want in my hard drive okay so let's try to tackle this First Command first so I'm going to check here what we need to do is to just check and see actually let's just go ahead and save it into something so I'm going to say const let's call it commands equals this so now that we have our Command which is string which in this case it will be this one we need to check if we have this phrase in that command and if so we're going to get this path and then create that file all right so let's now do our first check which is for creating file so I'm going to say create a file and I'm also going to say how the command should look like which is create a file and then path so when our user specifies this in our file and then saves we're going to run this code I mean let's check that we're going to implement right now so create a file and then the path so what we can do is to just check to see if an R command will have included this string so we could use the enclosed method that we have available on the strings so I could say if commands that includes and then specify that text which is create a file now at this point we know that the user has set something with create a file in it and what we need to do at this point is to grab the path and the way we can do it is by using the substring method that we have available on the strings so we're going to use two different methods two different string Methods one is includes and another one is substring and I'm gonna I'm just going to talk about it pretty quick in just a sec so let's go ahead and grab our file path so I'm going to call it file path equals command Dot substring and then right here I'll specify this create a file say create a file and then I also need to add one to it like this now let me quickly show you what these two methods do really doesn't have anything to do with node.js but let's just talk about it for a second so if I say I have this string wire a equals text I could use the includes method on it it's pretty self-explanatory whenever I specify here if my strength includes that it's going to return true otherwise it's going to return false if I say e x t it's going to be true but if I say e x B it's going to be false so this is the first method another one was substring and right now what do I specify here an index it's going to give me all the characters starting from that index all the way to the end so if I say zero I'm going to get the whole text if I say one I'm going to get from this second character all the way to the end if I say two again I'm going to get I'm going to start from this position which is X and I'm going to go all the way to the end so substring and includes two different string Methods that we have available in JavaScript and again it has nothing to do with notes okay and what we can do right now is to actually move our commands into their own variables because as you can see here I'm repeating this phrase twice so what I'm going to do is to right here I'm going to specify my commands so first one I'm just going to call it const create file command or just create file which is create a file and now I'm going to make use of this right here and also right here so I'm going to hit command D on my keyboard and I'm just going to paste okay and now let's go ahead and make use of this file path that we have and go ahead and create that file so what we can do is to I'm actually going to create a new function for creating a file and I'm going to call it create file uh Visual Studio code that's something that I don't want so I'm first going to Define my function right here so I'm going to say const create file equals this and it's going to accept file path like this or just path and now I'm going to call this function right here and then pass this file path to it okay now what I want you to do as a challenge is to go ahead and try to implement this function so try to create a function that you pass a path to it and then you create a file with that path and that's it you just create that file if it's a text file or it's an image file you just create it create an empty file okay so positively right now and see if you could tackle this problem now remember that you got to go to the node.js documentation and see how you could create files and then try to implement it right here all right so I'll see you in just a second okay so hopefully you gave this a shot and you managed to call this function right here and then create your files so let me now show you my solution so the way that I'm going to create this file is the first to a check and see if we already have that file in place we don't want to create it okay so we're just going to return an error that the file already exists so what I can do is to say file handle maybe exists and actually I'm just going to call it existing file handle makes a little bit more sense I'm just going to say wait fs.open and with the path and I'm also going to specify the flag as read Because in this case again we're not going to write anything we just want to check to see if we already have that file in place and I need to mark my function as async now if this open function doesn't return an error it means that it was successful in opening the file meaning that the file already exists and well we just want to return an error and exit out of this function and say that the file exists and we can proceed so I'm going to say return console.log file and I'm going to use es6 strings to inject the variable right here so the file path already exists pretty simple and I'm actually going to wrap this around the try catch because if we don't well it's not really going to work and you'll see in just a second why I'm going to move this logic right here and remember every time you open a file you've got to close it at the end so when you're done with it you've got to close it now I'm going to Define this variable right here at the top existing file handle like this and then right here after my try catch I'm going to close that file so let's try to go over this again so we want to check whether or not we have that file we already have that file so here if we don't return get an error it means that we do have the file so I'm going to say we already have that file and then right here in the catch if we do get an error it means that we don't have the file so we don't have the file now we should create it okay once I'm going ahead and try to create that file and the way that I'm going to create this file is Again by using the open method so I'm going to say const new file handle equals weight FS dot open path and then I'm going to specify the flag as W meaning that I'm going to write to it and just to show you some of the different options we have available in to specify as the flag you gotta go to the node.js documentation and scroll right here in the notes section and here it's the last item that says file system flags and here we could see it's all the options that we have available to specify as ADD arguments so we used R which means open file for reading now we're going to get an error if the file does not exist okay now we're also Now using this W which means that it will open the file for writing now if the file does not exist it's going to create that file we also have some other commands right here that you could take a look at for example art plus which means it opens file for rating and writing and again an exception we're going to get an error if the file does not exist so this one only opens for reading this one opens for reading and writing so you might want to come here and take a look at all these flags it's really easy to understand what they do so I'm not going to go over all of them okay so I'm going to open this file as W meaning that if we don't have that file in place we're going to create an empty file this in place I'm now going to say consonant lock a new file was successfully created and remember you always need to close a file whenever you open it so I'm going to say new file handle Dot close okay all right so let's go ahead and give this a shot and see if we could create some files so I'm going to save this and I'm going to go back to my terminal and I'm just going to run the application okay now here in the commander takes the file I'm going to say create a file and then let's just call it text.txt if I save okay we have an issue here first of all we're not getting deep path correctly and second of all we are getting an error here and actually my bad if at this point I don't have any file this is not going to get defined right so we're going to get straight to the catch so I actually should move this one right here so what happens here is that I just open the file and then close it if it was okay it means that we already have that file so we're just going to return an error if we do get an error at this point it means that we don't have the files so we're just going to create it right here in the catch and I don't need to do this here I'm just going to Define my variable right here actually as a constant okay now let's try to troubleshoot our path so we're using this substring method ah we actually need to use the length Okay I forgot to do this so we need to get the length and see how many characters we have there and then add one to it and then start from here and go all the way to the end to get our path okay so let's try this one one more time I'm gonna go back to my terminal run the application and then do actually I'm going to delete this file now I'm going to do a save and there we go now we have an empty file created in our working directory let's check to see if we don't have any error no if I was successfully created the file this already exists and it's again because of that double saving thing that happens in Visual Studio code several times save it try to do it twice so the second time we say the file already exists so we're not going to create it okay cool and let's also try to create a file maybe somewhere outside of our directory so I'm going to create a file maybe I don't know maybe on my desktop so I'm going to go to my desktop and I'm just going to create a directory here just count test I'm going to CD into test and right here we don't have any files or folders and now I'm going to create a file right here in this folder which is on my desktop so I'm going to copy this path here go back to my file and instead of this one I'm going to specify an absolute path so I'm going to start from slash root and then users Joseph desktop test and right here I'm going to say a new file Dot txt and actually let's just say dot JavaScript okay so I'm going to save come back here and now we have that JavaScript file created and this test folder okay so it's working pretty good and now with this in place let's move on to our second function and actually I'm going to do all these if statements right now and then I'm going to give you a challenge to implement those functions yourself first before you see my solution so let me do this pretty quick so here we have creating a file and then here we're going to have something for deleting a file so delete a file the command should look like this delete the file and then path so for the if statements I'm going to say if command dot includes let's define that variable actually I'm going to move the variables at the top so I'm going to cut this out then right here at top of our functions I'm going to paste my commands so right here it's creates file and then const delete file which is delete a file then we have rename file so rename file equals rename file and then last one we have add to file this one is add to the file okay so now that we have our commands let's go back here now for this one it's deleting files so if command dot includes delete file now what we have to do is to first get our file path just like before so const file path equals commands Dot substring and for this one we have to get this length and then add one to it and start from there then go all the way to the end just like here so delete file dot length plus one and that's it so delete file our U Visual Studio code so let's see if we can do it okay delete file and then file path so this is for deleting a file and anyone what let's just first add those functions right here so const ipate file file path and we have to add an equal sign right here and I'm just going to say a log right now the waiting this and then it will be your job to implement this functionality here but let's add those two other functions so another one is const rename file and we have to first get our old path and then our new path like this and then I'm just going to say a walk renaming old path to New Path okay and this should be an error function so let me just add in my arrow okay now last one is adding to the file and I'm going to call it add to file this one we need to get the path and also a content so we're going to add this content to this path here I'm going to say adding to this path and let's also lock the contents so ps6 strings so right here I'm going to say contents is contents all right so these three functions in place let's now call them right here so we're calling it right here to delete a file and next up I'm going to write the functionality for renaming files so rename file and here I'm going to say rename the file this to this so we're going to get one path and actually you just name and change it to New Path so we're going to give this function a file a path and then we're also going to give it A New Path so when we write this in our text file we want to rename this path this file to this one so our check so if command dot includes rename file now right here we have to do it a little bit differently so we first have to get the index of this two and then start from here up to this two to get our first path and then start from the end of this two all the way to the end to get our new path so let's go ahead and do it so I'm first going to get the index I'm just going to call it index and it's going to be command dot index off two and I'm also going to add two spaces around it then I'm going to get the old file path which is command Dot substring and we have to get the length of our commands so the length plus one just like before and then up until our index so this is going to start from this portion so we're getting this length and then we're adding one so we'll start from the beginning of the path and then we'll go all the way to the end before the two starts so we're also counting this space now let's also get our new path so new file file path command Dot substring and actually I think I forgot to say this you could just specify one number here and if you do that like here it's going to start from that character and then goes all the way to the end but you could also specify two different numbers and if you do that it will start from this one and then it goes up until this index so in this case it will start from our length plus this part and then goes all the way to the index which is right here it will not go to the end because we have specified two different variables start and finish now we're going to do the exact same thing here but this time we're going to specify only one variable and that's our index but in this case we have to add something to our index because our index will be right here so this index of 2 will return this part so the first portion of this string which is right here now I have to add like one two three four to this one so that I will start from the New Path so index plus 4 and then go all the way to the end to get my new path now with these two employees now we could call our functions so rename file old path and then new file path oops some mistakes it's a new file path and then right here old file path all right now let me also write down the last one which is adding to a file so add to file command looks like this add to the file then path and then we're going to say this content and then we're going to specify our contents so if commands dot includes add to file now again just like before we get our index and then start from the beginning go all the way to here and then stop at this point to get my path and then once more start from this portion after this contents and then go all the way to the ends to get the contents so let's first get the index so command dot index of space this contents so we're going to get this Index right before this this space and then I'm going to get the final path should be command Dot substring now we're going to start from the ends of this command so add to file dot length plus one and then go all the way to the end of this index so we're going to start from this beginning and go up actually we're going to start from here and go until our index which is right here index of this contents which is the beginning of this string now that we have our final path let's also get our content there's a command Dot substring now we're going to get our index but this time we have to add some thing to it so our Index right now is this so we have to add one two three four five six seven eight nine ten actually I'm not going to count it I'm just going to select this part and then look at my visual studio code at the bottom which says 15 selected so it means that this String's length is 15 characters so I'm going to add 15 to it okay so now we have our contents and our file path so let's just go ahead and call that add to file function so the first argument is file path second one is contents all right now before you start your challenge let's run this and make sure that everything is working as expected so I'm going to go back to my terminal from the application and we're not going to run this one anymore but let's try to delete this file so delete file this I'm going to save back over and well we're not getting any logs so let's see what we're doing wrong here all right so I had to possibly for a second to find this out and here I'm saying delete the file that the command is delete the file so let's just change it to delete the file and I'm going to run it again I'm going to save and sure enough we get that lock so deleting this now this means that we're getting our path correctly and it's now your job to implement your functionality right here so you have to path go ahead and delete it so this will be your first challenge now your second one is to rename that so let's see if that works well so I'm going to say rename the file this to just going to copy this path how do you step in but I'm going to change the name to new name save head back over to terminal and now we can see renaming this new file js2 this new name.js so this is going to be your second challenge renaming that file so you have the old path and you also have the New Path now your job is to change the name of that file which is this one to this new file name now your third and your last challenge is to implement this add to file now we've got to get the contents and then add that to this path now let's see if this works as expected so I'm going to back go back to my command.txt file and say add to the file this with content uh this is a new this is some text let's just keep it simple I'm going to save back over to my terminal and it's not working so let's see what we're doing wrong maybe our command's name so it's this content uh yeah so I'm saying what content should be this contents now I'm going to save back cover still not working so this content and then here it's at yeah this is our image typo here so it should be add to the file save rerun and then come here to save and sure enough we got that text so adding to this file with this contents so this is our content this is some text and we need to add this one to a new file dot JS file okay so these are your three challenges possibly right now and go ahead and give these a shot also make sure to do error handlings for example if you're trying to add to a file that does not exist instead of just throwing an error and exiting out of the application just lock something nice maybe Define that you're trying to add some content to does not exist and also don't sweat it if you can't get them all correctly it's fine really but the important Point here is that you gotta give it a shot so you gotta try your best so go to the documentation read them and try to figure out how you could solve these three problems the point is that you get more familiar with the node.js documentation use your problem solving skills more and just you know think and see how you could solve these all right so positively right now and make sure to spend at least 10 to 30 minutes on it all right so hopefully you managed it and now I'm going to show you my solution so for delete file I'm first going to remove this log and then what I'm going to do is to just go to the documentation and search for simply delete to see what node.js offers so I'm just going to search for delete and here we can see that it redirects me to this function f is promises dot on link so using this function could pass a path to it and it's going to delete that file now here it says if path refers to a symbolic link now a symbolic link is just a shortcut so if I go to my terminal and open this one in my finder now here we have our files app.js and command.txt what I can do is just right click and then click on make Alias now it's going to create an alias for me now an alias is just a shortcut it's a file that refers to the original file so if I double click on it I'm actually going to open this file up in my code editor and I have that now on my other screen but it could just double click you could just double click on it and you can open the file but it's not actually the original file so it's not a copy of that file it's just it's just a link that refers to that original file so this is what node.js means by a symbolic link and it could make a symbolic link out of anything maybe out of an application so that you have a shortcut you could double click on it and then you could open the actual program so here it says that if path refers to a symbolic link to a shortcut then that link is removed Without Really affecting the original file but if the path refers to an actual file and not a symbolic link then the file is deleted now here it also says seed posix on link documentation for more detail now Post 6 is just a standard so the standard that we have across different operating system and the reason we have this post-ex standard is to make the job of developers easier so you could develop an application and use these posix standard functions on a Mac and when you ship that application to another operating system that is also posting standards your app will work just fine so you don't have to spend a ton amount of time trying to make your functions in a way that will also work on the other operating system so we have these standards just to make this job easier for example node.js is using some of these posting standards functions like onlink which is the same thing if you try to delete a file and see for example or even on my operating system itself if I go back to my terminal I could make use of this unlink command so let's see what we have here if I try to remove this Alias I could just say unlink app.js slash alias now I made a typo a link and now that Alias is removed now I could use the same exact formats in node.js and it's also going to work the exact same format and c and it's also going to work so I have this on link here in my terminal you have it in other program languages that are also posted standard and also in other operating systems that are posting standards so let's try to use this function this unlink function so I'm going to head over to my code editor and right here I'm simply going to say wait fs.unlink and then I'm just going to pass in the path I also need to mark this as async and that's it all right let's now try to use this and see if it works going to run my application node app.js and if I change this to delete file this and if I save now the file is removed but in our terminal we actually have an error and the reason is again because of this double saving thing that Visual Studio code does so in the first time we successfully removed the file but in the second attempt because we no longer have that file and we try to remove it we're getting an error no such file directory at this path so let's try to fix this one pretty quick so what I can do is to just wrap this around try catch like this and then move this one in the try and I'm also going to catch this specific error so I could say if e dot error e dot code actually if e dot code is equal to this let's copy this one what I'm going to do is just log that no file at this path to remove but I'm also going to implement an else statement here that if any other error happens that is not this one I'm just going to say log and error occurred while removing the file and I'm also going to lock the error okay so this should be pretty much it about this function now we should have also done the same thing right here instead of just if any error happens we're going to proceed with creating that file we should only catch the code that corresponds to the file non-existing so right here if anything happens really we're going to proceed with creating a file so we should do the same thing but I'm not really going to do it you go on ahead and do it because this video was getting pretty long at this point and let's just focus on the main important things all right so let's try this one one more time and now if I first create that file so create a file this we now have that file right there if I try to delete it save actually it should make it to delete the file if I save the file is now gone and my terminal I don't get any errors inside I get no file at this path to remove which is the second attempt all right so this is our delete function now apart from this fs.unlink function there is also another function in node that you could have made use of and that is called the RM function so if I go back here and the fs promises there's this function called RM I'm going to click on it and you could have also make use of this function to remove some files and as you can see here it says remove files and directories modeled on the standard Post 6 RM utility and I could also make use of this RM command in my terminal now the difference between this RM function and that unlinked function is that using RM you could actually delete multiple files you could delete files directories directories that are not empty and actually have a lot more power with this function but with more power also comes greater responsibility so you got to make sure that you don't delete some stuff that you don't want to delete you could just say let me actually just show you how this function works so I'm going to open up my terminal and using a link we saw that I could delete one file if I create just some files a.txt and maybe B Dot txt and let's also create a directory called for example dir now I can't delete this directory using unlink so I say unlink dir I'm going to get an error that the error is a directory I can't also delete multiple files so if I say unlink a.txt and B dot txt I'll get an error that you cannot do this using a link if you want use the RM function so using RM I could delete multiple files and I could also delete directories and also delete directories that are not empty so I could just say rma.txt and B dot txt hit enter and now those two files are gone I could also remove this directory but I have to make use of attack so I could say RM Dash RF dir and now the directory is gone now dash R stands for recursive and F is for forced so we're going to recursively delete anything that we have right there now we could also specify these two options using nodes so you could specify the force and you could also specify the recursive option both of which are actually booleans so you could also make use of this function to delete some stuff but be cautious when you want to use this so if you use this one in your program and then you specify the force and the recursive option to be true and you might say that hey now that I have this let me change it to something that I could also delete directories and maybe multiple files well it's fine but if you try to run something like this rm-rf slash oh God I'm so stressed right now that I have this on my screen so let me just delete it if you run this command what's going to happen is that your whole computer will be just deleted well actually actually not everything but if you run that your computer will not probably turn on again and you might have to clean install your operating system so be really careful about that if you tried this function and then you just randomly specify slash to it and you're going to run rm-rf slash you're going to run into a ton amount of troubles probably you have to clean install your operating system again so it's true that you could also make use of this one but actually you could use this one maybe if you want to delete multiple files but it can be really cautious about it because if maybe someone tries to hack it and pass some kind of path that you know some would somehow bypass your validations they could just delete anything especially your whole hard drive now there's also another function and node that you could use to delete thanks and in this case it's RM directory which could only delete empty directories so you could also make use of this one which just removes the directory identified by path and I also have access to this one in my terminal so if I can create an empty directory I could say rmdir dir and now I don't have that directory but I can only delete folders that are empty and now just is actually advising to get Behavior similar to the rm-rf unix commands use fspromises.rm but with these two options specified as true okay so two more functions you could use to delete stuff RM you can use the delete pretty much anything folders multiple files and also RM directory that you can use to delete empty folders okay and now let's move on to rename file now this one should be pretty easy so let's first remove this log and go back to the documentation and just search for rename and right here we have that definition now this one is the Callback definition so let's let's actually move all the way up and here we could see that we have FS promises a DOT rename so I'm going to click on it all right here we can see that it's a pretty simple explanation just renames old path to New Path and that's it so let's try this out I'm going to say wait FS dot rename old path and then New Path super simple also async I'm also going to do the same error caching right here so I'm going to wrap this around try catch going to move this right here and actually let's also add some logs here so when we have successfully removed the file it's not to say file was successfully removed and right here let's say file was successfully renamed and then right here in the catch I'm going to catch for that same error let's actually just copy paste this code here but instead of no file at this path to remove I'm going to say no file at this path to rename but also we're going to get this exact same error if New Path does not exist so if you try to rename this path to another path that is in another directory and if that directory does not exist we're going to get this exact same error so no file of this path to remove or the destination doesn't exist all right now let's try this one what I'm going to do is to say rename the file text.txt to text new file name actually to make it obvious Dot txt and we don't actually have that file in place I deleted it but if you go to the terminal you can see no file at this path to rename or that one so we're catching that error but let's first try to create a file and actually we already have this final.txt so let's try to rename that one so rename the file file.txt to that one if I save the file is now renamed okay so it works pretty good now using this one you could actually move files around so if I create a directory called dir I could say rename new file name which is our new name to dir slash that and if I save the file will be moved to that directory now if I try to move it to a directory that does not exist we're going to get that exact same error so we're handling that one as well all right moving on to our last function which is appending to a file so what we want to do in this case is to just write some data to an existing file and we want to keep the existing data in place and then just write something at the end so what we could do with this case is well if you think about it appending to a file is just writing to it but we want to do it differently because if you try to write something onto a file what's going to happen is that you're going to just remove everything and then you are going to replace that with the content that you're trying to write well at least by default but if you go to the documentation and you scroll all the way down to find those flags here you could say that if you specify the a option it will open the file for appending so by default if you're trying to write you're going to use this one just W and this will actually just replace the contents but using this Dash a actually not Dash H is a you're going to append to the file so we're going to write at the end so what we're going to do is just open the file first and then just write some stuff to it so let's go ahead and do this so I'm going to remove these two logs and I'm going to say FS dot open and I'm going to open path which is right here and wait and I think I marked this one async but I didn't show it to you so make sure to do it and then I'm going to just save this one to a variable called file handle so now that I have the file opened but actually now I have to specify the flag to be a now right here we specified it to be just R meaning that we just want to read from it but in this case I specified it to be a meaning that we are going to append to it now that we have the file open what we can do is to just write this content to it so I'm going to say file handle dot right content okay and if we want you could take a look at the documentation of this write function as well now this in place let's also just do it in a try catch and I'm not really going to check to see if the file exists or not you should do it if you want to make it like an app production ready application but for the sake of Simplicity and time I'm just going to lock this one so if anything goes wrong we're just going to log it to the screen all right so now let's go ahead and give this a shot I'm going to save run the application and now I'm going to say add to the file and let's first try to create a file so create a file text.txt and I'm also going to delete this directory okay now this file is now empty that we just created I'm going to say add to the file text.txt this contents content's just going to be high if I save if you take a look here we now have that content if I try to Let's also just check the terminal okay so we don't have any errors and let's also add a log so here I'm going to say content was added successfully okay and now if I try to add another content so here we have high high and the reason we actually have high high is because of this double save feature so let's first try to fix this one so what we can do is to just check if we try to add something twice we're going to prevent the pending operation so what we can do is just Define a global variable and I'm just going to say I don't know maybe added contents and every time we append we write right here I'm going to say added content equals that content okay so when we write we're going to save this one to this variable which is outside of our function and then right here before we do anything right here actually I'm going to check to see if added content is equal to content let's just return and don't do anything else in this function so its purpose is only to prevent this double safe feature of Visual Studio codes now you might argue that what if I want to add something twice well you're right you can't do it but let's just just stick with this one not really it's not really that important so I'm going to run this application again I'm going to delete all the contents and let's just try to run this again now we have high and we have to unlock the content was added successfully and if I just save here multiple times we're not actually going to add that high again if I change something about this High maybe change it to Y now in that file we have high and by and just to show it to you what is going to be different if we change this flag so if I change it from a to w and I save and rerun the application now notice that in our text.txt file we have high and by now if I just try to do the same thing add to this file but let's say some text if I save now if you notice here the previous contents is now removed and it was replaced by whatever I tried to write in this case it's just some text so it's important what you specify when you are opening the files so you can specify all these flags right here a for opening the file right for writing to it and actually replacing whatever is already there reading and a couple more so let's change it back to a and we're now done with the add to file function now another thing that I want to say here is that you could also do it in another way so in this case we open the file first and then we wrote to it there is also this function in node that's called append file and it's right here FS promises dot append file and using this one you don't have to actually open the file first now we don't have an example right here but if we see the f is the Callback example it's right here you could see that you don't have to open the file first you could just call the function specified path and the content and that's it so you could do it in one step but actually what's happening behind the scene is that node is opening the file first and then it's writing to it and we could take a look at that in the source code I have it right here and if you want to open this up you could just scroll all the way up right here when the documentation begins you could see that source code for this module is in lib slash fs.js so just click on it it will redirect you to the source code for that module and if you just search for append file here's the function now if you try to read this you specify the path and the data and also what is going to happen is that node.js is going to call this fs.rite file now notice this is the Callback version but it's the same thing in the promise version as well and by default the flag that is going to get specified is Dash a so you're not specifying any flax when you were calling this function but by default nodes is saying that okay the flag should be Dash a now you could also specify flag here in the options for example A Plus or I think we've got a couple more but I don't remember them right now but you could specify the option but what is going to happen is that this function is going to get called which is called Write file so let's also take a look at the definition of that function and it's right here you could call this function specify the path the data and then some options and if you don't specify any flag it's going to get defaulted 2 Dash w but if you scroll down what you're going to see here is that this function the open function is actually getting called first so when you call that append function and note you're actually doing it in a simple step in your code but actually it's going to do it just like before just like opening first and then writing to it so it's going to call this write file function it's going to pass the flag to be a in the options then right here it's going to open that file with that flag which is a and then at the end it's going to write to it so this is the Callback version but you can imagine how the promise version would be different instead of callbacks we would have async await but I just wanted to say that you also have that option to call FS promises dot a pen file or pen file the Callback version but what's going to happen is that node.js is actually going to open the file first and then it's going to write to it so whenever you try to read or write to a file you first have to open it you cannot write to any file without opening it first and when you open a file what's going to happen is that you're just going to assign a number to that file and your memory so we're not actually moving the whole content into your memory you're just going to assign something to say that hey we have that file open keep an eye on it we might want to read from it or we might want to write to it all right our application is now complete I have to say that it's not really production ready we're not handling all the possible errors and also I noticed something weird when adding to a file with some special characters so if we try to add something here if we specify the content but some add some special characters here this index off might get confused and it will not work as expected so there are some bugs here and there and also the code is on GitHub and the link is down in the description box below if you want to try to enhance the application maybe add some more functions fix up the blocks that might happen in special cases do better error handlings and so forth if you do please make sure to upload your code on GitHub and send me a link or put it in the comments down below and I'll be glad to take a look at it so hopefully now you feel a lot more confidence using the fs module and we will definitely use it more throughout the course in the next video we're going to talk about a crucial concept a note and that is streams thanks for watching and I will see you there
Info
Channel: Cododev
Views: 9,871
Rating: undefined out of 5
Keywords: Node.js, File system, fs, fs module
Id: hNzRoZti6vI
Channel Id: undefined
Length: 130min 4sec (7804 seconds)
Published: Sun Nov 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.