1.promise、callback、sync
// promise
const path = require('node:path')
const fs = require('node:fs/promises');
(async function(path) {
try {
await fs.unlink(path)
console.log(`successfully deleted ${path}`)
} catch (error) {
console.error('there was an error:', error.message)
}
})(path.resolve(__dirname, './test.txt'))
// callback
const path = require('node:path')
const fs = require('node:fs')
const target = path.resolve(__dirname, './test.txt')
fs.unlink(target, (err) => {
if (err) throw err
console.log(`successfully deleted ${target}`)
})
// sync
const path = require('node:path')
const fs = require('node:fs')
const target = path.resolve(__dirname, './test.txt')
try {
fs.unlinkSync(target)
console.log(`successfully deleted ${target}`)
} catch (err) {
throw err
}
2.file-handle
在 Node.js 中,FileHandle
是一个表示打开文件的对象,提供了多种方法来操作文件内容。FileHandle
通常通过 fs.promises.open()
方法获取。
打开文件
使用 fs.promises.open()
方法可以异步打开文件,并返回一个 FileHandle
对象。
const fs = require('node:fs/promises');
async function openFile() {
try {
const fileHandle = await fs.open('example.txt', 'r');
console.log('File opened successfully');
// 进行文件操作
await fileHandle.close();
} catch (err) {
console.error('Error opening file:', err);
}
}
openFile();
读取文件
使用 fileHandle.read()
方法可以从文件中读取数据。
async function readFile() {
try {
const fileHandle = await fs.open('example.txt', 'r');
const buffer = Buffer.alloc(1024);
const { bytesRead } = await fileHandle.read(buffer, 0, buffer.length, 0);
console.log('Bytes read:', bytesRead);
console.log('Data:', buffer.toString('utf8', 0, bytesRead));
await fileHandle.close();
} catch (err) {
console.error('Error reading file:', err);
}
}
readFile();
写入文件
使用 fileHandle.write()
方法可以向文件中写入数据。
async function writeFile() {
try {
const fileHandle = await fs.open('example.txt', 'w');
const data = 'Hello, Node.js!';
const { bytesWritten } = await fileHandle.write(data);
console.log('Bytes written:', bytesWritten);
await fileHandle.close();
} catch (err) {
console.error('Error writing file:', err);
}
}
writeFile();
关闭文件
完成文件操作后,使用 fileHandle.close()
方法关闭文件句柄以释放资源。
async function closeFile() {
try {
const fileHandle = await fs.open('example.txt', 'r');
// 进行文件操作
await fileHandle.close();
console.log('File closed successfully');
} catch (err) {
console.error('Error closing file:', err);
}
}
closeFile();
3.constants
在 Node.js
中,constants
模块包含了各种操作系统特定的常量,这些常量用于文件系统操作、错误码、信号等。
const fs = require('node:fs')
console.log(fs.constants)
4.fs.access
fs.access
方法用来判断文件是否可访问:
F_OK 0
文件是否存在(默认值)R_OK 1
文件是否可读W_OK 2
文件是否可写X_OK 4
文件是否可执行
const path = require('node:path')
const fs = require('node:fs')
// 检测文件是否有执行权限
const access = fs.accessSync(path.resolve(__dirname, './3.constants.js'), fs.constants.X_OK)
console.log(access)
5.fs.appendFile
fs.appendFileSync(path, data[,options])
- 向目标文件中追加文本内容
- 如果目标文件不存在的话 会自动创建
const path = require('node:path')
const fs = require('node:fs')
const result = fs.appendFileSync(path.resolve(__dirname, './test.txt'), 'Hello World\n')
console.log(result)
6-1.chmod&chown
fs.chmodSync(path, mode)
fs.chownSync(path, uid, gid)
chmod
即为 change mode
(更改模式) chown
即为 change owner
(更改所有权)
const path = require('node:path')
const fs = require('node:fs')
const result = fs.chmodSync(path.resolve(__dirname, './6.chmod&chown.js'), 0o765)
console.log(result)
TIP
0o765
是八进制
0
没有许可1
只执行2
只写3
写和执行4
只读5
读取和执行6
读取和写7
读写和执行
6-2.fchmod&fchown
fs.fchmodSync(fd, mode)
fs.fchownSync(fd, uid, gid)
fd
全称为 file descriptor
即文件描述符。
const fs = require('node:fs')
// 使用 chownSync 更改文件路径为 'example.txt' 的文件所有者和群组
fs.chownSync('example.txt', 1000, 1000)
// 打开文件并获取文件描述符
const fd = fs.openSync('example.txt', 'r')
// 使用 fchownSync 更改文件描述符为 fd 的文件所有者和群组
fs.fchownSync(fd, 1000, 1000)
// 关闭文件描述符
fs.closeSync(fd)
7-1.open&close
文件描述符:
fchmod(fd)
fchown(fd)
readSync(fd)
const path = require('node:path')
const fs = require('node:fs')
const fd = fs.openSync(path.resolve(__dirname, './7-2.opendir&close.js'), 'r')
console.log(fd)
7-2.opendir&close
opendirSync
是一个同步函数,用于打开一个目录并返回一个 fs.Dir
对象。这个对象可以用来读取目录中的内容。
当使用 fs.opendirSync
打开一个目录时,会创建一个 fs.Dir
对象,并且底层操作系统资源(例如文件描述符)会被分配给该对象。
这些资源是有限的,如果不及时释放,可能会导致资源耗尽或其他潜在的问题。
因此,在使用 opendirSync
之后,要调用 closeSync
方法进行关闭。
readdirSync
读取整个目录的内容并返回一个包含目录条目名称的数组。它一次性读取所有条目,适用于简单的场景。
const path = require('node:path')
const fs = require('node:fs')
const dir = fs.opendirSync(path.resolve(__dirname, '../'))
// console.log(dir)
let dirent
while ((dirent = dir.readSync()) !== null) {
console.log(dirent)
}
// 关闭目录
dir.closeSync()
8.copyFile & cp
// 复制某文件到新文件 如果 `dest` 已存在,则操作会覆盖
fs.copyFileSync(src, dest[,mode])
// 复制目录到新目录
fs.cpSync(src, dest[,options])
9.existsSync
fs.existsSync(path)
如果 path
路径存在,则返回 true
,否则为 false
。
注意,这里的 path
指代的是路径,那么也就是无论是目录还是文件,都是可以的。
const fs = require('node:fs')
const path = require('node:path')
const dirResult = fs.existsSync(path.resolve(__dirname, '../1.assertion-testing'))
const fileResult = fs.existsSync(path.resolve(__dirname, './8.copyFile&cp.js'))
console.log(dirResult, fileResult)
10.mkdirSync
// fs.mkdirSync 创建目录
const path = require('node:path')
const fs = require('node:fs')
// 如果目录已存在的话 会报错。所以可以使用fs.existsSync方法提前判断
fs.mkdirSync(path.resolve(__dirname, '../1.assertion-testing'))
11.readdirSync
fs.readdirSync(path[,options])
读取目标目录,并列出目标目录下的目录和文件。
options: { encoding: 'utf8', withFileTypes: false, recursive: false }
如果 recursive
设置为 false
那么则会递归读取目录所有文件、子文件以及目录。
const path = require('node:path')
const fs = require('node:fs')
const result = fs.readdirSync(path.resolve(__dirname, '../../assets'), {
// encoding: 'utf8',
recursive: true // node较高版本,才可能生效,譬如v20.9.0
})
console.log(result)
12.readFileSync
fs.readFileSync(path[,options])
options
中包括:
encoding
编码方式 默认为null
flag
文件系统标志 默认为r
如果指定了 encoding
,返回一个字符串,表示文件内容。 如果未指定 encoding
,返回一个 Buffer
,表示文件的二进制数据。
const path = require('node:path')
const fs = require('node:fs')
const result = fs.readFileSync(path.resolve(__dirname, './11.readdirSync.js'), {
encoding: 'utf8'
})
console.log(result)
13.renameSync
fs.renameSync(oldPath, newPath)
Renames the file from oldPath
to newPath
. Returns undefined
.
const path = require('node:path')
const fs = require('node:fs')
fs.renameSync(path.resolve(__dirname, './12.readFileSync.js'), path.resolve(__dirname, './11.readFileSync.js'))
14.rmdirSync & rmSync
rmdirSync
删除目录(不推荐使用)rmSync
删除文件或目录
const path = require('node:path')
const fs = require('node:fs')
const dirPath = path.resolve(__dirname, '../../src/pages')
// 删除目录的话 需要声明recursive参数 否则报错ENOTEMPTY 另外控制台会有警告,主要大意就是 `recursive` param is deprecated,推荐使用fs.rmSync结合recursive参数进行使用
fs.rmdirSync(dirPath, {
recursive: true
})
// 删除目录的话 需要声明recursive参数 否则报错EISDIR
// fs.rmSync(dirPath, {
// recursive: true
// })
15.statSync
const path = require('node:path')
const fs = require('node:fs')
// const targetPath = path.resolve(__dirname, './14.rmdirSync&rmSync.js')
const targetPath = path.resolve(__dirname, '../')
// 获取文件或者目录的信息 包含文件大小 访问时间 内容修改时间 权限更改事件。
const stat = fs.statSync(targetPath)
console.log(stat)
/*
Stats {
dev: 16777220,
mode: 16877,
nlink: 62,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 122242453,
size: 1984,
blocks: 0,
atimeMs: 1718523576164.7617,
mtimeMs: 1718456959556.3726,
ctimeMs: 1719632506024.8196,
birthtimeMs: 1718285449381.608,
atime: 2024-06-16T07:39:36.165Z,
mtime: 2024-06-15T13:09:19.556Z,
ctime: 2024-06-29T03:41:46.025Z,
birthtime: 2024-06-13T13:30:49.382Z
}
*/
// 获取文件系统信息 包含文件系统的各种属性,如总大小、可用空间、块大小等。无论targetPath设置为什么,同一个系统的执行结果是一样的。
const statfs = fs.statfsSync(targetPath)
console.log(statfs)
/*
StatFs {
type: 26,
bsize: 4096,
blocks: 61202533,
bfree: 3031215,
bavail: 3031215,
files: 129382624,
ffree: 121248600
}
*/
16.unlinkSync
fs.unlinkSync(path)
unlinkSync
用于删除指定路径的文件或符号链接。
- 删除文件:
unlinkSync
用于从文件系统中删除指定路径的文件。 - 删除符号链接:如果指定路径是一个符号链接,那么
unlinkSync
会删除该符号链接,而不会删除它指向的目标文件。
const path = require('node:path')
const fs = require('node:fs')
const result = fs.unlinkSync(path.resolve(__dirname, './1.promise&callback&sync.js'))
console.log(result)
17.writeFileSync
fs.writeFileSync(file, data[,options])
options
:
encoding
默认utf8
mode
默认0o666
flag
默认w
flush
- 如果该操作,作用于目录,报错
illegal operation on a directory
- 如果该操作指定的目标不存在,则会自动创建
- 该操作会覆盖文件的原始内容 而不是追加
const path = require('node:path')
const fs = require('node:fs')
const result = fs.writeFileSync(path.resolve(__dirname, './test.txt'), '123\n456')
console.log(result)
18.createReadStream
在 node
中读取文件的方式有来两种,一个是利用 fs
模块,一个是利用流来读取。
如果读取小文件,我们可以使用 fs
读取,fs
读取文件的时候,是将文件一次性读取到本地内存。而如果读取一个大文件,一次性读取会占用大量内存,效率很低,这个时候需要用流来读取。
流是将数据分割段,一段一段的读取,可以控制速率,效率很高,不会占用太大的内存。
gulp
的 task
任务,文件压缩,和 http
中的请求和响应等功能的实现都是基于流来实现的。
const path = require('node:path')
const fs = require('node:fs')
const stream = fs.createReadStream(path.resolve(__dirname, './17.writeFileSync.js'), {
highWaterMark: 64, //文件一次读多少字节,默认 64*1024
flags: 'r', //默认 'r'
autoClose: true, //默认读取完毕后自动关闭
start: 0, //读取文件开始位置
// end:3, //默认为Infinity
encoding: 'utf8' //默认为null 此时返回的是Buffer
})
// 打开流
stream.on('open', () => {
console.log('打开流')
})
// 读取流
stream.on('data', (data) => {
console.log('data---', data)
})
// 读取错误
stream.on('err',() => {
console.log('读取错误')
})
//读取结束
stream.on('end',() => {
console.log('读取结束')
})
//读取关闭
stream.on('close',() => {
console.log('读取关闭')
})
// 读取暂停
// stream.pause()
// 读取恢复
// stream.resume()
19.createWriteStream
写入流 可以想象成 水流通过水管向水池中进行注入的过程,而对于水管,我们会称作“缓存区”,水池则是“目标文件”。
当每次写入完成,也就是水管中的水注入完了之后,都会触发 drain
方法。
const path = require('node:path')
const fs = require('node:fs')
const filePath = path.resolve(__dirname, './writeStream.txt')
const stream = fs.createWriteStream(filePath, {
flags: 'w',
encoding: 'utf8',
start: 0,
highWaterMark: 3
})
let i = 9
// 写入9876543210
function write() {
let flag = true
while (flag && i >= 0) {
flag = stream.write(i-- + '')
console.log(flag)
}
}
//缓存区充满并被写入完成,处于清空状态时触发
stream.on('drain',() => {
console.log('drain')
//当缓存区清空后我们在继续写
write()
})
write() //第一次调用write方法