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: require("path").dirname("/test/something") // "" require("path").dirname("/test/something/file.txt") // ".txt"

▍path.isAbsolute()

Returns true if the path is absolute:

Require("path").isAbsolute("/test/something") // true require("path").isAbsolute("./test/something") // false

▍path.join()

Connects several parts of the path:

Const name = "flavio" require("path").join("/", "users", name, "notes.txt") //"/users/flavio/notes.txt"

▍path.normalize()

Tries to figure out the real path based on a path that contains characters used in constructing relative paths like. , .. And // :

Require("path").normalize("/users/flavio/..//test.txt") ///users/test.txt

▍path.parse()

Converts a path to an object whose properties represent the individual parts of the path:

  • root: root directory.
  • dir: path to the file, starting from the root directory
  • base: file name and extension.
  • name: file name.
  • ext: file extension.

Here is an example of using this method:

Require("path").parse("/users/test.txt")

The result of his work is the following object:

( root: "/", dir: "/users", base: "test.txt", ext: ".txt", name: "test" )

▍path.relative()

Accepts 2 paths as arguments. Returns the relative path from the first path to the second, based on the current working directory:

Require("path").relative("/Users/flavio", "/Users/flavio/test.txt") //"test.txt" require("path").relative("/Users/flavio", "/Users/flavio/something/test.txt") //"something/test.txt"

▍path.resolve()

Finds an absolute path based on the relative path passed to it:

Path.resolve("flavio.txt") //"/Users/flavio/flavio.txt" when running from my home folder.

Results

Today we looked at the Node.js fs and path modules, which are used to work with the file system. In the next part of this series, where it ends, we will discuss the os , events , http modules, talk about working with threads and working with database management systems in Node.js.

Dear readers! What npm packages do you use when working with the file system in Node.js?

The transition from synchronous to asynchronous code was considered. In the second part, I will look at the transition from byte-by-byte to line-by-line reading from a file. Since the operation of encoding from one encoding to another is quite trivial, I will talk a little more about the theoretical side of the issue.

Part 2: How to read a line from a file

Fs.readFile("large.txt", ( encoding: "utf8"), (err, data) => ( if (err) throw err; data.split("\n").forEach(line => ( doSomethingWithLine (line); )); ));

He is perhaps the fastest. But it also requires the most memory - from 100% to 200% of the file size. 200% is at the same time the most common case, since the memory encoding of the string is UTF-16 and therefore the size of the required memory is multiplied by two if the file contains mainly characters from the single-byte UTF-8 range.

Additionally, Node.js developers do not recommend loading a lot of data into a Node.js process (see What is the memory limit on a node process?). This is not done very elegantly - even if there is enough physical memory, when you try to download a file larger than 1Gb, an exception is thrown:

This.parent = new SlowBuffer(this.length); ^ RangeError: length > kMaxLength

If the file is smaller, you can get something like this:

FATAL ERROR: CALL_AND_RETRY_0 Allocation failed - process out of memory

All that remains is to process the file in parts. To do this, you need to read it in parts and Node.js provides at least 5 ways for this:

  1. Use “old” streams - open a stream and subscribe to the “data” event.
  2. Use "new" streams - subscribe to the "readable" event and use the read() method.
  3. Create your own WritableStream and send a file stream to it using the “pipe()” method.
  4. Use file descriptors and a set of open(), read(), close() methods.
  5. Use synchronous options - openSync(), readSync(), closeSync().

Options 1-3 are more elegant, since they operate with a convenient abstraction - a stream. This allows you to consider a program as a data flow diagram and use terms such as merging, splitting, and transformation when designing an architecture.

Also, options 1 and 2 differ in the ability to read characters from a file. In options 3 and 4, data from the file is written to a buffer and then must be converted to text.

// Option #1 - "old" streams var stream = fs.createReadStream(file, ( encoding: "utf8" )); stream.on("data", (_, data) => processData(data)); stream.on("end", done); // Option #2 - "new" streams var stream = fs.createReadStream(file, ( encoding: "utf8" )); stream.on("readable", () => processData(stream.read())); stream.on("end", done); // Option #3 - pipe var stream = fs.createReadStream(file, ( encoding: "utf8" )); var writeStream = new Writable(); writeStream._write = (chunk, encoding, callback) => ( processData(chunk); callback(); ); writeStream.on("end", done); stream.pipe(writeStream); // Option #4 - asynchronous fs methods fs.open(file, "r", (err, fd) => ( var buffer = new Buffer(1000*1000); (function next() ( fs.read(fd, buffer, 0, buffer.length, null, (err, bytesRead, buffer) => ( if (bytesRead === 0) ( fs.close(fd, done); ) else ( processData(buffer); next(); ) )); )()); ));

The more conceptual difference is in terms of retrieving data from a file. Options 1-2 receive the next fragment as soon as the current fragment's event handler completes. In the case of asynchronous code in the handler, the sequence of its execution is unpredictable:

Function processData(chunk) ( console.log("first") setImmediate(() => ( console.log("second"); setImmediate(() => console.log("third")); )); ) var stream = fs.createReadStream(file, ( encoding: "utf8" )); stream.on("readable", () => processData(stream.read())); ... first third second third first second ...

The situation can be corrected using the pause()/resume() methods.

Function processData(chunk, done) ( console.log("first") setImmediate(() => ( console.log("second"); setImmediate(() => ( console.log("third"); done( ); )); )); ) var stream = fs.createReadStream(file, ( encoding: "utf8" )); stream.on("readable", () => ( stream.pause(); processData(stream.read(), () => stream.resume()); )); ... first second third first second third ...

In options 3 and 4, the next fragment will be received only after transfer of control (option 3) or request (option 4).

I think that there is enough information to implement the createTextReader() function from the first part of the article. Of all the options, the fourth one is the most appropriate, since its control flow is similar to the interface (request-callback).

Function createTextReader(file, options, done) ( var length, encoding, separator; if ("function" === typeof options) ( done = options; options = ( ); ) length = 4 * 1024; encoding = options.encoding || "utf8"; separator = (options.separator || "\n"); fs.open(file, "r", (err, fd) => ( var eof, tail, buffer, decoder, lines; if (err) ( done(err); return; ) eof = false; buffer = new Buffer(length); tail = ""; lines = ; decoder = new StringDecoder(encoding); done(null, ( readLine: done => ( var line; if (lines.length > 0) ( line = lines.shift(); done(null, line); ) else if (eof) ( done(null, null); ) else ( (function read() ( fs.read(fd, buffer, 0, length, null, function (err, bytesRead, buffer) ( var index, position; if (bytesRead === 0) ( eof = true; done(null, tail); ) else ( tail = tail + decoder.write(buffer.slice(0, bytesRead)); index = -1; while (-1 !== (position = tail.indexOf(separator, index))) ( lines.push( tail.substring(index, position));index = position + separator.length; ) tail = tail.substring(index); if (lines.length === 0) ( read(); ) else ( line = lines.shift(); done(null, line); ) ) )); )()); ) ), close: done => ( fs.close(fd, () => ( if (done) ( done(err || null); ) )); ) )); )); )

Afterword

In two parts of this article, I tried to outline everything that was useful to me when creating the module https://github.com/AlexAtNet/async-read-lines. Unfortunately, a lot was left out of scope, and there was not enough time for everything. So if you find an error or typo, write in private messages. If you have questions about the topic of the article, I will be glad to answer in the comments. If you see bugs in the module, create a request in github issues. You can contact me personally through the website alexatnet.com.

Good luck in programming!

About the author: Alexander Netkachev is a senior developer in C# and F#. Maintains the website alexatnet.com, conducts webinars (Code&Coffe), helps novice developers with code (CodeReview4U).

Hi all! In this article we will look at, how to write and read files in NodeJS.

Platform NodeJS allows you to write and read files in the operating system. To do this we will need to use the module FS(file system).

Var fs = require("fs");

To demonstrate reading the contents of files, let's create a file called readme.txt.

// contents of the readme.txt file
Here is some file content

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.

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 with the name writeme.txt, which will contain the contents written to the variable text from file readme.txt.

Let's look at how to use methods asynchronously. For example, we consider the file readme.txt:


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.

Now let's count the file contents again readme.txt and write it to a file writeme.txt, but only now 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!







2024 gtavrl.ru.