Check out a free preview of the full Digging Into Node.js course
The "Reading Files with Path & FS Modules" Lesson is part of the full, Digging Into Node.js course featured in this preview video. Here's what you'd learn in this lesson:
Kyle demonstrates how to use path.resolve to get a file's relative path, __dirname to get the current directory of a file, and how to print the contents of the file to the screen using the readFileSync within the "fs" module. Considerations about how the data is being passed are discussed.
Transcript from the "Reading Files with Path & FS Modules" Lesson
[00:00:00]
>> Kyle Simpson: So now that we know we can specify something like a string. But since it's a file, we wanna actually treat it as a file. And we know that we need a full path name if we're gonna do something with this file. So let's pull in another built in package from Node called path.
[00:00:19]
Minimist was a user provided one and it would show up in the node modules folder but path is just built into node. It's one of the many that's just built into node and we can use for free. And path has a number of different methods that are helpful for us, but in particular, the one that we wanna look at if we were to say filepath, we say path.resolve and then give it (arg.files).
[00:00:52]
And then we'll print that out. Let's see what that does at the command line. If I just say file= hello, you'll notice that it is implying that there should be a file at this absolute location in the directory that we're at called hello. So it's default behavior is if we give it a relative path, it figures it out according to that.
[00:01:17]
If I were to do something like ../hello and we do like a relative path that way, you notice that it automatically figures out where that is. So it handles all of the relative path thing logic, all that other stuff that you should not actually go invent yourself. Just use path.resolve to do that.
[00:01:38]
Now notice that it's referencing a file, but it's not telling us this is just a string operation. It's not telling us that that file exist, just saying if you specify it according to that, then that seems like that's a file that you're trying to indicate. So let's go back to our code and let's,
[00:01:57]
>> Kyle Simpson: Look at one other property that we might wanna use which is called dirname. __dirname. If I said console.log(__dirname);
>> Kyle Simpson: That's a magic variable that's available in all of our Node programs. And it tells us the working direct not the current working directory, it tells us the current directory of the current file that we're accessing it in.
[00:02:34]
So if you access a file that's deep, it'll give you the directory of that. So, if we check this out, run this again with just hello. You notice that dirname is that. So basically path.resolves, defaulting to saying, if you don't give me something that's absolute, then I'm gonna go ahead and make it relative to current dirname.
[00:02:56]
If we were to give it an absolute path, like /tmp/hello, then it doesn't use dirname. So it only uses dirname if we've given it a relative path. Okay, so now that we know we have a path to something, and if as long as we give it a file, we're gonna be able to do something with it.
[00:03:19]
Let's make our command line script that we're building or ex1 here. Let's make it access that file and just print the contents onto the screen. Very simple task. To access the file system, we're gonna need another built in module from node called fs for file system. And then rather than dumping this logic all into that if statement, I'm gonna go ahead and write a function down here called processFile().
[00:03:49]
It's gonna take a file path. It's gonna do something with that filepath. So let's just go ahead and call processFile with that path.
>> Kyle Simpson: So what do we wanna do with our filepath? We want to get the contents of the file. There's a couple of ways that we're going to accomplish that.
[00:04:21]
So first, what we're gonna do, is just simply do contents = fs.readFileSync. Sync stands for synchronous. So we're gonna tell it, I'm gonna wait around while you go get this file. And then we're gonna give it the filepath. And then we're gonna do console.log(contents).
>> Kyle Simpson: When we run this, you're going to see a little bit of a quirk about how buffers work.
[00:04:59]
So let's run this code. And we're gonna give it a file that actually exists and you'll notice in your current directory you have a files subdirectory that I've given you and in there, there's a file called hello.txt.
>> Kyle Simpson: So we're gonna give it a file that actually exists and when I run this program, we don't see the contents of the file, we actually see the stringification of a binary buffer.
[00:05:28]
That's because, by default, the file system commands, in fact, most I/O commands, they're assuming these low-level binary buffers. They're not assuming that you wanna represent things as strings. Interestingly, if we had taken console.log out and instead done process.stdout.write, let's look at what happens here. Now we're passing not a steam, but a buffer directly to process.stdout.write.
[00:06:05]
And if we run that, now you'll see that we passed the binary buffer directly to the shell. The shell knew what to do with those bites, and it translated them into characters. So the reason the previous example wasn't being translated is because by the time that got to the shell, console.log had already stringfied it into those characters that you saw.
[00:06:26]
It wasn't passing along a buffer, it was passing along a string of characters that said buffer 0c all that stuff. So when we want to pass along a buffer we've got to make sure we're actually dealing with a buffer and not something that's going to turn it into a string first.
[00:06:41]
And that's why I said earlier that console.log does more than just put a new line on the end. It actually, tries to do some processing on the values. That's why a video console.log42 or you do console.log'42. It does different colored output in your shell, it's because console log is doing a bunch of extra value processing.
[00:07:03]
And when we don’t want the value processing what we really wanna do is just process.stdout.write. So in this particular case, that ends up being exactly what we want. We want process.stdout.write instead of console.log. Now one other thing that you could have done if you really needed it as a string and not as a buffer, you could’ve told the read file to use a particular encoding.
[00:07:29]
If you pass an encoding to one of the
>> Kyle Simpson: File system commands like a read file command, and you give it an encoding it will say, okay, I know you're not wanting the buffer, you're actually wanting a real string. So we could have said UTFA. So this code's going to do exactly the same thing when we run it.
[00:07:50]
No difference at all, except under the covers, there is a slight performance difference. Because now what we've handed from our Node program over to the shell environment is a preprocessed string, which is slightly less efficient by like microseconds, but slightly less efficient than handing it a stream of binary data.
[00:08:10]
That's just something to keep in mind when you're dealing with input and output of data.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops