File System module
Intro
This is the fifth in a series of tutorials on Node.js.We created a project folder called nodejs-tutorial.
The code for the whole series is available on GitHub at github.com/LearnByCheating/nodejs-tutorial
Create a new directory in the nodejs-tutorial project named 5-fs.
Then open your Terminal application and cd into the new folder.
This tutorial covers the File System module fs.
Read it, watch it, do it, review it:
- There are both a written and accompanying video version of this tutorial. There are timestamps under the headings that align with the video version of the topic.
- Read it: For each topic heading, first read the topic.
- Watch it: Then watch the associated section of the video.
- Do it: Then follow the instructions to replicate the steps on your computer.
- The Node.js CheatSheet has a major category that aligns with this tutorial.
- Review it: When you are done with the whole tutorial, open the CheatSheet and review the File System category from this tutorial. Make sure you understand everything, and can refer back to the CheatSheet when you are working on your own projects in the future.
About the FS Module
[0:00 Video timestamp]
- The Node File System module, fs, provides an API for interacting with the operating system to create, modify or delete files and directories.
- FS is NOT part of the global object so you need to import it before using it.
Below is CommonJS syntax for importing the fs module:
const fs = require('fs');
- Path arguments can be:
- Relative to the current directory:
'./filename'
- Or absolute:
/Users/steve/Documents/filename'
Synchronous vs Asynchronous
[0:53 Video timestamp]- JavaScript is single-threaded so unlike many other programming languages, it can't do two things at once.
- Interacting with the host computer's file system takes place in the Operating System, outside of the JavaScript environment. Methods that interact with the file system can be synchronous or asynchronous:
- Synchronous version: The synchronous version of the method waits for the action to complete before moving on to the next JavaScript statement. The synchronous versions have "Sync" appended to the method name like readdirSync.
- Asynchronous version: The asynchronous version of the method does not wait for the action to complete. It immediately moves on to the next line of JavaScript code. The asynchronous version includes a callback function as an argument. When the action is completed, the callback function is executed.
- Most of the File System module methods have both a synchronous and asynchronous version.
Directories
Read Directory
[0:36 Video timestamp]Create a file named directory-read.js and populate it with:
nodejs-tutorial/5-fs/directory-read.js
const fs = require('fs');
// Read directory synchronous version
const files = fs.readdirSync('.');
console.log(1, files);
console.log(2, 'In the synchronous version, this logs after the file list is returned.');
console.log('-------------------------------------------------------------');
// Read directory async version
fs.readdir('.', (err, files) => {
if (err) throw err;
console.log(4, files);
});
console.log(3, 'In the asynchronous version, this logs before the file list is returned.');
- The File System module has two methods that list the content of a directory: fs.readirSync and fs.readdir.
- The file above uses both of these methods, and each has a console.log message after it.
- Let's see how the synchronous and asynchronous versions of this method differ.
Execute the file with Node to see the results:
node directory-read
Synchronous Version:
- The synchronous format of the read directory method is:
fs.readdirSync(path[, options])
Which in our file is:fs.readdirSync('.');
- The path is a dot so it reads from the current directory.
- Since it is synchronous, it waits to get the result back from the Operating System before moving on to the next line.
Blocking: This is called blocking since it blocks the rest of the code from executing until the response is received back from the operating system.
- When the result is returned, it executes the console.log 1 and prints the directory content to the console.
- Then executes console.log 2.
Then there is a dividing line: -----------------------------------------------------------------------------
Asynchronous Version:
- The asynchronous format of the read directory method is:
fs.readdir(path[, options], callback)
In the our file it looks like:
fs.readdir('.', (err, files) => {
if (err) throw err;
console.log(4, files);
}); console.log(3, 'In the asynchronous version...');
- Since it is asynchronous, as soon as the fs.readdir function is called, it immediately goes to the next line and logs message 3.
Nonblocking: This is called non-blocking since it does not prevent the rest of the JavaScript code from executing while it waits for the response.
- When the Operating System returns the file list, the callback function gets executed. It takes two arguments:
- An error object in case it returns an error.
- The files list that got returned.
- The callback function executes console.log 4 and prints the directory content to the console.
Make a directory
[1:55 Video timestamp]
The below methods make a new directory:
The below methods make a new directory:
- Async:
fs.mkdir(path[, options], callback)
- Sync:
fs.mkdirSync(path[, options])
Create a file named directory-make.js and populate it with:
nodejs-tutorial/5-fs/directory-make.js
const fs = require('fs');
if (!fs.existsSync('newdir')) {
fs.mkdir('newdir', (err) => {
if (err) console.error(err);
console.log('newdir directory created');
});
}
We are using the asynchronous version.
Check that directory doesn't already exist
[2:10 Video timestamp]Note, that we are wrapping the mkdir method in another method called fs.existsSync that checks if the directory already exists. If it does then we do nothing. Without that check, it would throw an error if the directory already existed.
Also note that the callback function takes the error as the argument. If there is an error you can handle it in the callback. Here we're just logging the error message to the console.
Execute the file and a new directory named newdir will be created:
node directory-make
Rename a directory
[2:43 Video timestamp]
The below methods rename a directory:
The below methods rename a directory:
- Async:
fs.rename(oldName, newName, callback)
- Sync:
fs.renameSync(oldName, newName)
Create a file named directory-rename.js and populate it with:
nodejs-tutorial/5-fs/directory-rename.js
const fs = require('fs');
// If directory exists, rename it
if (fs.existsSync('newdir')) {
fs.rename('newdir', 'newdir-renamed', (err) => {
if (err) console.error(err);
console.log('newdir directory renamed');
});
}
- The fs.rename method renames newdir to newdir-renamed. The old name is the first argument, the new name is the second.
Execute the file and the file will be renamed.
node directory-rename
Remove a directory
[3:24 Video timestamp]Async:
fs.rmdir(path[, options], callback)
Sync:
fs.rmdirSync(path[, options])
Create a file named directory-remove.js and populate it with:
nodejs-tutorial/5-fs/directory-remove.js
const fs = require('fs');
if (fs.existsSync('newdir-renamed')) {
fs.rmdir('newdir-renamed', (err) => {
if (err) console.error(err);
console.log('newdir-renamed has been removed');
});
}
Execute the file and the newdir-renamed directory will get deleted.
node directory-remove
Files
[3:41 Video timestamp]Now let's work with files.
Create a file named file-write-read.js and populate it with:
nodejs-tutorial/5-fs/file-write-read.js
const content = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' fs.writeFileSync('text-file.txt', content); const moreContent = '\n\nAppend this sentence to the existing file.' fs.appendFileSync('text-file.txt', moreContent); const data = fs.readFileSync('text-file.txt', 'utf8'); console.log(data);
We are using three different methods in this file. And we are using the synchronous version in all three.
Write to File
Create a new file if it doesn't exist. Replace it if it does.
- Async:
fs.writeFile(file, data[, options], callback)
- Callback function takes err parameter to handle potential errors.
- Sync:
fs.writeFileSync(file, data[, options])
- Our version is:
fs.writeFileSync('text-file.txt', content);
- The first argument is the file name if it's in the same directory, or path if it goes in a different directory.
- The second argument is the content of the file. The content variable is set to Lorem Ipsum filler text.
Append to File
[4:03 Video timestamp]
- Append data to the end of the file.
- If the file does not exist it will be created.
- Async:
fs.appendFile(path, data[, options], callback)
- Sync:
fs.appendFileSync(path, data[, options])
- Our version is:
fs.appendFileSync('text-file.txt', moreContent);
- We are appending more content to the bottom of text-file we created above.
Read File
[4:09 Video timestamp]
- Async:
fs.readFile(path[, options], callback)
- Sync:
fs.readFileSync(path[, options])
- Our version is:
const data = fs.readFileSync('text-file.txt', 'utf8');
- This gets the content of the file from the first argument.
- The first option is encoding which for text would generally be 'utf8'. If no encoding is specified, then the raw buffer is returned.
- We assigned the result to the variable "data" and logged it to the console.
Execute the file:
node file-write-read
The result is:
- The text-file.txt gets created,
- An extra line is appended to the file,
- Then the file is read and logged to the console.
Create a file named file-copy-rename-move.js and populate it with:
nodejs-tutorial/5-fs/file-copy-rename-move.js
const fs = require('fs'); if (!fs.existsSync('newdir')) { fs.mkdirSync('newdir'); }
fs.copyFileSync('text-file.txt', 'file-copy.txt');
fs.renameSync('file-copy.txt', 'file-renamed.txt');
fs.renameSync('file-renamed.txt', 'newdir/file-moved.txt');
- If the newdir directory does not already exist, create it.
Copy File
[4:26 Video timestamp]
Async:
Sync:
Async:
fs.copyFile(src, dest, callback)
Sync:
fs.copyFileSync(src, dest)
- Our version is:
fs.copyFileSync('text-file.txt', 'file-copy.txt');
- Copies text-file.txt to a new file named file-copy.txt
Rename or Move File or Directory
[4:35 Video timestamp]
- Async:
fs.rename(oldPath, newPath, callback)
- Sync:
fs.renameSync(oldPath, newPath)
- Our version for renaming is:
fs.renameSync('file-copy.txt', 'file-renamed.txt');
- Renames file-copy.txt to file-renamed.txt
- Our version for moving is:
fs.renameSync('file-renamed.txt', 'newdir/file-moved.txt');
- Moves and renames the file by putting the file in the newdir directory in the second argument.
Execute the file:
node file-copy-rename-move
- If the newdir directory does not already exist it will be created.
- The text-file.txt will be copied,
- The copied file will be renamed,
- The copied file will be moved into it and renamed to file-moved.txt.
Delete File
[5:02 Video timestamp]
Async:
Async:
fs.unlink(path, callback)
Sync:
fs.unlinkSync(path)
Let's delete the newdir/file-moved.txt file.
Create a file named file-delete.js and populate it with:
nodejs-tutorial/5-fs/file-delete.js
const fs = require('fs'); fs.unlinkSync('newdir/file-moved.txt');
Execute the file:
node file-delete
And the file should be removed.