前言
最近在做一个多平台统一部署打包流程优化的专项。 其中插件中的一个小功能就是:将build的产物dist目录下的文件拷贝到.net项目静态资源目录下。于是就有了这个Node专栏。用到哪个模块哪个方法就整理记录一下~
fs(文件系统)
fs
模块可用于与文件系统进行交互(以类似于标准 POSIX 函数的方式)。
要使用此模块:
const fs = require("fs");
所有多文件系统操作都具有同步的、回调的、以及基于 promise的形势。
同步的案例
同步的形式会阻塞 Node.js 事件循环何进一步的JavaScript执行,直到操作完成。异常会被立即抛出,可以使用 try...catch处理,也可以冒泡。
const fs = require("fs");
try{
fs.unlinkSync('文件');
console.log('已成功删除文件呢')
}catch(err){
//处理错误
}
回调的案例
异步的形式总是把完成回调作为其最后一个参数。传给完成回调的参数取决于具体方法,但第一个参数总是预留给异常。如果操作被成功完成,则第一个参数会为null或 undefined。
const fs = require('fs');
fs.unlink('文件',(err)=>{
if(err) throw err;
console.log('已成功删除文件呢')
})
Promise的示例
基于promise的操作会返回Promise(当异步操作完成时被解决)。
const fs = require('fs');
(async function(path){
try{
await fs.unlink(path);
console.log(`已成功删除文件${path}`);
}catch(error){
console.error('出错:',error.message);
}
})('文件');
回调与基于promise的操作的顺序
当使用异步的方法时,无法保证顺序。 因此,以下的操作容易出错,因为 fs.stat() 操作可能在 fs.rename() 操作之前完成:
fs.rename('旧文件','新文件',(err)=>{
if (err) throw err;
console.log('重命名完成');
});
fs.stat('新文件', (err, stats) => {
if (err) throw err;
console.log(`文件属性: ${JSON.stringify(stats)}`);
});
若要正确地排序这些操作,则移动 fs.stat() 调用到 fs.rename() 操作的回调中:
fs.rename('旧文件', '新文件', (err) => {
if (err) throw err;
fs.stat('新文件', (err, stats) => {
if (err) throw err;
console.log(`文件属性: ${JSON.stringify(stats)}`);
});
});
或者,使用基于promise的API:
const fs = requir('fs/promises');
(async function(from,to){
try{
await fs.rename(from,to);
const stats = await fs.stat(to);
}catch(error){
console.error('出错:', error.message);
}
})('旧文件','新文件')
fs.writeFile(file,data[,options],callback)
- file
<string>
|<Buffer>
|<URL>
|<integer>
文件名或文件描述符。 - data
<string>
|<Buffer>
|<TypedArray>
|<DataView>
- options
<Object>
|<string>
- encoding
<string>
|<null>
默认值: 'utf8'。 - mode
<integer>
默认值: 0o666。 - flag
<string>
参见文件系统 flag 的支持。 默认值: 'w'。
- encoding
- callback
<Function>
- err
<Error>
- err
当 file
是文件名时,则异步地写入数据到文件(如果文件已存在,则覆盖文件)。data
可以是字符串或buffer
。
当file
是文件描述符时,则其行为类似于直接调用fs.write()
(建议使用)。
如果data
是 buffer,则encoding
选项则会被忽略。 如果data
是普通对象,则它必须具有自身的toString
函数属性。
const data = new Uint8Array(Buffer.from('Node.js 中文网'));
fs.writeFile('文件.txt', data, (err) => {
if (err) throw err;
console.log('文件已被保存');
});
如果 options 是字符串,则它指定字符编码:
fs.writeFile('文件.txt', 'Node.js 中文网', 'utf8', callback);
不等待回调就对同一个文件多次使用 fs.writeFile() 是不安全的。 对于这种情况,建议使用 fs.createWriteStream()。
fs.readdirSync(path[,options],callback)
path
<string>
|<Buffer>
|<URL>
options
<Object>
|<string>
encoding
<string>
默认'utf8'。withFileTypes
<boolean>
默认值 false
可选的 options 参数可以是字符串(指定字符编码)、或具有 encoding 属性(指定用于返回的文件名的字符编码)的对象。 如果 encoding 被设置为 'buffer',则返回的文件名会作为 Buffer 对象传入。
如果 options.withFileTypes 被设置为 true,则结果会包含 fs.Dirent 对象。
fs.lstatSync(path[, options])
path
<string>
|<Buffer>
|<URL>
options
<Object>
bigint
<boolean>
返回的fs.Stats
对象中的数值是否应为bigint
型。默认值:false
。 返回:<fs.Stats>
同步的 lstat(2)。
fs.Stats类
fs.Stats
对象提供了关于文件的信息。
从 fs.stat()
、fs.lstat()
、fs.fstat()
、以及它们的同步方法返回的对象都是此类型。 如果传给这些方法的 options 中的 bigint 为 true,则数值会是 bigint 型而不是 number 型,并且该对象还会包含额外的纳秒级精度的属性(以 Ns 为后缀)。
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 }
bigint
版本
BigIntStats {
dev: 2114n,
ino: 48064969n,
mode: 33188n,
nlink: 1n,
uid: 85n,
gid: 100n,
rdev: 0n,
size: 527n,
blksize: 4096n,
blocks: 8n,
atimeMs: 1318289051000n,
mtimeMs: 1318289051000n,
ctimeMs: 1318289051000n,
birthtimeMs: 1318289051000n,
atimeNs: 1318289051000000000n,
mtimeNs: 1318289051000000000n,
ctimeNs: 1318289051000000000n,
birthtimeNs: 1318289051000000000n,
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 }
stats.isDirectory()
- 返回
<boolean>
如果 fs.Stats对象描述文件系统目录,则返回 true
如果 fs.Stats 对象来自 fs.lstat(),则此方法会始终返回 false。 这是因为 fs.lstat() 返回关于符号链接本身(而不是其解析的路径)的信息。
fs.existsSync(path)
path
<string>
|<Buffer>
|<URL>
- 返回:
<boolean>
如果路径存在,则返回 true,否则返回 false。
if (fs.existsSync('文件')) {
console.log('该路径已存在');
}
fs.mkdirSync(path[, options])
- path :
<string>
|<Buffer>
|<URL>
isDirectory - options:
<Object>
|<integer>
- recursive
<boolean>
默认值:false
。 - mode
<string>
|<integer>
在 Windows 上不支持。默认值: 0o777。
- recursive
- 返回:
<string>
|<undefined>
同步地创建目录。 返回 undefined,或创建的第一个目录的路径(如果 recursive 为 true)。 这是 fs.mkdir() 的同步版本。
fs.copyFileSync(src,dest[,mode])
- src
<string>
|<Buffer>
|<URL>
要拷贝的源文件名。 - dest
<string>
|<Buffer>
|<URL>
拷贝操作的目标文件名。 - mode
<integer>
用于拷贝操作的修饰符。默认值: 0。
同步地将 src 拷贝到 dest。 默认情况下,如果 dest 已经存在,则覆盖它。 返回 undefined。 Node.js 不保证拷贝操作的原子性。 如果在打开目标文件用于写入后发生错误,则 Node.js 将尝试删除目标文件。
mode 是一个可选的整数,指定拷贝操作的行为。 可以创建由两个或更多个值按位或组成的掩码(比如 fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)。
- fs.constants.COPYFILE_EXCL - 如果 dest 已存在,则拷贝操作将失败。
- fs.constants.COPYFILE_FICLONE - 拷贝操作将尝试创建写时拷贝(copy-on-write)链接。如果平台不支持写时拷贝,则使用后备的拷贝机制。
- fs.constants.COPYFILE_FICLONE_FORCE - 拷贝操作将尝试创建写时拷贝链接。如果平台不支持写时拷贝,则拷贝操作将失败。
const fs = require('fs');
const { COPYFILE_EXCL } = fs.constants;
// 默认情况下将创建或覆盖目标文件。
fs.copyFileSync('源文件.txt', '目标文件.txt');
console.log('源文件已拷贝到目标文件');
// 通过使用 COPYFILE_EXCL,如果目标文件存在,则操作将失败。
fs.copyFileSync('源文件.txt', '目标文件.txt', COPYFILE_EXCL);