关于node.js:Nodejs文件目录操作实例

3次阅读

共计 4831 个字符,预计需要花费 13 分钟才能阅读完成。

文件关上和敞开

fs.open(path.resolve("data.txt"), "r", (err, fd) => {console.log(fd); // 3
});

fs.open("data.txt", "r", (err, fd) => {console.log(fd);
  fs.close(fd, (err) => {console.log('close successful');
  });
});

大文件读写操作

波及 open 和 write 两个办法

// read 读操作就是将数据从磁盘文件写入到 buffer 中
// read(fd: number, -- 定位以后被关上的文件
// buffer: Buffer, -- 用于标识以后缓冲区
// offset: number, -- 从 buffer 哪个地位开始写操作
// length: number, -- 以后次写入的字节长度
// position: fs.ReadPosition, -- 从磁盘文件中哪一个字节开始读取
// callback: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void
let buf = Buffer.alloc(10);
fs.open("data.txt", "r", (err, readfd) => {console.log(readfd);
  fs.read(readfd, buf, 1, 3, 2, (err, readBytes, data) => {console.log(readBytes);
    console.log(data);
    console.log(data.toString());
  });
});

// write(fd: number,-- 定位以后被关上的文件
//  buffer: Buffer, -- 用于标识以后缓冲区
//  offset: number, -- 从 buffer 哪个地位开始读取数据
//  length: number,  -- 以后次写的字节长度 
//  position: number, -- 从哪个字节开始写操作
//  callback: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void
let buf = Buffer.from('1234567890')
fs.open('a.txt','w',(err,writefd)=>{fs.write(writefd,buf,1,3,0,(err,written,buffer)=>{console.log(written)  // 3
        console.log(buffer)  // <Buffer 31 32 33 34 35 36 37 38 39 30>
        console.log(buffer.toString()) // 1234567890
        fs.close(writefd)
    })
})

文件拷贝自定义实现

/**
 * 1 关上 a 文件,利用 read 将数据保留到 buffer 暂存起来 -- a 文件内容为 1234567890
 * 2, 关上 b 文件,利用 write 将 buffer 中数据写入到 b 文件
 */
let buf = Buffer.alloc(10);
// 关上指定文件
fs.open("a.txt", "r", (err, readfd) => {
  // 关上 b 文件,用于执行数据写入操作
  fs.open("b.txt", "w", (err, writefd) => {
    // 从关上的文件读取数据
    fs.read(readfd, buf, 0, 10, 0, (err, readBytes) => {
      // buffer 写入到 b.txt 中
      fs.write(writefd, buf, 0, 10, 0, (err, wirtten) => {console.log("write successful");
      });
    });
  });
});

针对大文件边读边写,利用 buffer 缓冲区实现操作

let buf = Buffer.alloc(10);
const BUFFER_SIZE = buf.length;
let readOffset = 0;

fs.open("a.txt", "r", (err, readfd) => {fs.open("b.txt", "w", (err, writefd) => {function next() {fs.read(readfd, buf, 0, BUFFER_SIZE, readOffset, (err, readBytes) => {if (!readBytes) {
          // 如果条件成立,内容曾经读取结束
          fs.close(readfd, () => {});
          fs.close(writefd, () => {});
          console.log("拷贝实现");
          return;
        }
        readOffset += readBytes;
        fs.write(writefd, buf, 0, readBytes, (err, written) => {next(); // 递归读写
        });
      });
    }
    next();});
});

FS 目录操作 API

access 判断文件或目录是否具备操作权限
stat 获取目录及文件信息
mkdir 创立目录
rmdir 删除目录
readdir 读取目录中的内容
unlink 删除指定文件

fs.access("a.txt", (err) => {if (err) {console.log(err);
  } else {console.log("有操作权限");
  }
});

fs.stat("a.txt", (err, statObj) => {console.log(statObj.size); // 14
  console.log(statObj.isFile()); // true
  console.log(statObj.isDirectory()); // false
});

fs.mkdir("a/b/c", (err) => {if (!err) {console.log("create successful");
  } else {console.log(err); // 此时报错,要保障 a / b 存在能力创立 c
  }
});

fs.mkdir("a/b/c", { recursive: true}, (err) => {  // 递归创立,不必保障 a / b 目录存在
  if (!err) {console.log("create successful");
  } else {console.log(err); // 此时报错,要保障 a / b 存在能力创立 c
  }
});

fs.rmdir("a/b/c", (err) => {  // a/b/ c 都存在的状况下,只会删除 c . 默认状况下只能删除非空目录
  if (!err) {console.log("delete successful");
  } else {console.log(err);
  }
});

fs.rmdir("a", { recursive: true}, (err) => { // 递归删除
  if (!err) {console.log("delete successful");
  } else {console.log(err);
  }
});

fs.readdir("a", (err, files) => {console.log(files); // ['a.txt', 'b']  默认只会查看第一层,后果是个数组
});

fs.unlink("a/a.txt", (err) => {if (!err) {console.log("del successful");
  }
});

目录创立同步实现

/**
 * 1 未来调用时须要接管相似于 a /b/c,这样的门路,他们之间才欧用 / 进行连贯
 * 2 利用 / 宰割符将门路进行拆分,将每一项放入一个数组中进行治理 ['a' , 'b', 'c']
 * 3 对上述数组进行遍历,咱们须要拿到每一项,而后与前一项进行拼接
 * 4 判断一下以后拼接之后的门路是否具备可操作性的权限,如果有则证实存在,否则就须要执行创立
 */
function makeDirSync(dirPath) {let items = dirPath.split(path.sep);
  console.log(items); // ['a', 'b', 'c']
  for (let i = 1; i <= items.length; i++) { // 这里从下标 1 开始
    let dir = items.slice(0, i).join(path.sep);
    console.log(dir);
    try {fs.accessSync(dir);
    } catch (err) {fs.mkdirSync(dir);
    }
  }
}

makeDirSync("a\\b\\c");

目录创立异步实现

function mkDir(dirPath, cb) {let parts = dirPath.split("/");
  let index = 1;
  function next() {if (index > parts.length) {return cb && cb();
    }
    let current = parts.slice(0, index++).join("/");
    fs.access(current, (err) => {if (err) {
        // 没有操作权限
        fs.mkdir(current, next);
      } else {next();
      }
    });
  }
  next();}

mkDir("a/b/c", () => {console.log("create successful");
});

利用 es6 办法实现, 须要应用 util 包外面的promiseify

const {promisify} = require("util");
// 将 access 与 mkdir 解决传给你 async 格调
const access = promisify(fs.access);
const mkdir = promisify(fs.mkdir);

async function myMkdir(dirPath, cb) {let parts = dirPath.split("/");
  for (let index = 1; index <= parts.length; index++) {let current = parts.slice(0, index).join("/");
    try {await access(current);
    } catch (error) {await mkdir(current);
    }
  }
  cb && cb();}

myMkdir("a/b/c", () => {console.log("create successful");
});

目录删除之异步实现


/**
 * 需要:子弟你一个函数,接管一个门路,而后执行删除操作
 * 1,判断以后传入的门路是否为一个文件,间接执行删除以后文件
 * 2,如果以后传入的是一个目录,咱们须要持续读取目录中的的内容,而后再执行删除操作
 * 3,将删除行为定义成为一个函数,而后通过递归的形式进行复用
 * 4,将以后的名称拼接成在删除时能够应用的门路
 */

function myRmDir(dirpath, cb) {
  // 判断以后 dirpath 类型
  fs.stat(dirpath, (err, statObj) => {if (statObj.isDirectory()) {
      // 目录,持续读取
      fs.readdir(dirpath, (err, files) => {let dirs = files.map((item) => path.join(dirpath, item));
        console.log(dirs);
        let index = 0;
        function next() {if (index === dirs.length) {return fs.rmdir(dirpath, cb); // 遍历实现,删除最外层目录
          }
          let current = dirs[index++];
          myRmDir(current, next);
        }
        next();});
    } else {
      // 文件 -- 间接删除
      fs.unlink(dirpath, cb);
    }
  });
}

myRmDir("a.txt", () => {
  // 文件
  console.log("del successful");
});
myRmDir("a", () => {
  // 目录
  console.log("del successful");
});
正文完
 0