Node 文件 IO
fs 模块
- 在Node中只有require的相对路径是针对当前文件的文件目录的,内置 path 模块的 join 和 resolve 都是相对process.cwd()命令路径,Node中的全局变量
__dirname的值是当前执行脚本文件所在的文件目录的完整路径
const fs = require("fs");
const path = require("path");
class File {
constructor(filename, name, ext, isFile, size, createTime, updateTime) {
this.filename = filename;
this.name = name;
this.ext = ext;
this.isFile = isFile;
this.size = size;
this.createTime = createTime;
this.updateTime = updateTime;
}
async getContent(isBuffer = false) {
if (this.isFile) {
if (isBuffer) {
return await fs.promises.readFile(this.filename);
} else {
return await fs.promises.readFile(this.filename, "utf-8");
}
}
return null;
}
async getChildren() {
if (this.isFile) {
//文件不可能有子文件
return [];
}
let children = await fs.promises.readdir(this.filename);
children = children.map(name => {
const result = path.resolve(this.filename, name);
return File.getFile(result);
});
return Promise.all(children);
}
static async getFile(filename) {
const stat = await fs.promises.stat(filename);
const name = path.basename(filename);
const ext = path.extname(filename);
const isFile = stat.isFile();
const size = stat.size;
const createTime = new Date(stat.birthtime);;l
const updateTime = new Date(stat.mtime);
return new File(filename, name, ext, isFile, size, createTime, updateTime);
}
}
async function readDir(dirname) {
const file = await File.getFile(dirname);
return await file.getChildren();
}
async function test() {
const dirname = path.resolve(__dirname, "./myfiles");
const result = await readDir(dirname);
const datas = await result[0].getChildren();
console.log(datas);
}
test();
大文件读写流 Stream
流是指数据的流动,数据从一个地方缓慢的流动到另一个地方,在Node中使用stream模块进行使用
由于其他介质和内存的
- 数据规模不一致,磁盘里面可以装很多的数据,但是内存小里面可以装的数据很少,所以在读大数据的时候,不可能把磁盘里面的大数据一下子读到内存,只能一部分一部分的读。
- 数据处理能力不一致,内存处理能力很快,硬盘的速度和内存是没有办法比的,1G 的内存中的数据全部往硬盘里面塞,就会造成对硬盘的阻塞,所以用流缓慢的存。
变量存在内存中,流的使用一般是读一部分扔一部分,如果在data中将所有的chunk收集流的数据规模特性就发挥不到了 普通读写和流读写之间的区别
const fs = require("fs");
const path = require("path");
//方式1
async function method1() {
const from = path.resolve(__dirname, "./temp/abc.txt");
const to = path.resolve(__dirname, "./temp/abc2.txt");
console.time("方式1");
const content = await fs.promises.readFile(from);
await fs.promises.writeFile(to, content);
console.timeEnd("方式1");
console.log("复制完成");
}
//方式2
async function method2() {
const from = path.resolve(__dirname, "./temp/abc.txt");
const to = path.resolve(__dirname, "./temp/abc2.txt");
console.time("方式2");
const rs = fs.createReadStream(from);
const ws = fs.createWriteStream(to);
rs.on("data", chunk => {
//读到一部分数据
const flag = ws.write(chunk);
if (!flag) {
//表示下一次写入,会造成背压
rs.pause(); //暂停读取
}
});
ws.on("drain", () => {
//可以继续写了
rs.resume();
});
rs.on("close", () => {
//写完了
ws.end(); //完毕写入流
console.timeEnd("方式2");
console.log("复制完成");
});
}
method2();
上述可以直接用pipe实现读写复制
const fs = require("fs");
const path = require("path");
//方式2
async function method2() {
const from = path.resolve(__dirname, "./temp/abc.txt");
const to = path.resolve(__dirname, "./temp/abc2.txt");
console.time("方式2");
const rs = fs.createReadStream(from);
const ws = fs.createWriteStream(to);
rs.pipe(ws);
rs.on("close", () => {
console.timeEnd("方式2");
});
}
method2();