Skip to main content

文件操作

常用对文件的操作:

  • 获取文件相关信息
  • 修改文件相关信息
  • 创建文件、目录
  • 删除文件、目录
  • 复制、移动和重命名
  • 遍历文件、目录
  • 匹配文件、目录
  • 创建和解压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;
}
}