Basic IO Operations in Node.js

Basic IO Operations in Node.js

·

3 min read

stdin, stdout, stderr

Below code shows how to use stdin, stdout and stderr in nodejs.

process.stdin.on("data", (data) => {
    const name = data.toString().trim();
    if (name !== "") {
        process.stdout.write("name: " + name + "\n");
    } else {
        process.stderr.write("invalid name");
        process.exit();
    }
});

Let's see the process.

$ node index.js
Tom
name: Tom
Jack
name: Jack

File Read/Write Sync

The most simple way to read/write file is to use the readFileSync and writeFileSync api.

const fs = require("fs");

let contents1 = fs.readFileSync("hello.txt", { encoding: "utf-8" });
console.log(contents1.toString());

fs.writeFileSync("hello.txt", "write to hello file", { encoding: "utf8" });

let contents2 = fs.readFileSync("hello.txt", { encoding: "utf-8" });
console.log(contents2.toString());

File Read/Write Callback Async

Callback is the traditional way for nodejs to handle async operations.

const fs = require("fs");

fs.readFile("hello.txt", { encoding: "utf-8" }, (err, contents) => {
    if (err) {
        console.error(err);
    } else {
        console.log(contents.toString());

        fs.writeFile( "hello.txt", "write to hello file", { encoding: "utf-8" }, (err) => {
                if (err) {
                    console.error(err);
                } else {

                    fs.readFile( "hello.txt", { encoding: "utf-8" }, (err, contents) => {
                            if (err) {
                                console.error(err);
                            } else {
                                console.log(contents.toString());
                            }
                        }
                    );
                }
            }
        );
    }
});

As you can see, it is pretty long for integrate several callbacks together.

File Read/Write Promise Async

Promise is the most recommended way to handle async operations.

const fs = require("fs").promises;

Promise.resolve()
    .then(() => {
        return fs.readFile("hello.txt", { encoding: "utf8" });
    })
    .then((contents) => {
        console.log(contents.toString());
    })
    .then(() => {
        fs.writeFile("hello.txt", "write to hello file", { encoding: "utf-8" });
    })
    .then(() => {
        return fs.readFile("hello.txt", { encoding: "utf-8" });
    })
    .then((contents) => {
        console.log(contents.toString());
    })
    .catch((err) => {
        console.error(err);
    });

As you can see, we have 3 type api for handling file IO in nodejs: the sync api, the callback-based async api and the promised-based async api. In nodejs, a lot of apis have these 3 types. For async operations, it is always recommended to use promise-based api.

Access File Metadata

const fs = require("fs").promises;

fs.stat("hello.txt")
    .then((stats) => {
        console.log(stats);
    })
    .catch((err) => {
        console.error(err);
    });
Stats {
  dev: 16777221,
  mode: 33188,
  nlink: 1,
  uid: 502,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 8637948036,
  size: 19,
  blocks: 8,
  atimeMs: 1658405488047.815,
  mtimeMs: 1658405486844.7258,
  ctimeMs: 1658405486844.7258,
  birthtimeMs: 1658404778790.4702,
  atime: 2022-07-21T12:11:28.048Z,
  mtime: 2022-07-21T12:11:26.845Z,
  ctime: 2022-07-21T12:11:26.845Z,
  birthtime: 2022-07-21T11:59:38.790Z
}

File Permissions And Access

In below code, we use fs.chmod to change file permissions and fs.access to test it.

const fs = require("fs").promises;
const { constants } = require("fs");

Promise.resolve()
    .then(() => {
        return fs.chmod("hello.txt", 0o000);
    })
    .then(() => {
        console.log("chmod success");
    })
    .catch(() => {
        console.error("chmod fail");
    })
    .then(() => {
        return fs.access("./hello.txt", constants.R_OK | constants.W_OK);
    })
    .then(() => {
        console.log("can access");
    })
    .catch(() => {
        console.error("cannot access");
    })
    .then(() => {
        return fs.chmod("hello.txt", 0o777);
    })
    .then(() => {
        console.log("chmod success");
    })
    .catch(() => {
        console.error("chmod fail");
    })
    .then(() => {
        return fs.access("./hello.txt", constants.R_OK | constants.W_OK);
    })
    .then(() => {
        console.log("can access");
    })
    .catch(() => {
        console.error("cannot access");
    });
$ node index.js
chmod success
cannot access
chmod success
can access

Watch File

In nodejs, we can use fs.watch to watch file changes.

const fs = require("fs").promises;

(async () => {
    try {
        const watcher = fs.watch("hello.txt");
        for await (const event of watcher) console.log(event);
    } catch (err) {
        console.error(err);
    }
})();
$ node index.js
{ eventType: 'change', filename: 'hello.txt' }
{ eventType: 'change', filename: 'hello.txt' }
{ eventType: 'change', filename: 'hello.txt' }
{ eventType: 'change', filename: 'hello.txt' }
{ eventType: 'rename', filename: 'hello.txt' }