跳到主要内容

fs 模块

文件

读取文件

读取文本文件
import fs from "fs";

// fs.readFile(path[, options], callback)
const getJSON = async () => {
const filePath = dataFoldURL + info.data;
// 获取 buffer 数据
const buffer = fs.readFileSync(filePath);
// buffer 数据转 string
const str = buffer.toString();
// 解析为 json 对象
const json = JSON.parse(str);
return json;
};

// fs.read(fd, buffer, offset, length, position, callback)
// 用的不多
文件流读取
import fs from "fs";

// fs.createReadStream(path[, options])
const cs = fs.createReadStream(filePath);
cs.on("data", function (chunk) {
console.log("读取数据: " + chunk);
})
.on("error", function (err) {
console.log("出错: " + err.message);
})
.on("end", function () {
console.log("没有数据了");
})
.on("close", function () {
console.log("已经关闭");
});
文件内容截取
import fs from "fs";

// fs.truncate(path[, len], callback)
fs.truncate("path/file.txt", 100, (err) => {
if (err) throw err;
console.log("path/file.txt was truncated");
});

// fs.ftruncate(fd[, len], callback)
// 该 api 传递文件句柄

写入文件

写入原则
  • 若文件不存在则创建文件;
  • 若文件存在则覆盖文件;
文件写入
import fs from "fs";

// fs.writeFile(file, data[, options], callback)
fs.writeFile("./fileForWrite.txt", "hello world", "utf8", function (err) {
if (err) throw err;
console.log("文件写入成功");
});
文件流写入
import fs from "fs";

// fs.createWriteStream(path[, options])
const writeStream = fs.createWriteStream("./fileForWrite1.txt", "utf8");
writeStream.on("close", function () {
// 已经关闭, 不会再有事件抛出
console.log("已经关闭");
});
writeStream.write("hello");
writeStream.write("world");
writeStream.end("");
追加文件内容
import fs from "fs";

// fs.appendFile(path, data[, options], callback)
fs.appendFile("message.txt", "data to append", "utf8", (err) => {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});

删除文件

删除文件
import fs from "fs";

// fs.unlink(path, callback)
fs.unlink("./fileForUnlink.txt", function (err) {
if (err) throw err;
console.log("文件删除成功");
});

文件权限

文件是否访问
import fs from "fs";

// fs.access(path[, mode], callback)
// Check if the file exists in the current directory.
fs.access(file, constants.F_OK, (err) => {
console.log(`${file} ${err ? "does not exist" : "exists"}`);
});
// Check if the file is readable.
fs.access(file, constants.R_OK, (err) => {
console.log(`${file} ${err ? "is not readable" : "is readable"}`);
});
// Check if the file is writable.
fs.access(file, constants.W_OK, (err) => {
console.log(`${file} ${err ? "is not writable" : "is writable"}`);
});
// Check if the file is readable and writable.
fs.access(file, constants.R_OK | constants.W_OK, (err) => {
console.log(`${file} ${err ? "is not" : "is"} readable and writable`);
});

文件属性

修改文件属性
import fs from "fs";

// fs.utimes(path, atime, mtime, callback)
let newModifiedTime = new Date();
let newAccessTime = new Date();
fs.utimes("example_file.txt", newAccessTime, newModifiedTime, () => {
// After
});

// fs.futimes(fd, atime, mtime, callback)
// 该 api 传递文件句柄

// fs.ltimes(path, atime, mtime, callback)
// 若文件时软连接, 该 api 仅修改软连接, fs.utimes 修改软连接指向的目标文件

监听文件

监听文件修改
  • 具有 fs.watch() 和 fs.watchFile() 两个 api;
  • fs.watch() 跨平台有 bug,不推荐使用;
import fs from "fs";

// fs.watchFile(filename[, options], listener)
var options = {
persistent: true, // 默认就是true
interval: 2000, // 多久检查一次
};
// curr, prev 为当前和上一次的 fs.Stat 实例
// 可以通过 fs.unwatch() 移除监听
fs.watchFile("./fileForWatch.txt", options, function (curr, prev) {
console.log("修改时间为: " + curr.mtime);
});

文件夹

创建文件夹

创建目录
import fs from "fs";

// fs.mkdir(path[, options], callback)
// 目标文件夹已存在会报错
fs.mkdir(
"./hello/world",
{
recursive: true, // 递归创建文件树, 默认为 false
},
function (err) {
if (err) throw err;
console.log("目录创建成功");
}
);

遍历文件夹

遍历文件夹
import fs from "fs";

// fs.readdir(path[, options], callback)
const traverseFolder = (folderPath: string) => {
const files = await fs.promises.readdir(folderPath);
const promises = files.map((file) => {
const filePath = path.join(folderPath, file);
const promise = new Promise(async (resolve) => {
const stat = await fs.promises.stat(filePath);
if (stat.isDirectory()) {
await traverseFolder(filePath);
resolve(1);
} else {
// ...
resolve(1);
}
});
return promise;
await Promise.all(promises);
});
};

删除文件夹

// fs.rmdir(path[, options], callback)
// 只能删除空文件夹

文件和文件夹

删除文件和文件夹
// fs.rm(path[, options], callback)
fs.rm("./hello",{
force: true // 强制删除, 默认为 false
recursive: true, // 递归删除文件树, 默认为 false
}, function (err) {
if (err) throw err;
console.log("重命名成功");
});
重命名
import fs from "fs";

// fs.rename(oldPath, newPath, callback)
fs.rename("./hello", "./world", function (err) {
if (err) throw err;
console.log("重命名成功");
});
修改权限
import fs from "fs";

// fs.chmod(path, mode, callback)
fs.chmod("my_file.txt", 0o775, (err) => {
if (err) throw err;
console.log('The permissions for file "my_file.txt" have been changed!');
});

// fs.fchmod(fd, mode, callback)
// 该 api 传递文件句柄

// fs.lchmod(path, mode, callback)
// 若文件时软连接, 该 api 仅修改软连接, fs.chmod 修改软连接指向的目标文件
文件(夹)状态
import fs from "fs";

// fs.stat(path[, options], callback)
const pathsToCheck = ["./txtDir", "./txtDir/file.txt"];
for (let i = 0; i < pathsToCheck.length; i++) {
stat(pathsToCheck[i], (err, stats) => {
console.log(stats.isDirectory());
console.log(stats);
});
}

// fs.fstat(fd[, options], callback)
// 该 api 传递文件句柄

// fs.lstat(path[, options], callback)
// 若文件时软连接, 该 api 仅修改软连接, fs.stat 修改软连接指向的目标文件

fs.Stats

方法
stats.isDirectory(); // 是否为文件夹, fs.lstat 总返回 false
stats.isFile(); // 是否为文件
stats.isSocket(); // 是否为 socket
stats.isSymbolicLink(); // 是否为符号链接, 仅 fs.lstat 有效
stats.isBlockDevice(); // 不理解
stats.isCharacterDevice(); // 不理解
stats.isFIFO(); // 不理解
属性
Stats {
dev: 2114,
ino: 48064969,
mode: 33188,
nlink: 1,
uid: 85,
gid: 100,
rdev: 0,
size: 527,
blksize: 4096,
blocks: 8,
atimeMs: 1318289051000.1,
mtimeMs: 1318289051000.1,
ctimeMs: 1318289051000.1,
birthtimeMs: 1318289051000.1,
atime: Mon, 10 Oct 2011 23:24:11 GMT, // 访问时间
mtime: Mon, 10 Oct 2011 23:24:11 GMT, // 内容修改时间
ctime: Mon, 10 Oct 2011 23:24:11 GMT, // 状态修改时间
birthtime: Mon, 10 Oct 2011 23:24:11 GMT // 创建时间
}

fs.ReadStream

事件
import fs from "fs";

// fs.createReadStream(path[, options])
const cs = fs.createReadStream(filePath);

// 流打开
cs.on("open", function (chunk) {
//
});

// 流准备使用, 发生在 open 之后
cs.on("ready", function (chunk) {
//
});

// 数据进入流
cs.on("data", function (chunk) {
//
});

// 流数据完全被消耗
cs.on("end", function () {
//
});

// 流关闭, 发生在 end 之后
cs.on("close", function () {
//
});

// 流报错
cs.on("error", function (err) {
//
});

fs.WriteStream

属性
writable.closed; // 是否关闭
writable.destroyed; // 是否摧毁
方法
import fs from "fs";

const cs = fs.createWriteStream(filePath);

// writable.write(chunk[, encoding][, callback])
// 写入流, 写入后触发回调
write("hello", () => {
console.log("Write completed, do more writes now.");
});

// writable.end([chunk[, encoding]][, callback])
// 等待 cs.write() 传输完毕并结束流
file.end("world!");

// writable.destroy([error])
// 立刻摧毁流, 触发 error 和 close 时间
// cs.write() 的数据可能未完全写入
cs.destroy(error);
事件
import fs from "fs";

// fs.createReadStream(path[, options])
const cs = fs.createWriteStream(filePath);

// 流打开
cs.on("open", function (chunk) {
//
});

// 流准备使用, 发生在 open 之后
cs.on("ready", function (chunk) {
//
});

// 恢复向流写入数据
cs.on("drain", function (chunk) {
//
});

// 流数据写入完毕, stream.end() 触发
cs.on("finish", function () {
//
});

// 流关闭
cs.on("close", function () {
//
});

// 流报错
cs.on("error", function (err) {
//
});