Search function implementation steps

1. Open the file

2. Trigger the newListener event and read the data in flowing mode

3. Data filtering Counts the number of times that the search content matches

  • Readable streams actually work in one of two modes: flowing and Paused
  • Under flowing mode, readable streams automatically read data from the underlying system and provided it to the application as quickly as possible through events from the EventEmitter interface.

A method is called

let SearchTime = require('./SearchTimes')
let reader = new SearchTime('./1.txt',{
    text:'good',// Search for content highWaterMark:30}) reader.on('searchTimes',(data)=>{// listen to searchTimes return file contents console.log(data)}) reader.on('end',data=>{// Listen to send return the number of files that meet the conditions console.log('count',data)
})

reader.on('error',(error)=>{
    console.log('error',error)
})
Copy the code

The Flowing mode instantiation of the createReadStream class

  • I’m going to introduce events, FS.

  • Define a SearchTimes class and inherit the Event module to add the properties passed in for later use of event subscription publications.

  • The newListener event is raised when a newListener is added to an object.

this.on('newListener', (type) = > {if(type= ='searchTimes'){// If you add searchTimes and listeners, the file content begins to be read in flowing mode this.read(); }})Copy the code

Implementing the read method

  • Check whether the file is open, if not, trigger a file open event.
  • Read several bytes at a time based on the position of the water mark and the size of the remaining content.
        lethowMuchToRead = this.end? Math.min(this.end-this.pos+1,this.highWaterMark):this.highWaterMarkCopy the code
  • Fs. read Reads the file.
  • The read is successful, and the searchTimes event is emitted to return the read.
  • And to read the content of the cumulative record.
  • If the end is not read or the passed end is greater than the file displacement, the read is complete and go to the next step.
  • Close the file and return the number of matches with the re filter.

Test files and code

SearchTimes class

let EventEmitter = require('events')
let fs = require('fs')

class SearchTimes extends EventEmitter {
    constructor(path, options) {
        super(path, options);
        this.path = path;
        this.text = options.text || ' ';
        this.highWaterMark = options.highWaterMark || 64 * 1024;
        this.buffer = Buffer.alloc(this.highWaterMark);
        this.flags = options.flags || 'r';
        this.encoding = options.encoding || 'utf-8';
        this.mode = options.mode || 0o666;
        this.start = options.start || 0;
        this.end = options.end;
        this.pos = this.start;
        this.autoClose = options.autoClose || true;
        this.buffers = ' ';
        this.on('newListener', (type) = > {if(type= ='searchTimes'){
                this.read();
            }
        })
        this.open();
    }
    read() {if(typeof this.fd ! ='number') {return this.once('open',()=>this.read())
        }
        lethowMuchToRead = this.end? Math.min(this.end-this.pos+1,this.highWaterMark):this.highWaterMark fs.read(this.fd,this.buffer,0,howMuchToRead,this.pos,(err,bytes)=>{if(err){
                if(this.autoClose)
                    this.destroy()
                return this.emit('err',err)
            }
            if(bytes){
                letdata = this.buffer.slice(0,bytes) this.pos += bytes data = this.encoding? data.toString(this.encoding):data this.emit('searchTimes',data)
                this.buffers += data
                if(this.end && this.pos > this.end){
                    return this.endFn();
                }else{ this.read(); }}else{
                return this.endFn();
            }
       })
    }
    getPlaceholderCount(strSource,text) {
        var thisCount = 0;
        strSource.replace(new RegExp(this.unicode(text),'g'), function (m, i) {
            thisCount++;
        });
        return thisCount;
    }
    unicode(str){
        var value=' ';
        for (var i = 0; i < str.length; i++) {
            value += '\\u' + this.left_zero_4(parseInt(str.charCodeAt(i)).toString(16));
        }
        return value;
    }
    left_zero_4(str) {
        if(str ! = null && str ! =' '&& str ! ='undefined') {
            if (str.length == 2) {
                return '00'+ str; }}return str;
    }
    endFn(){
        const count = this.getPlaceholderCount(this.buffers,this.text)
        this.emit('end',count);
        this.destroy();
    }
    open(){
        fs.open(this.path,this.flags,this.mode,(err,fd)=>{
            if(err){
                if(this.autoClose){
                    this.destroy()
                    return this.emit('err',err)
                }
            }
            this.fd = fd
            this.emit('open')})}destroy(){
        fs.close(this.fd,(err)=>{
            this.emit('close')
        })
    }
}

module.exports = SearchTimes
Copy the code

Call the file

let SearchTime = require('./SearchTimes')
let reader = new SearchTime('./1.txt',{
    text:'good',// Search for content highWaterMark:30}) reader.on('searchTimes',(data)=>{// listen to searchTimes return file contents console.log(data)}) reader.on('end',data=>{// Listen to send return the number of files that meet the conditions console.log('count',data)
})

reader.on('error',(error)=>{
    console.log('error',error)
})
Copy the code

Object file to search for

All right, merlin of all right today, all right, all right, all right, all rightCopy the code