1. The fs module

  • In Node.js, the FS module is used to create, write, and delete all related files and directories.
  • In FS module, all methods are divided into synchronous and asynchronous implementations.
  • withsyncThe suffix method is synchronous method and does not havesyncMethods with suffixes are asynchronous methods.

2. Read the file as a whole

2.1 Asynchronous Reading

fs.readFile(path[, options], callback)
Copy the code
  • options
    • encoding
    • Flag Flag Default = ‘r’

2.2 Synchronous Reading

fs.readFileSync(path[, options])
Copy the code

3. Write files

3.1 Asynchronous Write

fs.writeFile(file, data[, options], callback)
Copy the code
  • options
    • encoding
    • Flag Flag Default = ‘w’
    • Mode Read and write permission. The default value is 0666
let fs = require('fs');
fs.writeFile('./1.txt',Date.now()+'\n',{flag:'a'},function(){
  console.log('ok');
});
Copy the code

3.2 Synchronous Write

fs.writeFileSync(file, data[, options])
Copy the code

3.3 Appending Files

fs.appendFile(file, data[, options], callback)

fs.appendFile('./1.txt',Date.now()+'\n'.function(){
  console.log('ok');
})
Copy the code

3.4 Copying Files

function copy(src,target){
  fs.readFile(src,function(err,data){ fs.writeFile(target,data); })}Copy the code

4. Read the file from the specified position

4.1 Opening a File

fs.open(filename,flags,[mode],callback);

  • Filename Specifies the name of the file. This parameter is mandatory
  • * Flags, operation flags, such as “r”, read mode on
  • [mode], permission, such as 777, indicates that any user read/write can be executed
  • Callback Is a callback function to open a file. By default, the first parameter of err and the second fd are integers, indicating the file descriptor returned when the file is opened
fs.open('./1,txt'.'r', 0600,function(err,fd){});
Copy the code

4.2 Reading Files

fs.read(fd, buffer, offset, length, position, callback((err, bytesRead, buffer)))

const fs=require('fs');
const path=require('path');
fs.open(path.join(__dirname,'1.txt'),'r',0o666,function (err,fd) {
    console.log(err);
    letbuf = Buffer.alloc(6); Fs. Read (fd, buf, 0,6,3,function(err, bytesRead, buffer){ console.log(bytesRead); //6 console.log(buffer===buf); //trueconsole.log(buf.toString()); })})Copy the code

4.3 Writing files

fs.write(fd, buffer[, offset[, length[, position]]], callback)

const fs=require('fs');
const path=require('path');
fs.open(path.join(__dirname,'1.txt'),'w',0o666,function (err,fd) {
    console.log(err);
    let buf=Buffer.from('Hello Chengdu'); Fs. Write (fd, buf, 3,6,0,function(err, bytesWritten, buffer){ console.log(bytesWritten); //6 console.log(buffer===buf); //trueconsole.log(buf.toString()); // Hello Chengdu})})Copy the code

4.4 Synchronizing Disk Cache

fs.fsync(fd,[callback]);

4.5 Closing files

fs.close(fd,[callback]);

let buf = Buffer.from('Hello Chengdu');
fs.open('./2.txt'.'w'.function (err, fd) {
  fs.write(fd, buf, 3, 6, 0, function (err, written, buffer) {
    console.log(written);
    fs.fsync(fd, function (err) {
      fs.close(fd, function (err) {
          console.log('Written! ')}); }); })});Copy the code

4.6 Copying Files

let BUFFER_SIZE=1;
const path=require('path');
const fs=require('fs');
function copy(src,dest,callback) {
    let buf=Buffer.alloc(BUFFER_SIZE);
    fs.open(src,'r',(err,readFd)=>{
        fs.open(dest,'w',(err,writeFd) => {
            !function read() {
                fs.read(readFd,buf,0,BUFFER_SIZE,null,(err,bytesRead) => {
                    bytesRead&&fs.write(writeFd,buf,0,bytesRead,read); }); }})} ()); } copy(path.join(__dirname,'1.txt'),path.join(__dirname,'2.txt'),()=>console.log('ok'));
Copy the code

5 Directory Operations

5.1 Creating a Directory

fs.mkdir(path[, mode], callback)

The parent directory must exist

5.2 Checking whether a file is accessible

fs.access(path[, mode], callback)

fs.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK, (err) => {
  console.log(err ? 'no access! ' : 'can read/write');
});
Copy the code

5.3 Reading All Files in a Directory

fs.readdir(path[, options], callback)

5.4 Viewing File and Directory Information

fs.stat(path, callback)

  • stats.isFile()
  • stats.isDirectory()
  • Atime (Access Time) Time when the file was read last Time.
  • Ctime (State Change Time) : indicates the Time when an attribute or content was modified last Time.
  • Mtime (Modified Time) : indicates the time when the contents of the file were last Modified.

5.5 Moving A File or Directory

fs.rename(oldPath, newPath, callback)
Copy the code

5.6 Deleting a File

fs.unlink(path, callback)
Copy the code

5.7 Truncating files

fs.ftruncate(fd[, len], callback)
Copy the code
const fd = fs.openSync('temp.txt'.'r+'); F.ftruncate (fd, 4, (err) => {console.log(fs.readfilesync (fs.readfilesync))'temp.txt'.'utf8'));
});
Copy the code

5.8 Monitoring Files or Directories

fs.watchFile(filename[, options], listener)
Copy the code
let fs = require('fs');
fs.watchFile('1.txt', (curr, prev) => {// The parse() method parses a date and time string and returns the number of milliseconds from the date and time at midnight 1970/1.if(Date.parse(prev.ctime)==0){
    console.log('create');
  }else if(Date.parse(curr.ctime)==0){
    console.log('delete');
  }else if(Date.parse(prev.ctime) ! = Date.parse(curr.ctime)){ console.log('change'); }});Copy the code

6 Create directories recursively

6.1 Creating a Directory Synchronously

let fs=require('fs');
let path=require('path');
function makepSync(dir) {
    let parts=dir.split(path.sep);
    for (leti=1; i<=parts.length; i++){letparent=parts.slice(0,i).join(path.sep); try { fs.accessSync(parent); } catch (error) { fs.mkdirSync(parent); }}}Copy the code

6.2 Creating a Directory Asynchronously

function makepAsync(dir,callback) {
    let parts=dir.split(path.sep);
    let i=1;
    function next() {
        if (i>parts.length)
            return callback&&callback();    
        let parent=parts.slice(0,i++).join(path.sep);
        fs.access(parent,err => {
            if (err) {
                fs.mkdir(parent,next);
            } else{ next(); }}); } next(); }Copy the code

6.3 Async+Await Create directory

async function mkdir(parent) {
    return new Promise((resolve,reject) => {
        fs.mkdir(parent,err => {
            if (err) reject(err);
            else resolve();
        });
    });
}

async function access(parent) {
    return new Promise((resolve,reject) => {
        fs.access(parent,err => {
            if (err) reject(err);
            else resolve();
        });
    });
}
async function makepPromise(dir,callback) {
    let parts=dir.split(path.sep);
    for (leti=1; i<=parts.length; i++){letparent=parts.slice(0,i).join(path.sep); try { await access(parent); }catch(err) { await mkdir(parent); }}}Copy the code

7. Delete directories recursively

7.1 Deleting a Directory Synchronously (Depth-first)

let fs=require('fs');
let path=require('path')
function rmSync(dir) {
    try {
        let stat = fs.statSync(dir);
        if (stat.isFile()) {
            fs.unlinkSync(dir);
        } else {
            let files=fs.readdirSync(dir);
            files
                .map(file => path.join(dir,file))
                .forEach(item=>rmSync(item));
            fs.rmdirSync(dir);
        }
    } catch (e) {
        console.log('Delete failed! ');
    }
}
rmSync(path.join(__dirname,'a'));
Copy the code

7.2 Asynchronously Deleting a Non-Empty Directory (Promise Version)

function rmPromise(dir) {
    return new Promise((resolve,reject) => {
        fs.stat(dir,(err,stat) = > {if (err) return reject(err);
            if (stat.isDirectory()) {
                fs.readdir(dir,(err,files) => {
                    let paths = files.map(file => path.join(dir,file));
                    let promises = paths.map(p=>rmPromise(p));
                    Promise.all(promises).then((() => fs.rmdir(dir,resolve)));
                });
            } else{ fs.unlink(dir,resolve); }}); }); } rmPromise(path.join(__dirname,'a')).then(() => {
    console.log('Deleted successfully');
})
Copy the code

7.3 Deleting A Directory Asynchronously (Depth-First)

function rmAsyncSeries(dir,callback) {
    setTimeout(() => {
        fs.stat(dir,(err,stat) = > {if (err) return callback(err);
            if (stat.isDirectory()) {
                fs.readdir(dir,(err,files) => {
                    let paths = files.map(file => path.join(dir,file));
                    function next(index) {
                        if (index>=files.length) return fs.rmdir(dir,callback);
                        let current=paths[index];
                        rmAsyncSeries(current,()=>next(index+1));
                    }
                    next(0);
                });
            } else{ fs.unlink(dir,callback); }})}, 1000); } console.time('cost');
rmAsyncSeries(path.join(__dirname,'a'),err => {
     console.timeEnd('cost');
})
Copy the code

7.4 Asynchronously Deleting directories in Parallel (Depth-first)

function rmAsyncParallel(dir,callback) {
    setTimeout(() => {
        fs.stat(dir,(err,stat) = > {if (err) return callback(err);
            if (stat.isDirectory()) {
                fs.readdir(dir,(err,files) => {
                    let paths=files.map(file => path.join(dir,file));
                    if (paths.length>0) {
                        let i=0;
                        function done() {
                            if (++i == paths.length) {
                                fs.rmdir(dir,callback);
                            }
                        }
                      paths.forEach(p=>rmAsyncParallel(p,done));
                    } else{ fs.rmdir(dir,callback); }}); }else{ fs.unlink(dir,callback); }})}, 1000); } console.time('cost');
rmAsyncParallel(path.join(__dirname,'a'),err => {
     console.timeEnd('cost');
})
Copy the code

7.5 Deleting A Directory Synchronously (Breadth First)

function rmSync(dir){
    let arr=[dir];
    let index=0;
    while (arr[index]) {
        let current=arr[index++];
        let stat=fs.statSync(current);
        if (stat.isDirectory()) {
            let dirs=fs.readdirSync(current); arr=[...arr,...dirs.map(d => path.join(current,d))]; }}let item;
    while(null ! = (item = arr.pop())) {let stat = fs.statSync(item);
        if (stat.isDirectory()) {
            fs.rmdirSync(item);
        } else{ fs.unlinkSync(item); }}}Copy the code

7.6 Deleting a Directory Asynchronously (Breadth First)

function rmdirWideAsync(dir,callback){
    let dirs=[dir];
    let index=0;
    function rmdir() {
        let current = dirs.pop();
        if (current) {
            fs.stat(current,(err,stat) = > {if (stat.isDirectory()) {
                    fs.rmdir(current,rmdir);
                } else{ fs.unlink(current,rmdir); }}); }} instead!function next() {
        let current=dirs[index++];
        if (current) {
            fs.stat(current,(err,stat) = > {if (err) callback(err);
                if (stat.isDirectory()) {
                    fs.readdir(current,(err,files) => {
                        dirs=[...dirs,...files.map(item => path.join(current,item))];
                        next();
                    });
                } else{ next(); }}); }else {
            rmdir();
        }

    }();
}
Copy the code

8. Traversal algorithm

  • Directory is a tree structure, and depth-first + first-order traversal algorithm is generally used in traversal
  • Depth-first, which means that when a node is reached, child nodes are first traversed instead of neighbor nodes
  • Sequential traversal means that the traversal is complete when a node is reached for the first time, rather than when a node is returned for the last time
  • Therefore, the following tree is traversed in the order A > B > D > E > C > F.
            A
           / \
          B   C
         / \   \
        D   E   F
    Copy the code

    8.1 Synchronization Depth-first + Sequential Traversal

    function deepSync(dir){
      console.log(dir);
      fs.readdirSync(dir).forEach(file=>{
          let child = path.join(dir,file);
          let stat = fs.statSync(child);
          if(stat.isDirectory()){
              deepSync(child);
          }else{ console.log(child); }}); }Copy the code

    8.2 Asynchronous depth-first + sequential traversal

    function deep(dir,callback) {
      console.log(dir);
      fs.readdir(dir,(err,files)=>{
          !function next(index){
              if(index == files.length){
                  return callback();
              }
              let child = path.join(dir,files[index]);
              fs.stat(child,(err,stat) = > {if(stat.isDirectory()){
                      deep(child,()=>next(index+1));
                  }else{ console.log(child); next(index+1); })}(0)})}Copy the code

    8.3 Synchronization Breadth First + Sequential traversal

    function wideSync(dir){
      let dirs = [dir];
      while(dirs.length>0){
          let current = dirs.shift();
          console.log(current);
          let stat = fs.statSync(current);
          if(stat.isDirectory()){
              letfiles = fs.readdirSync(current); files.forEach(item=>{ dirs.push(path.join(current,item)); }); }}}Copy the code

8.4 Asynchronous breadth-first + sequential traversal

// asynchronous breadth traversalfunction wide(dir, cb) {
    console.log(dir);
    cb && cb()
    fs.readdir(dir, (err, files) => {
        !function next(i){
            if(i>= files.length) return;
            let child = path.join(dir,files[i]);
            fs.stat(child,(err,stat) = > {if(stat.isDirectory()){
                    wide(child, () => next(i+1));
                } else{ console.log(child); next(i+1); }})} (0); }) } wide(path.join(__dirname,'a'));
Copy the code

8. The path module

Path is a core module in Node that deals specifically with paths

  • Path. join combines multiple parameter value strings into a single path string
  • Path. basename Gets the name of a file in a path
  • Path. extName Gets an extension in a path
  • Path. sep File separator specified by the operating system
  • The path.delimiter property value is the path delimiter of the environment variables specified by the system
  • Path. normalize Converts nonstandard path strings to standard path strings.
    • Can parse and..
    • Multiple bars can be converted to one bar
    • Under Windows, backbars are converted to positive bars
    • If the end ends in a bar, keep the slash
  • resolve
    • Start with the application root directory
    • If the argument is a plain string, it means a subdirectory of the current directory
    • If the argument is.. Go back to the previous directory
    • A slash indicates an absolute root path
var path = require('path');
var fs = require('fs'); /** * normalize converts an unnormalized path to a normalized path * 1. Parse and.. * 2. Multiple slashes are converted to a single slash * 3. Slashes under Windows are converted to forward slashes * 4. **/ console.log(path.normalize('./a////b//.. \\c//e//.. / / ')); // \a\c\ // Multiple argument strings merged into a single path string console.log(path.join(__dirname,'a'.'b')); /** * resolve * 1; /** * resolve * 1; Start with the application as root * 2... 4. / Indicates the root directory of the Jedi path */ console.log(path.resolve()); // Empty represents the current directory path console.log(path.resolve('a'.'/c')); // /a/b // d:\c // Console. log(path.relative(__dirname,'/a')); // a // Returns the directory where the specified path resides console.log(path.dirname(__filename)); // 9.path console.log(path.dirname('./1.path.js')); Basename console.log(path.basename(__filename)); // 9. console.log(path.basename(__filename,'.js')); console.log(path.extname(__filename)); console.log(path.sep); // File delimiter window \ Linux/console.log(path.win32.sep); console.log(path.posix.sep); console.log(path.delimiter); // Path separator window; linux :Copy the code

9. flags

symbol meaning
r Read the file. No file error is reported
r+ Read and write file without error
rs Read the file synchronously and ignore the cache
w Write a file. If it does not exist, create it. If it does exist, delete it
wx Write files exclusively
w+ Read and write files, create if they don’t exist, empty if they do
wx+ Just like w+, open exclusively
a Additional written
ax Similar to a, write in exclusive mode
a+ Read and append to, create if not present
ax+ Functions like a+, but opens files in an exclusive manner

10. Mnemonic

  • R read
  • W to write
  • S synchronization
  • + Add the opposite operation
  • X exclusivity
  • The difference between r+ W +?
    • When the file does not exist, r+ will not be created and the call will fail, but W + will be created.
    • If the file exists, r+ will not automatically empty the file, but W + will automatically empty the contents of the existing file.

11. Linux Permissions #