Interacting with the file system in Node.js is important especially if you need to manage dynamic files to support a web application or service. Node.js provides a good interface for interacting with the file system in the fs
module. This module provides the standard file access APIs that are available in most languages to open, read, write, and interact with files.
This chapter provides you with the fundamentals necessary to access the file system from Node.js applications. You should come away with the ability to create, read, and modify files as well as navigate the directory structure. You also learn how to access file and folder information as well as delete, truncate, and rename files and folders.
For all the file system calls discussed in this chapter, you need to have loaded the fs
module, for example:
var fs = require('fs');
The fs
module provided in Node.js makes almost all functionality available in two forms: asynchronous and synchronous. For example, there is the asynchronous form write()
and the synchronous form writeSync()
. It is important to understand the difference when you are implementing your code.
Synchronous file system calls block until the call completes and then control is released back to the thread. This has advantages but can also cause severe performance issues in Node.js if synchronous calls block the main event thread or too many of the background thread pool threads. Therefore, synchronous file system calls should be limited in use when possible.
Asynchronous calls are placed on the event queue to be run later. This allows the calls to fit into the Node.js event model; however, this can be tricky when executing your code because the calling thread continues to run before the asynchronous call gets picked up by the event loop.
For the most part, the underlying functionality of both synchronous and asynchronous file system calls is exactly the same. They both accept the same parameters with the exception that all asynchronous calls require an extra parameter at the end, which is a callback function to execute when the file system call completes.
The following list describes the important differences between synchronous and asynchronous file system calls in Node.js:
Asynchronous calls require a callback function as an extra parameter. The callback function is executed when the file system request completes, and typically contains an error as its first parameter.
Exceptions are automatically handled by asynchronous calls, and an error object is passed as the first parameter if an exception occurs. Exceptions in synchronous calls must be handled by your own try/catch
blocks of code.
Synchronous calls are run immediately, and execution does not return to the current thread until they are complete. Asynchronous calls are placed on the event queue, and execution returns to the running thread code, but the actual call will not execute until picked up by the event loop.
Node provides synchronous and asynchronous methods for opening files. Once a file is opened, you can read data from it or write data to it depending on the flags used to open the file. To open files in a Node.js app, use one of the following statements for asynchronous or synchronous:
fs.open(path, flags, [mode], callback) fs.openSync(path, flags, [mode])
The path
parameter specifies a standard path string for your file system. The flags
parameter specifies what mode to open the file in—read, write, append, and so on—as described in Table 6.1. The optional mode
parameter sets the file access mode and defaults to 0666
, which is readable and writable.
Table 6.1 Flags that define how files are opened
Mode |
Description |
|
Open file for reading. An exception occurs if the file does not exist. |
|
Open file for reading and writing. An exception occurs if the file does not exist. |
|
Open file for reading in synchronous mode. This is not the same as forcing |
Same as |
|
|
Open file for writing. The file is created if it does not exist or truncated if it does exist. |
|
Same as |
|
Open file for reading and writing. The file is created if it does not exist or truncated if it exists. |
|
Same as |
|
Open file for appending. The file is created if it does not exist. |
|
Same as |
|
Open file for reading and appending. The file is created if it does not exist. |
|
Same as |
Once a file has been opened, you need to close it to force flushing changes to disk and release the OS lock. Closing a file is done using one of the following methods and passing the file handle to it. In the case of the asynchronous close()
call, you also need to specify a callback function:
fs.close(fd, callback) fs.closeSync(fd)
The following shows an example of opening and closing a file in asynchronous mode. Notice that a callback
function is specified that receives an err
and an fd
parameter. The fd
parameter is the file descriptor that you can use to read or write to the file:
fs.open("myFile", 'w', function(err, fd){ if (!err){ fs.close(fd); } });
The following shows an example of opening and closing a file in synchronous mode. Notice that a there is no callback function and that the file descriptor used to read and write to the file is returned directly from fs.openSync()
:
var fd = fs.openSync("myFile", 'w'); fs.closeSync(fd);
The fs
module provides four different ways to write data to files. You can write data to a file in a single call, write chunks using synchronous writes, write chunks using asynchronous writes, or stream writes through a Writable
stream. Each of these methods accepts either a String
or a Buffer
object as input. The following sections describe how to use these methods.
The simplest method for writing data to a file is to use one of the writeFile()
methods. These methods write the full contents of a String
or Buffer
to a file. The following shows the syntax for the writeFile()
methods:
fs.writeFile(path, data, [options], callback) fs.writeFileSync(path, data, [options])
The path
parameter specifies the path to the file. The path
can be relative or absolute. The data
parameter specifies the String
or Buffer
object to be written to the file. The optional options
parameter is an object that can contain encoding
, mode
, and flag
properties that define the string encoding as well as the mode and flags used when opening the file. The asynchronous method also requires a callback
that is called when the file write has been completed.
Listing 6.1 implements a simple asynchronous fileWrite()
request to store a JSON string of a config
object in a file. Listing 6.1 Output shows the output of the code.
Listing 6.1 file_write.js
: Writing a JSON string to a file
01 var fs = require('fs'); 02 var config = { 03 maxFiles: 20, 04 maxConnections: 15, 05 rootPath: "/webroot" 06 }; 07 var configTxt = JSON.stringify(config); 08 var options = {encoding:'utf8', flag:'w'}; 09 fs.writeFile('config.txt', configTxt, options, function(err){ 10 if (err){ 11 console.log("Config Write Failed."); 12 } else { 13 console.log("Config Saved."); 14 } 15 });
Listing 6.1 Output file_write.js
: Writing a configuration file
C:ooks odech06writing>node file_write.js Config Saved.
The synchronous method of file writing writes the data to the file before returning execution to the running thread. This provides the advantage of allowing you to write multiple times in the same section of code, but this can be a disadvantage if the file writes hold up other threads as discussed earlier.
To write to a file synchronously, first open it using openSync()
to get a file descriptor and then use fs.writeSync()
to write data to the file. The following shows the syntax for fs.writeSync()
:
fs.writeSync(fd, data, offset, length, position)
The fd
parameter is the file descriptor returned by openSync()
. The data
parameter specifies the String
or Buffer
object to be written to the file. The offset
parameter specifies the index in the input data
to begin reading from; if you want to begin at the current index in the String
or Buffer
, this value should be null
. The length
specifies the number of bytes to write; specifying null
writes until the end of the data
buffer. The position
argument specifies the position in the file to begin writing at; specifying null
for this value uses the current file position.
Listing 6.2 illustrates implementing basic synchronous writing to store a series of string data in a file. Listing 6.2 Output shows the result.
Listing 6.2 file_write_sync.js
: Performing synchronous writes to a file
1 var fs = require('fs'); 2 var veggieTray = ['carrots', 'celery', 'olives']; 3 fd = fs.openSync('veggie.txt', 'w'); 4 while (veggieTray.length){ 5 veggie = veggieTray.pop() + " "; 6 var bytes = fs.writeSync(fd, veggie, null, null); 7 console.log("Wrote %s %dbytes", veggie, bytes); 8 } 9 fs.closeSync(fd);
Listing 6.2 Output file_write_sync.js
: Writing synchronously to a file
C:ooks odech06writing>node file_write_sync.js Wrote olives 7bytes Wrote celery 7bytes Wrote carrots 8bytes
The asynchronous method of file writing puts the write request on the event queue and then returns control back to the calling code. The actual write does not take place until the event loop picks up the write request and executes it. You need to be careful when performing multiple asynchronous write requests on the same file, since you cannot guarantee what order they will be executed unless you wait for the first write callback before executing the next. Typically the simplest way to do this is to nest writes inside the callback from the previous write. Listing 6.3 illustrates that process.
To write to a file asynchronously, first open it using open()
and then after the callback from the open request has executed, use fs.write()
to write data to the file. The following shows the syntax for fs.write()
:
fs.writeSync(fd, data, offset, length, position, callback)
The fd
parameter is the file descriptor returned by openSync()
. The data
parameter specifies the String
or Buffer
object to be written to the file. The offset
parameter specifies the index in the input data to begin reading data; if you want to begin at the current index in the String
or Buffer
, this value should be null
. The length
specifies the number of bytes to write; specifying null
writes until the end of the buffer. The position
argument specifies the position in the file to begin writing at; specifying null
for this value uses the current file position.
The callback
argument must be a function that can accept two parameters, error
and bytes
, where error
is an error that occurred during the write and bytes
specifies the number of bytes written.
Listing 6.3 illustrates implementing basic asynchronous writing to store a series of string data in a file. Notice that the callback specified in lines 18–20 in the open()
callback calls the writeFruit()
function and passes the file descriptor. Also notice that the write()
callback specified in lines 6–13 also calls writeFruit()
and passes the file descriptor. This ensures that the asynchronous write completes before executing another. Listing 6.3 Output shows the output of the code.
Listing 6.3 file_write_async.js
: Performing asynchronous writes to a file
01 var fs = require('fs'); 02 var fruitBowl = ['apple', 'orange', 'banana', 'grapes']; 03 function writeFruit(fd){ 04 if (fruitBowl.length){ 05 var fruit = fruitBowl.pop() + " "; 06 fs.write(fd, fruit, null, null, function(err, bytes){ 07 if (err){ 08 console.log("File Write Failed."); 09 } else { 10 console.log("Wrote: %s %dbytes", fruit, bytes); 11 writeFruit(fd); 12 } 13 }); 14 } else { 15 fs.close(fd); 16 } 17 } 18 fs.open('fruit.txt', 'w', function(err, fd){ 19 writeFruit(fd); 20 });
Listing 6.3 Output file_write_async.js
: Writing asynchronously to a file
C:ooks odech06writing>node file_write_async.js Wrote: grapes 7bytes Wrote: banana 7bytes Wrote: orange 7bytes Wrote: apple 6bytes
One of the best methods to use when writing large amounts of data to a file is the streaming method. This method opens the file as a Writable
stream. As discussed in Chapter 5, “Handling Data I/O in Node.js,” Writable
streams can easily be implemented and linked to Readable
streams using the pipe()
method, which makes it easy to write data from a Readable
stream source such as an HTTP request.
To stream data to a file asynchronously, you first need to create a Writable
stream object using the following syntax:
fs.createWriteStream(path, [options])
The path
parameter specifies the path to the file and can be relative or absolute. The optional options
parameter is an object that can contain encoding
, mode
, and flag
properties that define the string encoding as well as the mode and flags used when opening the file.
Once you have opened the Writable
file stream, you can write to it using the standard stream write(buffer)
methods. When you are finished writing, call the end()
method to close the stream.
Listing 6.4 illustrates implementing a basic Writable
file stream. Notice that when the code is finished writing, the end()
method is executed on line 13, which triggers the close
event. Listing 6.4 Output shows the output of the code.
Listing 6.4 file_write_stream.js
: Implementing a Writable
stream to allow streaming writes to a file
01 var fs = require('fs'); 02 var grains = ['wheat', 'rice', 'oats']; 03 var options = { encoding: 'utf8', flag: 'w' }; 04 var fileWriteStream = fs.createWriteStream("grains.txt", options); 05 fileWriteStream.on("close", function(){ 06 console.log("File Closed."); 07 }); 08 while (grains.length){ 09 var data = grains.pop() + " "; 10 fileWriteStream.write(data); 11 console.log("Wrote: %s", data); 12 } 13 fileWriteStream.end();
Listing 6.4 Output file_write_stream.js
: Implementing streaming writes to a file
C:ooks odech06writing>node file_write_stream.js Wrote: oats Wrote: rice Wrote: wheat File Closed.
The fs
module also provides four different ways to read data from files. You can read data in one large chunk, read chunks of data using synchronous writes, read chunks of data using asynchronous writes, or stream reads through a Readable
stream. Each of these methods is effective. Which one you should use depends on the particular needs of your application. The following sections describe how to use and implement these methods.
The simplest method for reading data to a file is to use one of the readFile()
methods. These methods read the full contents of a file into a data buffer. The following shows the syntax for the readFile()
methods:
fs.readFile(path, [options], callback) fs.readFileSync(path, [options])
The path
parameter specifies the path to the file and can be relative or absolute. The optional options
parameter is an object that can contain encoding
, mode
, and flag
properties that define the string encoding as well as the mode and flags used when opening the file. The asynchronous method also requires a callback
that is called when the file read has been completed.
Listing 6.5 illustrates implementing a simple asynchronous readFile()
request to read a JSON string from a configuration file and then use it to create a config
object. Listing 6.5 Output shows the output of the code.
Listing 6.5 file_read.js
: Reading a JSON string file to an object
01 var fs = require('fs'); 02 var options = {encoding:'utf8', flag:'r'}; 03 fs.readFile('config.txt', options, function(err, data){ 04 if (err){ 05 console.log("Failed to open Config File."); 06 } else { 07 console.log("Config Loaded."); 08 var config = JSON.parse(data); 09 console.log("Max Files: " + config.maxFiles); 10 console.log("Max Connections: " + config.maxConnections); 11 console.log("Root Path: " + config.rootPath); 12 } 13 });
Listing 6.5 Output file_read.js
: Reading a configuration file to an object
C:ooks odech06 eading>node file_read.js Config Loaded. Max Files: 20 Max Connections: 15 Root Path: /webroot
The synchronous method of file reading reads the data from the file before returning execution to the running thread. This provides the advantage of allowing you to read multiple times in the same section of code, but this can be a disadvantage if the file reads hold up other threads as discussed earlier.
To read to a file synchronously, first open it using openSync()
to get a file descriptor and then use r
eadSync()
to read data from the file. The following shows the syntax for readSync()
:
fs.readSync(fd, buffer, offset, length, position)
The fd
parameter is the file descriptor returned by openSync()
. The buffer
parameter specifies the Buffer
object that data will be read into from the file. The offset
parameter specifies the index in the buffer
to begin writing data; if you want to begin at the current index in the Buffer
this value should be null
. The length
specifies the number of bytes to read; specifying null
writes until the end of the buffer. The position
argument specifies the position in the file to begin reading from; specifying null
for this value uses the current file position.
Listing 6.6 illustrates implementing basic synchronous reading to read a chunk of string data from a file. Listing 6.6 Output shows the output of the code.
Listing 6.6 file_read_sync.js
: Performing synchronous reads from a file
01 var fs = require('fs'); 02 fd = fs.openSync('veggie.txt', 'r'); 03 var veggies = ""; 04 do { 05 var buf = new Buffer(5); 06 buf.fill(); 07 var bytes = fs.readSync(fd, buf, null, 5); 08 console.log("read %dbytes", bytes); 09 veggies += buf.toString(); 10 } while (bytes > 0); 11 fs.closeSync(fd); 12 console.log("Veg g (to get output shown) ies: " + veggies);
Listing 6.6 Output file_read_sync.js
: Reading synchronously from a file
C:ooks odech06 eading>node file_read_sync.js read 5bytes read 5bytes read 5bytes read 5bytes read 2bytes read 0bytes Veggies: olives celery carrots
The asynchronous method of file reading puts the read request on the event queue and then returns control back to the calling code. The actual read does not take place until the event loop picks up the read request and executes it. You need to be careful when performing multiple asynchronous read requests on the same file, since you cannot guarantee what order they will be executed unless you wait for the first read callback to execute before executing the next read. Typically the simplest way to do this is to nest reads inside the callback from the previous read. Listing 6.7 illustrates that process.
To read from a file asynchronously, first open it using open()
and then after the callback from the open request has executed, use read()
to read data from the file. The following shows the syntax for read()
:
fs.read(fd, buffer, offset, length, position, callback)
The fd
parameter is the file descriptor returned by openSync()
. The buffer parameter specifies the Buffer
object that data will be read into from the file. The offset
parameter specifies the index in the buffer to begin reading data; if you want to begin at the current index in the Buffer
, this value should be null
. The length
specifies the number of bytes to read; specifying null
reads until the end of the buffer. The position
argument specifies the position in the file to begin reading from; specifying null
for this value uses the current file position.
The callback
argument must be a function that can accept three parameters: error
, bytes
, and buffer
. The error
parameter is an error that occurred during the read, bytes
specifies the number of bytes read, and buffer
is the buffer with data populated from the read request.
Listing 6.7 illustrates implementing basic asynchronous reading to read chunks of data from a file. Notice that the callback specified in lines 16–18 in the open()
callback calls the readFruit()
function and passes the file descriptor. Also notice that the read()
callback specified in lines 5–13 also calls readFruit()
and passes the file descriptor. This ensures that the asynchronous read completes before executing another. Listing 6.7 Output shows the output of the code.
Listing 6.7 file_read_async.js
: Performing asynchronous reads from a file
01 var fs = require('fs'); 02 function readFruit(fd, fruits){ 03 var buf = new Buffer(5); 04 buf.fill(); 05 fs.read(fd, buf, 0, 5, null, function(err, bytes, data){ 06 if ( bytes > 0) { 07 console.log("read %dbytes", bytes); 08 fruits += data; 09 readFruit(fd, fruits); 10 } else { 11 fs.close(fd); 12 console.log ("Fruits: %s", fruits); 13 } 14 }); 15 } 16 fs.open('fruit.txt', 'r', function(err, fd){ 17 readFruit(fd, ""); 18 });
Listing 6.7 Output file_read_async.js
: Reading asynchronously from a file
C:ooks odech06 eading>node file_read_async.js read 5bytes read 5bytes read 5bytes read 5bytes read 5bytes read 2bytes Fruits: grapes banana orange apple
One of the best methods to use when reading large amounts of data from a file is the streaming method. This method opens the file as a Readable
stream. As discussed in Chapter 5, Readable
streams can easily be implemented and linked to Writable
streams using the pipe()
method. This makes it easy to read data from a file and inject it into a Writable
stream source such as an HTTP response.
To stream data from a file asynchronously, you first need to create a Readable
stream object using the following syntax:
fs.createReadStream(path, [options])
The path
parameter specifies the path to the file. The path
can be relative or absolute. The optional options
parameter is an object that can contain encoding
, mode
, and flag
properties that define the string encoding as well as the mode and flags used when opening the file.
Once you have opened the Readable
file stream, you can easily read from it using the readable
event with read()
requests or by implementing a data
event handler as shown in Listing 6.8.
Listing 6.8 illustrates implementing a basic Readable
file stream. Notice that lines 4–7 implement a data
event handler that continuously reads data from the stream. Listing 6.8 Output shows the output of the code.
Listing 6.8 file_read_stream.js
: Implementing a Readable
stream to allow streaming reads from a file
01 var fs = require('fs'); 02 var options = { encoding: 'utf8', flag: 'r' }; 03 var fileReadStream = fs.createReadStream("grains.txt", options); 04 fileReadStream.on('data', function(chunk) { 05 console.log('Grains: %s', chunk); 06 console.log('Read %d bytes of data.', chunk.length); 07 }); 08 fileReadStream.on("close", function(){ 09 console.log("File Closed."); 10 });
Listing 6.8 Output file_read_stream.js
: Implementing streaming reads from a file
C:ooks odech06 eading>node file_read_stream.js Grains: oats rice wheat Read 16 bytes of data. File Closed.
In addition to reading and writing files, the fs
module also provides functionality for interacting with the file system—for example, listing files in a directory, looking at file information, and much more. The following sections cover the most common file system tasks that you may need to implement when creating Node.js applications.
Before doing any kind of read/write operation on a file or directory, you might want to verify whether the path exists. This can easily be done using one of the following methods:
fs.exists(path, callback) fs.existsSync(path)
The fs.existsSync(path)
returns true
or false
based on the path
existence. Just as with any other asynchronous file system call, if you use fs.exists()
, you need to implement a callback that is executed when the call completes. The callback
is passed a Boolean value of true
or false
depending on whether the path
exists. For example, the following code verifies the existence of a file named filesystem.js
in the current path and displays the results:
fs.exists('filesystem.js', function (exists) { console.log(exists ? "Path Exists" : "Path Does Not Exist"); });
Another common task is to get basic information about file system objects such as file size, the mode, modify time, whether the entry is a file or folder, and so on. This information can be obtained using one of the following calls:
fs.stats(path, callback) fs.statsSync(path)
The fs.statsSync()
method returns a Stats
object, whereas the fs.stats()
method is executed and the Stats
object is passed to the callback function as the second parameter. The first parameter is error
if an error occurs.
Table 6.2 lists some of the most commonly used attributes and methods attached to the Stats
object.
Table 6.2 Attributes and methods of Stats
objects for file system entries
Attribute/Method |
Description |
|
Returns |
|
Returns |
|
Returns |
|
Specifies the device ID on which the file is located |
|
Specifies the access mode of the file |
|
Specifies the number of bytes in the file |
|
Specifies the block size used to store the file in bytes |
|
Specifies the number of blocks the file is taking on disk |
|
Specifies the time the file was last accessed |
|
Specifies the time the file was last modified |
|
Specifies the time the file was created |
Listing 6.9 illustrates the use of the fs.stats()
call by making the call and then outputting the results of the object as a JSON string as well as using the isFile()
, isDirector()
, and isSocket()
calls, as shown in Listing 6.9 Output.
Listing 6.9 file_stats.js
: Implementing an fs.stats()
call to retrieve information about a file
01 var fs = require('fs'); 02 fs.stat('file_stats.js', function (err, stats) { 03 if (!err){ 04 console.log('stats: ' + JSON.stringify(stats, null, ' ')); 05 console.log(stats.isFile() ? "Is a File" : "Is not a File"); 06 console.log(stats.isDirectory() ? "Is a Folder" : "Is not a Folder"); 07 console.log(stats.isSocket() ? "Is a Socket" : "Is not a Socket"); 08 stats.isDirectory(); 09 stats.isBlockDevice(); 10 stats.isCharacterDevice(); 11 //stats.isSymbolicLink(); //only lstat 12 stats.isFIFO(); 13 stats.isSocket(); 14 } 15 });
Listing 6.9 Output file_stats.js
: Displaying information about a file
C:ooks odech06>node file_stats.js stats: { "dev": 818973644, "mode": 33206, "nlink": 1, "uid": 0, "gid": 0, "rdev": 0, "ino": 1970324837052284, "size": 535, "atime": "2016-09-14T18:03:26.572Z", "mtime": "2013-11-26T21:51:51.148Z", "ctime": "2014-12-18T17:30:43.340Z", "birthtime": "2016-09-14T18:03:26.572Z" } Is a File Is not a Folder Is not a Socket
Another common task when working with the file system is listing files and folders in a directory. For example, you might want to determine whether the files and folders need to be cleaned up, you might need to dynamically operate on the directory structure, and so on.
To access the files in the file system, use one of the following commands to read a list of entries:
fs.readdir(path, callback) fs.readdirSync(path)
If readdirSync()
is called, an array of strings representing the entry names in the specified path
is returned. In the case of readdir()
, the list is passed as the second parameter to the callback
function and an error, if there is one, is passed as the first.
To illustrate the use of readdir()
, Listing 6.10 implements a nested callback chain to walk the directory structure and output the entries. Notice that the callback function implements a wrapper to provide closure for the fullPath
variable, and that the WalkDirs()
function loops by being called by the asynchronous callback function, as shown in Listing 6.10 Output.
Listing 6.10 file_readdir.js
: Implementing a callback chain to walk down and output the contents of a directory structure
01 var fs = require('fs'); 02 var Path = require('path'); 03 function WalkDirs(dirPath){ 04 console.log(dirPath); 05 fs.readdir(dirPath, function(err, entries){ 06 for (var idx in entries){ 07 var fullPath = Path.join(dirPath, entries[idx]); 08 (function(fullPath){ 09 fs.stat(fullPath, function (err, stats){ 10 if (stats.isFile()){ 11 console.log(fullPath); 12 } else if (stats.isDirectory()){ 13 WalkDirs(fullPath); 14 } 15 }); 16 })(fullPath); 17 } 18 }); 19 } 20 WalkDirs("../ch06");
Listing 6.10 Output file_readdir.js
: Iteratively walking the directory structure using chained asynchronous callbacks
C:ooks odech06>node file_readdir.js ../ch06 ..ch06file_readdir.js ..ch06filesystem.js ..ch06data ..ch06file_stats.js ..ch06file_folders.js ..ch06 enamed ..ch06 eading ..ch06writing ..ch06dataconfig.txt ..ch06datafolderA ..ch06datagrains.txt ..ch06datafruit.txt ..ch06 eadingfile_read.js ..ch06dataveggie.txt ..ch06datalog.txt ..ch06dataoutput.txt ..ch06writingfile_write.js ..ch06 eadingfile_read_async.js ..ch06 eadingfile_read_sync.js ..ch06 eadingfile_read_stream.js ..ch06writingfile_write_async.js ..ch06writingfile_write_stream.js ..ch06writingfile_write_sync.js ..ch06datafolderAfolderC ..ch06datafolderAfolderB ..ch06datafolderAfolderBfolderD ..ch06datafolderAfolderCfolderE
Another common task when working with files is deleting them to clean up data or make more room on the file system. To delete a file from Node.js, use one of the following commands:
fs.unlink(path, callback) fs.unlinkSync(path)
The unlinkSync(path)
returns true
or false
based on whether the delete is successful. The asynchronous unlink()
call passes back an error value to the callback function if an error is encountered when deleting the file.
The following code snippet illustrates the process of deleting a file named new.txt
using the unlink()
asynchronous fs
call:
fs.unlink("new.txt", function(err){ console.log(err ? "File Delete Failed" : "File Deleted"); });
Truncating a file means reducing the size of the file by setting the end to a smaller value than the current size. You might want to truncate a file that grows continuously but does not contain critical data, such as a temporary log. To truncate a file, use one the following fs
calls and pass in the number of bytes you want the file to contain when the truncation completes:
fs.truncate(path, len, callback) fs.truncateSync(path, len)
The truncateSync(path)
returns true
or false
based on whether the file is successfully truncated. The asynchronous truncate()
call passes an error value to the callback function if an error is encountered when truncating the file.
The following code snippet illustrates the process of truncating a file named log.txt
to zero bytes.
fs.truncate("new.txt", function(err){ console.log(err ? "File Truncate Failed" : "File Truncated"); });
At times you may need to implement a directory structure for files being stored by your Node.js application. The fs
module provides the functionality to add and remove directories as necessary.
To add a directory from Node.js, use one of the following fs
calls. The path can be absolute or relative. The optional mode parameter allows you to specify the access mode for the new directory.
fs.mkdir(path, [mode], callback) fs.mkdirSync(path, [mode])
The mkdirSync(path)
returns true
or false
based on whether the directory is successfully created. The asynchronous mkdir()
call passes an error value to the callback
function if an error is encountered when creating the directory.
Keep in mind that when using the asynchronous method, you need to wait for the callback for the creation of the directory before creating a subdirectory. The following code snippet shows how to chain the creation of a subdirectory structure together:
fs.mkdir("./data/folderA", function(err){ fs.mkdir("./data/folderA/folderB", function(err){ fs.mkdir("./data/folderA/folderB/folderD", function(err){ }); }); fs.mkdir("./data/folderA/folderC", function(err){ fs.mkdir("./data/folderA/folderC/folderE", function(err){ }); }); });
To delete a directory from Node.js, use one of the following fs
calls. The path can be absolute or relative.
fs.rmdir(path, callback) fs.rmdirSync(path)
The rmdirSync(path)
returns true
or false
based on whether the directory is successfully deleted. The asynchronous rmdir()
call passes an error value to the callback function if an error is encountered when deleting the directory.
Just as with the mkdir()
calls, keep in mind that when using the asynchronous method, you need to wait for the callback of the deletion of the directory before deleting the parent directory. The following code snippet shows how to chain the deletion of a subdirectory structure together:
fs.rmdir("./data/folderA/folderB/folderC", function(err){ fs.rmdir("./data/folderA/folderB", function(err){ fs.rmdir("./data/folderD", function(err){ }); }); fs.rmdir("./data/folderA/folderC", function(err){ fs.rmdir("./data/folderE", function(err){ }); }); });
You might also need to rename files and folders in your Node.js application to make room for new data, archive old data, or apply changes made by a user. Renaming files and folders uses the fs
calls shown here:
fs.rename(oldPath, newPath, callback) fs.renameSync(oldPath, newPath)
The oldPath
specifies the existing file or directory path, and the newPath
specifies the new name. The renameSync(path)
returns true
or false
based on whether the file or directory is successfully renamed. The asynchronous rename()
call passes an error value to the callback function if an error is encountered when renaming the file or directory.
The following code snippet illustrates implementing fs
calls to rename a file named old.txt
to new.txt
and a directory named testDir
to renamedDir
:
fs.rename("old.txt", "new.txt", function(err){ console.log(err ? "Rename Failed" : "File Renamed"); }); fs.rename("testDir", "renamedDir", function(err){ console.log(err ? "Rename Failed" : "Folder Renamed"); });
Although not entirely stable, the fs
module provides a useful tool to watch a file and execute a callback function when the file changes. This can be useful if you want to trigger events to occur when a file is modified, but do not want to continually poll from your application directly. This does incur some overhead in the underlying OS, so you should use watches sparingly.
To implement a watch on a file, use the following command passing the path
to the file you want to watch. You can also pass in options
, which is an object that contains persistent
and interval
properties. The persistent
property is true
if you want the process to continue to run as long as files are being watched. The interval
property specifies the time in milliseconds that you want the file to be polled for changes:
fs.watchFile(path, [options], callback)
When a file change occurs, the callback
function is executed and passes a current and previous Stats
object.
The following code example monitors a file named log.txt
at an interval of every 5 seconds and uses the Stats
object to output the current and previous times the file was modified:
fs.watchFile("log.txt", {persistent:true, interval:5000}, function (curr, prev) { console.log("log.txt modified at: " + curr.mtime); console.log("Previous modification was: " + prev.mtime); });
Node.js provides the fs
module that allows you to interact with the file system. The fs
module allows you to create, read, and modify files. You can also use the fs
module to navigate the directory structure, look at information about files and folders, and change the directory structure by deleting and renaming files and folders.
3.145.118.87