• Read file default encoding is null, binary data, file does not exist will report an error
  • Write files are written in binary mode by default. If the file does not exist, the file is created, and if the file exists, the file is overwritten

readFileSync

Synchronous read

const read = fs.readFileSync(path.resolve(__dirname, 'name.txt'), 'utf8');
console.log(read); / / = > chapter three
Copy the code

writeFileSync

Synchronous write

fs.writeFileSync(path.resolve(__dirname, 'age.txt'), '18'.'utf8');
Copy the code

readFile

Asynchronous read

fs.readFile(path.resolve(__dirname, 'name.txt'), (err, data) = > {
    if (err) throw err;
    console.log(data.toString()); / / = > chapter three
})
Copy the code

writeFile

Asynchronous write

fs.writeFile(path.resolve(__dirname, 'age.txt'), '20'.err= > {
    if (err) throw err;
})
Copy the code

createReadStream

use

const fs = require('fs');
const path = require('path');

const rs = fs.createReadStream(path.resolve(__dirname, './number.txt'), {
    flags: 'r'.encoding: null.// mode: 0o66,// mode: 0o66
    autoClose: true.start: 0.end: 6.// read from index 0 to index 3, closed interval [0,6]
    highWaterMark: 3.// The number of bytes read each time,
})

rs.on('open'.(fd) = > {
    console.log(fd);
})

const arr = []
// When listening for data events, internal data is constantly sent
rs.on('data'.(thunk) = > {
    console.log(thunk);
    arr.push(thunk);
})

rs.on('end'.() = > {
    console.log(Buffer.concat(arr).toString()); / / = > 0123456
})

rs.on('close'.() = > {
    console.log('close');
})

//rs.pause() pauses reading
//rs.resume() can resume reading
Copy the code

Simple implementation

The main use is fs open, read

const EventEmitter = require('events');
const fs = require('fs');

class ReadStream extends EventEmitter {
    constructor(path, options) {
        super(a)// Read the file path
        this.path = path;
        //
        this.flags = options.flags || 'r';
        // Read the starting position of the index
        this.start = options.start || 0;
        // Read the end position of the index
        this.end = options.end || undefined;
        // The encoding format to read
        this.encoding = options.encoding || null;
        // Whether to automatically shut down
        this.autoClose = options.autoClose || true;
        // The number of characters read at a time
        this.hightWaterMark = options.hightWaterMark || 64 * 1024;
        / / the offset
        this.offset = 0;
        // Is the flow mode
        this.flowing = false;

        // Open the file
        this.open()

        // Listen to the user register data method
        this.on('newListener'.(type) = > {
            if (type === 'data') { // The user registered data
                this.flowing = true; // Set to flow
                // Start reading the file
                this._read()
            }
        })
    }

    // Open the file
    open() {
        fs.open(this.path, this.flags, (err, fd) = > {
            if (err) throw err;
            this.fd = fd;
            this.emit('open', fd); })}/ / read the file
    _read() {
        // Open file asynchronously, so we can't get fd at this time
        if (typeof this.fd ! = ='number') return this.once('open'.this._read);
        // Count the number of reads. If end has a value, count it through end and hightWaterMark
        // Start end is a closed interval, so +1
        const howMouchToRead = this.end ? Math.min(this.hightWaterMark, this.end - this.offset + 1) : this.hightWaterMark;

        const buffer = Buffer.alloc(howMouchToRead);
        // Start reading the file
        fs.read(this.fd, buffer, 0, howMouchToRead, this.offset, (err, bytesRead, buf) = > {
            if (err) return this.destroy(err);
            //bytesRead specifies the number of bytesRead
            if (bytesRead > 0) {
                // Send data to the registered data of the client
                this.emit('data', buf);
                this.offset += bytesRead;
                if (this.flowing) {
                    this._read(); }}else {
                // The reading is complete
                this.emit('end');
                this.destroy(); }})}// Start operation
    resume() {
        // Make sure it has been paused
        if (!this.flowing) {
            this.flowing = true;
            this._read(); }}// Pause the operation
    pause() {
        this.flowing = false;
    }

    / / end
    destroy(err) {
        if (err) return this.emit('error', err);
        if (typeof this.fd === 'number' && this.autoClose) {
            fs.close(this.fd, () = > {
                this.emit('close'); })}}}module.exports = ReadStream;
Copy the code

createWriteStream

  • The process of writing is sorted, so when you start writing, you write the first one, you put the rest in the linked list, you wait for the first one to complete, you take the first one out of the linked list and then you write it
  • HighWaterMark: How many bytes do I expect to use to complete the write operation? If it exceeds the value of write, the return value of write will be false. The return value of write will be false for judgment

Simple to use

const path = require('path');
const fs = require('fs');

const ws = fs.createWriteStream(path.resolve(__dirname, './copy.txt'), {
    flags: 'w'.encoding: 'utf8'.mode: 0o666.autoClose: true.emitClose: true.start: 0.highWaterMark: 3
});

// Note that the return value of write is false if the number of characters written >=highWaterMark value
// In the following process, the 0 in 012 is actually written for the first time, and the 12 is put into the list to wait for the 0 to complete
// Take the first 1 from the list and continue writing, and so on, until you are done. Here the second r returns false because 012 is
//3 characters >= 3 of highWaterMark
let r = ws.write('01'.(err) = > {
    if (err) throw err;
})
console.log(r); //=>true

r = ws.write('2'.(err) = > {
    if (err) throw err;
})
console.log(r); //=>false
Copy the code

You want to write 10 numbers (0-9) with only one byte of memory

const fs = require('fs');
const path = require('path');

const ws = fs.createWriteStream(path.resolve(__dirname, './copy.txt'), {
    flags: 'w'.encoding: 'utf8'.mode: 0o666.autoClose: true.emitClose: true.start: 0.highWaterMark: 1
})

let index = 0;

function write() {
    let writting = true;
    while (index < 10) {
        // The value cannot be of type number, otherwise it will return an error
        writting = ws.write(`${index++}`);
        if(! writting) {break; }}if (index === 10) {
        ws.end(); // Close is emitted after end, and end will no longer emit drain. If end is commented out, 10 drains will be printed, and if uncommented out, 9 drains and a close will be printed
        // ws.end('yy'); End =write+close}}// The drain event is emitted when the number of writes reaches the expected value or exceeds the highWaterMark before being consumed
ws.on('drain'.() = > {
    console.log('drain');
    write();
})

ws.on('close'.() = > {
    console.log('close');
})

/ / execution
write();
Copy the code

Realize the writeStream

The main use is fs open, write

const fs = require('fs');
const EventEmitter = require('events');

class WriteStream extends EventEmitter {
    constructor(path, options = {}) {
        super(a);this.path = path;
        this.flags = options.flags || 'w';
        this.encoding = options.encoding || 'utf8';
        this.mode = options.mode || 0o666;
        this.autoClose = options.autoClose || true;
        this.emitClose = options.emitClose || true;
        this.start = options.start || 0;
        this.highWaterMark = options.highWaterMark || 16 * 1024;

        this.offset = 0;
        // It is not writing by default. The first call to write requires the fs.write method
        this.writting = false;
        // Indicates the length to be written
        this.len = 0;
        // Whether the drain event is emitted
        this.needDrain = false;
        / / cache
        this.cache = [];

        // Open the file
        this.open();

    }

    open() {
        fs.open(this.path, this.flags, this.mode, (err, fd) = > {
            if (err) this.destory(err);
            this.fd = fd;
            this.emit('open', fd); })}write(chunk, encoding = this.encoding, cb = () => {}) {
        // What the user writes may be Chinese characters
        chunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
        // The length to write to
        this.len += chunk.length;
        // Returns the result if 
        const result = this.len < this.highWaterMark;
        // The reverse of the result returned
        this.needDrain = ! resultconst clearBuffer = () = > {
            this.clearBuffer();
            cb();
        }
        if (this.writting) {
            // Put the rest in the cache
            this.cache.push({
                chunk,
                encoding,
                clearBuffer
            })
        } else {
            // The first time it was actually written to the file
            this.writting = true;
            // Write for real
            this._write(chunk, encoding, clearBuffer);
        }

        return result;
    }

    _write(chunk, encoding, cb) {
        // Open is an asynchronous process, where fd is not available
        if (typeof this.fd ! = ='number') return this.once('open'.() = > this._write(chunk, encoding, cb));
        // Write process
        fs.write(this.fd, chunk, 0, chunk.length, this.offset, (err, written) = > {
            if (err) return this.destory(err);
            / / modify offset
            this.offset += written;
            / / modify len
            this.len -= written;
            // The cache must be cleared after the write is completecb(); })}clearBuffer() {
        // Retrieve a data from the cache
        const data = this.cache.shift();
        if (data) { // There is something in the cache
            // Continue writing data to the file
            this._write(data.chunk, data.encoding, data.clearBuffer);
        } else {
            // There is no more data in the cache
            this.writting = false;
            if (this.needDrain) {
                this.needDrain = false;
                this.emit('drain'); }}}destory(err) {
        if (err) this.emit('error', err); }}module.exports = WriteStream;
Copy the code