文件操作
常用对文件的操作:
- 获取文件相关信息
- 修改文件相关信息
- 创建文件、目录
- 删除文件、目录
- 复制、移动和重命名
- 遍历文件、目录
- 匹配文件、目录
- 创建和解压ZIP和TAR档案
相关模块
FS 模块相关API | 备注 |
---|---|
fs.stat(filename,callback) | 异步方法,如果返回的stat类型是false,则文件是不存在的 |
fs.statSync(filename) | 同步方法 |
fs.lstatSync(filename) | 同步方法 |
fs.readdir() | 读取目录 返回文件信息(数组) |
fs.rename() | 改名 |
fs.unlink() | 删除 |
fs.mkdir() | 创建文件夹 |
重要:
基本所有node的异步
api
,其回调函数的第一个参数都是 err,错误信息因为早期的
api
都是才采用回调函数的方式,很容易让人绕晕,在async/await
或者promise出来以后,情况好了很多
读取文件
相关API | 说明 |
---|---|
fs.open(path,flags,[mode],callback(err, fd)) | |
fs.read(fd, buffer, offset, length, position, callback(err, bytesRead, buffer)) | 这里的fd 是指通过 fs.open 打开后的文件描述符 |
fs.readFile(filename,[encoding],[callback(err,data)] | |
fs.readFileSync(filename:String, [encoding]) |
吐槽 ,node 前期的
fs
设计还是挺反人类的,各种回调可读性奇差无比
写入
buf
的话,不需要指定编码
// 异步
fs.readFile(filename, "utf8", (err, res)=>{
res.toString().split(/[\n|\r\n]/).forEach(function(eachline){
console.log(eachline)
});
})
// 同步
res = fs.readFileSync(target)
res.toString().split(/[\n|\r\n]/).forEach(function(eachline){
console.log(eachline)
});
const fs = require('fs');
let buf = Buffer.alloc(6);// 创建6字节长度的buf缓存对象
// 打开文件
fs.open('6.txt', 'r', (err, fd) => {
// 读取文件
fs.read(fd, buf, 0, 3, 0, (err, bytesRead, buffer) => {
console.log(bytesRead);
console.log(buffer);
// 继续读取
fs.read(fd, buf, 3, 3, 3, (err, bytesRead, buffer) => {
console.log(bytesRead);
console.log(buffer);
console.log(buffer.toString());
fs.close(fd, )
});
});
});
// 3
// <Buffer e4 bd a0 00 00 00>
// 3
// <Buffer e4 bd a0 e5 a5 bd>
// 你好
写入文件
相关API | |
---|---|
fs.write(fd, buffer, offset, length, position, callback(err, bytesWritten, buffer)); | |
fs.writeFile(filename:String, data, callback(err)) | |
文件flag | 含义 |
---|---|
r | 读取文件,如果文件不存在则抛出异常。 |
r+ | 读取并写入文件,如果文件不存在则抛出异常。 |
rs | 读取并写入文件,指示操作系统绕开本地文件系统缓存。 |
w | 写入文件,文件不存在会被创建,存在则清空后写入。 |
wx | 写入文件,排它方式打开。 |
w+ | 读取并写入文件,文件不存在则创建文件,存在则清空后写入。 |
wx+ | 和 w+ 类似,排他方式打开。 |
a | 追加写入,文件不存在则创建文件。 |
ax | 与 a 类似,排他方式打开。 |
a+ | 读取并追加写入,不存在则创建。 |
ax+ | 与 a+ 类似,排他方式打开。 |
- 带 " + " 的增加相反的操作
- 带 " x " 的相当于排他
r+ 和 w+ 的区别,当文件不存在时,r+ 不会创建文件,而会抛出异常,但 w+ 会创建文件;如果文件存在,r+ 不会自动清空文件,但 w+ 会自动把已有文件的内容清空。
let context = '写入的内容'
fs.writeFile(filename, context, "utf8", callback)
判断文件是否存在
相关API:
fs.stat
fs.statSynv
fs.lstatSync()
const f = fs.stat(target)
f {
dev: 2114,
ino: 48064969,
mode: 33188,
nlink: 1,
uid: 85,
gid: 100,
rdev: 0,
size: 527,
blksize: 4096,
blocks: 8,
atimeMs: 1318289051000.1,//access time 最后访问时间
mtimeMs: 1318289051000.1,//modify time 最后修改时间(文件内容修改)一般使用这个
ctimeMs: 1318289051000.1,//change time 最后变化时间(元数据,权限,所有者)
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
}
// 异步
fileIsExist = async (filename:String) {
fs.stat(filename, (fstst=>{
if (!fstst) {
console.log('文件不存在')
}
}))
}
// 同步
function fileIsExist(filename:String):Boolen {
return fs.statSync(filename)
}
文件监听
常见的监听方案:
- nodemon 模块
- chokdir 模块
- fs 模块的 watch和watchFile 方法
nodemon
chokdir
// 使用第三方模样 chokdir
// yarn add chokidar
// https://github.com/paulmillr/chokidar
const chokidar = require('chokidar')
fs.watch
let watcher = fs.watch(path, options, (event,name)=>{ xxxxxx/ })
//停止监听
watcher.close()
fs.watchFile
let watcher = fs.watchFile(path,options,)
//停止监听
watcher.close()
区别:
watch
- 调用系统内置API
实现,整体cpu
分配合理,但某些系统平台不支持watchFile
- 通过fs.stat
实现文件监视 ,全平台兼容,但cpu
可能占用会高chokidar
- 第三方模块,功能较强
创建可写流
const rs = ws.createWriteStream(tar)
ws.write()
// 结束流
clearInterval(tar)
ws.end()
创建临时目录
import fsp from "fs/promises";
import path from "path";
import os from "os";
async function mkdtemp(prefix){
try {
return await fsp.mkdtemp(path.join(os.tmpdir(), prefix));
} catch (err) {
return false
}
}
通过文件头判断格式
const t = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].toString();
console.log(t);
// 各格式对应图像数据的标识数值
const IMAGE_FILE_HEADER = [
{ ext: 'png', headFlag: [137, 80, 78, 71, 13, 10, 26, 10], offset: 0 },
{ ext: 'jpg', headFlag: [255, 216, 255], offset: 0 },
{ ext: 'gif', headFlag: [71, 73, 70], offset: 0 },
{ ext: 'ico', headFlag: [0, 0, 1, 0], offset: 0 },
{ ext: 'bmp', headFlag: [66, 77], offset: 0 },
{ ext: 'webp', headFlag: [87, 69, 66, 80], offset: 8 },
];
for (let i = 0; i < IMAGE_FILE_HEADER.length; i++) {
const { headFlag, offset, ext } = IMAGE_FILE_HEADER[i];
if (isEqualFormatPrefix(imgUint8Array, headFlag, offset)) {
return ext;
}
}