Node js file creation. Nodejs
File operations are nothing new to JavaScript - JScript, built into Windows, has a full set of functions for working with disk. Node, due to its asynchronous nature, somewhat complicates these generally trivial tasks.
I would like to immediately warn you about one possible error. If you, like me, run Node in a virtual machine from a shared folder, remember that the VM cannot write to this folder. Attempts to create or add files in it will only result in Error: Permission denied
Opening a file
Accessing files on disk is a slow operation. It is on average tens of thousands of times longer than accessing RAM. Therefore, most file operations are asynchronous. All operations with the file system are collected in a built-in module fs, so let's start with connecting it.
Var fs = require("fs"), sys = require("sys");
Module sys we need it to output information to the console. In subsequent examples I will omit these lines so as not to repeat myself.
Opening a file is done like this:
Fs.open( <путь> , <флаги> , <режим доступа> , <функция-обработчик> )
- Path to the file. Relative to the running script or absolute.
- Flag— file access mode. Can take the following values:
- r - read only, pointer at the beginning of the file
- r+ - read and write, pointer at the beginning of the file
- w - record only, pointer at the beginning of the file
- w+ - write and read, pointer at the beginning of the file
- a - record, pointer at the end of the file
- a+ - write and read, pointer at the end of the file
- Access mode used if the file being opened does not exist. In this case, a new empty file with the specified mode will be created. The notation is standard for UNIX - for example 0664
- Handler— a function that will be executed when opening/creating a file. An error flag and a file descriptor are passed as arguments.
For example:
Fs.open("readme.txt", "r+", 0644, function(err, file_handle) ( if (!err) ( // Open file operations ) else ( // Error handling ) ));
Write to file
To write to a file, use the fs.write method:
Fs.write( <дескриптор> , <данные> , <позиция> , <кодировка> , <обработчик> )
- Descriptor file received in fs.open .
- Data which we write down. Objects here will be cast to string type.
- Position, from which recording begins. Null means writing from the current position.
- Encoding, in which the data will be recorded. May be " ascii«, « utf8" And " raw«
- Handler— a function that will be executed after recording. Arguments - error flag and number of bytes written
Let's expand the previous example by writing a string :)
Fs.open("readme.txt", "a", 0644, function(err, file_handle) ( if (!err) ( // Write the phrase "Copyrighted by Me" // at the end of the readme.txt file when opening in mode The "a" pointer is already at the end of the file, and we pass null // as position fs.write(file_handle, "Copyrighted by Me", null, "ascii", function(err, written) ( if (!err) ( / / Everything went well ) else ( // An error occurred while writing ) )); ) else ( // Handling errors when opening ) ));
Reading from a file
Reading is done like this:
Fs.read( <дескриптор> , <длина> , <позиция> , <кодировка> , <обработчик> )
Everything here is almost the same as in fs.write .
- Descriptor file received in fs.open
- Length data we plan to read
- Position, with which we begin to read. Null - from the current position
- Encoding, in which the data is read. May be " ascii«, « utf8" And " raw". It's better not to make mistakes here)
- Handler- a function that will be executed after reading. Arguments - error flag, data, number of bytes read
Reading from a file is a very simple process:
Fs.open("readme.txt", "r", 0644, function(err, file_handle) ( if (!err) ( // Read 10 kilobytes from the beginning of the file, in ascii fs.read(file_handle, 10000, null, "ascii", function(err, data) ( if (!err) ( // Everything went well, print what we read to the console sys.puts(data); ) else ( // An error occurred while reading ) )); ) else ( // Handling errors when opening a file ) ));
After reading/writing is completed, the file must be closed. Node can serve many clients at the same time, so it is better to release resources immediately when they are no longer needed.
Fs.open("readme.txt", "r", 0644, function(err, file_handle) ( if (!err) ( // Read 10 kilobytes from the beginning of the file, in ascii fs.read(file_handle, 10000, null, "ascii", function(err, data) ( if (!err) ( // Everything went well, print what we read to the console sys.puts(data); fs.close(file_handle); ) else ( // An error occurred while reading ) )); ) else ( // Handling errors when opening a file ) ));
The second argument of fs.close can take a callback function, to which an exception is passed in case of an error.
All of the functions listed have synchronous options. Sync is added to their name and they do not take a handler function as the last argument, but simply return the corresponding value (or throw an exception). Note that readSync returns an array of data and the number of bytes read.
Var file_handle = fs.openSync("readme.txt", "r", 0644); var data = fs.readSync(file_handle, 10000, null, "ascii"); sys.puts(data); fs.closeSync(file_handle);
Hi all! In this article, we'll look at how to write and read files in NodeJS.
To do this we will need to use the FS(file system) module. var fs =require(`fs`)-
To demonstrate reading the contents of files, let's create a file called readme.txt.
Video: node.js » fs module » writing to file
// contents of the readme.txt file
Here is some content of the file
var text = fs.readFileSync(`readme.txt`,`utf8`)-
console.log(text)-
We use a method in which we pass the file name as the first parameter, and the encoding as the second. As the name suggests, this method is synchronous. This means that all the code that follows will only be executed when the entire file has been read. Then we simply write the received data into a variable, which we then display on the screen.
Video: Node.js - creating an Excel file using a template
Now let's try to write the contents of the file we read into a new file.
To do this, we will write the following:
fs.writeFileSync(`writeme.txt`, text)-
Now, after running the code, you will see that a new file has been created called writeme.txt, which will contain the content written to the text variable from the readme.txt file.
Video: Node.JS Basics. 2. Working with files
Let's look at how to use methods asynchronously.
For example, let's look at the readme.txt file:
console.log(data)-
})-
console.log(`will be output before the data from the file`)-
The usage is almost the same, but now we also pass the function as the third parameter, where the first argument is the error, and the second is the contents of the file, which we then output.
Below I wrote another text output to show you that the method is indeed asynchronous, so while the file is being read, the code below will be executed, and only then the text from the file will be output.
Video: Working with files, fs module
Now let's read the contents of the readme.txt file again and write it to the writeme.txt file, but this time asynchronously.
fs.readFile(`readme.txt`,`utf8`,function(error, data)(
fs.writeFile(`writeme.txt`, data)-
})-
And that's all for me today. Thank you for your attention!
(No ratings yet)Today, in the ninth part of the translation of the Node.js guide, we will talk about working with files. In particular, we will talk about the fs and path modules - about file descriptors, about paths to files, about obtaining information about files, about reading and writing them, about working with directories.
Working with File Descriptors in Node.js
Before you can interact with files residing on your server's file system, you need to obtain a file handle.
The handle can be obtained by using the asynchronous open() method from the fs module to open the file:
Const fs = require("fs") fs.open("/Users/flavio/test.txt", "r", (err, fd) => ( //fd is a file descriptor ))
Note the second parameter, r, used when calling the fs.open() method. This is a flag that tells the system that the file is being opened for reading. Here are some other flags that are often used when working with this and some other methods:
- r+ - open a file for reading and writing.
- w+ - open a file for reading and writing, setting the stream pointer to the beginning of the file. If the file does not exist, it is created.
- a - open a file for writing, setting the stream pointer to the end of the file. If the file does not exist, it is created.
- a+ - open a file for reading and writing, setting the stream pointer to the end of the file. If the file does not exist, it is created.
Files can also be opened using the synchronous fs.openSync() method, which, instead of providing a file descriptor in the callback, returns it:
Const fs = require("fs") try ( const fd = fs.openSync("/Users/flavio/test.txt", "r") ) catch (err) ( console.error(err) )
After receiving the descriptor using any of the methods described above, you can perform the necessary operations with it.
File data
Each file is associated with a set of data about it; you can explore this data using Node.js. In particular, this can be done using the stat() method from the fs module.
Call this method, passing it the path to the file, and after Node.js has the necessary information about the file, it will call the callback passed to the stat() method. This is what it looks like:
Const fs = require("fs") fs.stat("/Users/flavio/test.txt", (err, stats) => ( if (err) ( console.error(err) return ) //file information contained in the `stats` argument))
Node.js has the ability to synchronously retrieve file information. With this approach, the main thread is blocked until the file properties are retrieved:
Const fs = require("fs") try ( const stats = fs.statSync ("/Users/flavio/test.txt") ) catch (err) ( console.error(err) )
Information about the file will go into the stats constant. What kind of information is this? In fact, the corresponding object provides us with a large number of useful properties and methods:
- The .isFile() and .isDirectory() methods allow you to find out, respectively, whether the file being examined is a regular file or a directory.
- The .isSymbolicLink() method allows you to find out whether a file is a symbolic link.
- The file size can be found using the .size property.
There are other methods, but these are the most commonly used. Here's how to use them:
Const fs = require("fs") fs.stat("/Users/flavio/test.txt", (err, stats) => ( if (err) ( console.error(err) return ) stats.isFile() //true stats.isDirectory() //false stats.isSymbolicLink() //false stats.size //1024000 //= 1MB ))
File paths in Node.js and the path module
The path to a file is the address of the location in the file system where it is located.
On Linux and macOS the path might look like this:
/users/flavio/file.txt
On Windows the paths look a little different:
C:usersflaviofile.txt
Differences in path recording formats when using different operating systems should be taken into account, taking into account the operating system used to deploy the Node.js server.
Node.js has a standard path module designed to work with file paths. Before using this module in the program, it must be connected:
▍Getting information about the path to a file
If you have a path to a file, then, using the capabilities of the path module, you can find out details about this path in a form convenient for perception and further processing. It looks like this:
Const notes = "/users/flavio/notes.txt" path.dirname(notes) // /users/flavio path.basename(notes) // notes.txt path.extname(notes) // .txt
Here, in the notes line, the path to the file is stored. The following methods of the path module are used to parse the path:
- dirname() - returns the parent directory of the file.
- basename() - returns the file name.
- extname() - returns the file extension.
You can find out the file name without an extension by calling the .basename() method and passing it a second argument representing the extension:
Path.basename(notes, path.extname(notes)) //notes
▍Working with file paths
Multiple path parts can be joined using the path.join() method:
Const name = "flavio" path.join("/", "users", name, "notes.txt") //"/users/flavio/notes.txt"
You can find the absolute path of a file based on its relative path using the path.resolve() method:
Path.resolve("flavio.txt") //"/Users/flavio/flavio.txt" when running from my home folder
In this case, Node.js simply adds /flavio.txt to the path leading to the current working directory. When calling this method, if you pass another parameter representing the path to the folder, the method uses it as a basis for determining the absolute path:
Path.resolve("tmp", "flavio.txt") // "/Users/flavio/tmp/flavio.txt" when running from my home folder
If the path passed as the first parameter begins with a slash, that means it is an absolute path.
Path.resolve("/etc", "flavio.txt") // "/etc/flavio.txt"
Here's another useful method - path.normalize() . It allows you to find the actual path of a file using a path that contains relative path specifiers such as a dot (.), two dots (..), or two forward slashes:
Path.normalize("/users/flavio/..//test.txt") // /users/test.txt
The resolve() and normalize() methods do not check for the existence of a directory. They simply find a path based on the data given to them.
Reading files in Node.js
The simplest way to read files in Node.js is to use the fs.readFile() method, passing it the file path and a callback that will be called passing it the file data (or an error object):
Fs.readFile("/Users/flavio/test.txt", (err, data) => ( if (err) ( console.error(err) return ) console.log(data) ))
If necessary, you can use the synchronous version of this method - fs.readFileSync() :
Const fs = require("fs") try ( const data = fs.readFileSync("/Users/flavio/test.txt") console.log(data) ) catch (err) ( console.error(err) )
By default, when reading files, the encoding is utf8, but you can set the encoding yourself by passing the appropriate parameter to the method.
The fs.readFile() and fs.readFileSync() methods read the entire contents of a file into memory. This means that working with large files using these methods will seriously impact your application's memory consumption and performance. If you need to work with such files, it is best to use streams.
Writing files in Node.js
In Node.js, the easiest way to write files is using the fs.writeFile() method:
Const fs = require("fs") const content = "Some content!" fs.writeFile("/Users/flavio/test.txt", content, (err) => ( if (err) ( console.error(err) return ) //file written successfully ))
There is also a synchronous version of the same method - fs.writeFileSync() :
Const fs = require("fs") const content = "Some content!" try ( const data = fs.writeFileSync("/Users/flavio/test.txt", content) //file written successfully ) catch (err) ( console.error(err) )
These methods, by default, replace the contents of existing files. You can change their standard behavior by using the corresponding flag:
Fs.writeFile("/Users/flavio/test.txt", content, ( flag: "a+"), (err) => ())
The flags that we have already listed in the section on descriptors can be used here. Details about the flags can be found.
Attaching data to a file
The fs.appendFile() method (and its synchronous version, fs.appendFileSync()) is useful for appending data to the end of a file:
Const content = "Some content!" fs.appendFile("file.log", content, (err) => ( if (err) ( console.error(err) return ) //done! ))
About using threads
Above, we described methods that, when writing to a file, write the entire amount of data transferred to it, after which, if their synchronous versions are used, they return control to the program, and if asynchronous versions are used, they call callbacks. If you are not satisfied with this state of affairs, it would be better to use streams.
Working with directories in Node.js
The fs module provides the developer with many convenient methods that can be used to work with directories.
▍Checking the existence of a folder
To check if a directory exists and if Node.js can access it given permissions, you can use the fs.access() method.
▍Creating a new folder
In order to create new folders, you can use the fs.mkdir() and fs.mkdirSync() methods:
Const fs = require("fs") const folderName = "/Users/flavio/test" try ( if (!fs.existsSync(dir))( fs.mkdirSync(dir) ) ) catch (err) ( console.error( err) )
▍Reading the contents of a folder
To read the contents of a folder, you can use the fs.readdir() and fs.readdirSync() methods. This example reads the contents of a folder—that is, what files and subdirectories it contains—and returns their relative paths:
Const fs = require("fs") const path = require("path") const folderPath = "/Users/flavio" fs.readdirSync(folderPath)
This is how you can get the full path to the file:
Fs.readdirSync(folderPath).map(fileName => ( return path.join(folderPath, fileName) )
The results can be filtered to return only files and exclude directories from the output:
Const isFile = fileName => ( return fs.lstatSync(fileName).isFile() ) fs.readdirSync(folderPath).map(fileName => ( return path.join(folderPath, fileName)).filter(isFile) )
▍Renaming a folder
To rename a folder, you can use the fs.rename() and fs.renameSync() methods. The first parameter is the current folder path, the second is the new one:
Const fs = require("fs") fs.rename("/Users/flavio", "/Users/roger", (err) => ( if (err) ( console.error(err) return ) // done ) )
You can also rename a folder using the synchronous fs.renameSync() method:
Const fs = require("fs") try ( fs.renameSync("/Users/flavio", "/Users/roger") ) catch (err) ( console.error(err) )
▍Deleting a folder
In order to delete a folder, you can use the fs.rmdir() or fs.rmdirSync() methods. It should be noted that deleting a folder that contains something is a slightly more difficult task than deleting an empty folder. If you need to remove such folders, use the fs-extra package, which is quite popular and well supported. It is a replacement for the fs module, expanding its capabilities.
The remove() method from the fs-extra package can remove folders that already have something in them.
You can install this module like this:
Npm install fs-extra
Here is an example of its use:
Const fs = require("fs-extra") const folder = "/Users/flavio" fs.remove(folder, err => ( console.error(err) ))
Its methods can be used as promises:
Fs.remove(folder).then(() => ( //done )).catch(err => ( console.error(err) ))
It is also possible to use the async/await construct:
Async function removeFolder(folder) ( try ( await fs.remove(folder) // done ) catch (err) ( console.error(err) ) ) const folder = "/Users/flavio" removeFolder(folder)
fs module
Above we have already encountered some methods of the fs module used when working with the file system. In fact, it contains a lot more useful things. Let us remind you that it does not require installation; in order to use it in the program, you just need to connect it:
Const fs = require("fs")
After this, you will have access to its methods, among which we note the following, some of which are already familiar to you:
- fs.access() : Checks if a file exists and can be accessed based on permissions.
- fs.appendFile() : Appends data to a file. If the file does not exist, it will be created.
- fs.chmod() : Changes the permissions for the given file. Similar methods: fs.lchmod() , fs.fchmod() .
- fs.chown() : Changes the owner and group for the given file. Similar methods: fs.fchown() , fs.lchown() .
- fs.close() : Closes a file handle.
- fs.copyFile() : Copies a file.
- fs.createReadStream() : Creates a file reading stream.
- fs.createWriteStream() : Creates a file write stream.
- fs.link() : Creates a new hard link to a file.
- fs.mkdir() : Creates a new directory.
- fs.mkdtemp() : Creates a temporary directory.
- fs.open() : Opens a file.
- fs.readdir() : Reads the contents of a directory.
- fs.readFile() : Reads the contents of a file. Similar method: fs.read() .
- fs.readlink() : Reads the value of a symbolic link.
- fs.realpath() : Allows a relative file path constructed using symbols. and.., all the way.
- fs.rename() : Renames a file or folder.
- fs.rmdir() : Deletes a folder.
- fs.stat() : Returns file information. Similar methods: fs.fstat() , fs.lstat() .
- fs.symlink() : Creates a new symbolic link to a file.
- fs.truncate() : Truncates the file to the specified length. Similar method: fs.ftruncate() .
- fs.unlink() : Removes a file or symbolic link.
- fs.unwatchFile() : Disables file change watching.
- fs.utimes() : Changes the timestamp of a file. Similar method: fs.futimes() .
- fs.watchFile() : Enables watching for file changes. Similar method: fs.watch() .
- fs.writeFile() : Writes data to a file. Similar method: fs.write() .
An interesting feature of the fs module is the fact that all its methods are asynchronous by default, but there are also synchronous versions of them, the names of which are obtained by adding the word Sync to the names of the asynchronous methods.
For example:
- fs.rename()
- fs.renameSync()
- fs.write()
- fs.writeSync()
The use of synchronous methods has a serious impact on how the program works.
Node.js 10 has experimental support for these promise-based APIs.
Let's explore the fs.rename() method. Here is an asynchronous version of this method using callbacks:
Const fs = require("fs") fs.rename("before.json", "after.json", (err) => ( if (err) ( return console.error(err) ) //done ))
When using its synchronous version, a try/catch construct is used to handle errors:
Const fs = require("fs") try ( fs.renameSync("before.json", "after.json") //done ) catch (err) ( console.error(err) )
The main difference between these options for using this method is that in the second case, script execution will block until the file operation is completed.
path module
The path module, some of whose capabilities we have already discussed, contains many useful tools that allow you to interact with the file system. As already said, there is no need to install it since it is part of Node.js. In order to use it, you just need to connect it:
Const path = require("path")
The path.sep property of this module provides the character used to separate path segments (; on Windows and / on Linux and macOS), and the path.delimiter property provides the character used to separate multiple paths (; on Windows and: on Linux and macOS).
Let's look at and illustrate with examples some methods of the path module.
▍path.basename()
Returns the last fragment of the path. By passing the second parameter to this method, you can remove the file extension.
Require("path").basename("/test/something") //something require("path").basename("/test/something.txt") //something.txt require("path").basename ("/test/something.txt", ".txt") //something
▍path.dirname()
Returns the part of the path that represents the directory name:
Require("path").dirname("/test/something") // /test require("path").dirname("/test/something/file.txt") // /test/something
▍path.extname()
Returns the part of the path that represents the file extension: