【node.js】fs 模块

news/2024/11/19 19:35:25/

fs 文件系统

  • fs (file system) 文件系统,属于 node.js 的核心模块,用于操作文件(夹)

  • 使用 fs,需要先引入该模块

  • 核心模块的标识就是模块的名字,这里就是 fs

const fs = require('fs');

同步和异步调用

  • fs 模块中的操作有 2 种形式:同步、异步
  • 同步调用有可能阻塞程序的执行。同步执行会返回结果。
  • 异步调用不会阻塞程序的执行。异步执行是通过回调函数获取结果。

路径问题

  • 使用相对路径时,是相对项目根目录而言的
    就是说,在项目根目录不同的情况下,文件执行的结果会不一样
  • 开发中,尽量使用 __dirname 拼接路径

操作文件

writeFile[Sync]

fs.writeFile(path, data[, options], callBack):[创建文件并]写入数据

fs.writeFileSync(path, data[, options]):返回 undefined

  1. path:文件的路径
  2. data:要写入的数据
  3. option:配置对象
    • encoding:编码格式,默认为 utf8
    • flag:文件系统标志,默认为 'w'-设置数据;改为 'a'-追加数据
  4. callBack:回调函数,写入完成后调用;接收 1 个参数 err:出错时表示出错的信息,默认为 null
const fs = require('fs');
let data = '新写入的数据';// 同步写入数据
fs.writeFileSync('./writeFileSync.txt', data);// 异步写入数据
fs.writeFile('./writeFile.txt', data,err => console.log("err", err) // err null
);
  • 如果写入的文件不存在,会创建该文件并写入数据;
  • 如果写入的文件中原来就有内容,原来的内容会被覆盖
    如果想追加数据,可以设置 flag: 'a'
const fs = require('fs');
let data = '追加的内容';// 同步追加数据
fs.writeFileSync('./writeFileSync.txt', data, { flag: 'a' }); // 设置 flag 为 a// 异步追加数据
fs.writeFile('./writeFile.txt', data, { flag: 'a' }, // 设置 flag 为 aerr => console.log("err", err)
);

appendFile[Sync]

fs.appendFile(path, data[, options], callback):[创建文件并]追加数据

fs.appendFileSync(path, data[, options]:返回 undefined

  1. path:文件的路径
  2. data:写入的数据
  3. options:配置对象
    • encoding:默认为 'utf8',可以设为 "buffer"
    • flag:默认值为 'a'
  4. callback:回调函数,追加完成后调用;接收 1 个错误参数 err
const fs = require('fs');
let data = '追加的内容';// 同步追加数据
fs.appendFileSync('./appendFileSync.txt', data);// 异步追加数据
fs.appendFile('./appendFile.txt', data,err => console.log("err", err) // err null
);

readFile[Sync]

fs.readFile(path[, options], callback):读取文件数据

fs.readFileSync(path[, options]):返回文件数据

  1. path:文件的路径
  2. options:配置对象
    • encoding:数据的编码格式,默认为 null
      如果只设置 encoding 可以直接写成 String 格式
    • flag:文件系统标志,默认为 'r'
  3. callback:回调函数,接收 2 个参数:
    • err:出错信息,默认为 null
    • data:读取的数据
const fs = require('fs');// 同步读取数据
let data = fs.readFileSync('./writeFileSync.txt');
console.log("syncData", data); // <Buffer e6 96 b0...>
console.log("syncData + ''", data + ''); // 新写入的数据// 异步读取数据
fs.readFile('./writeFile.txt', (err, data) => {if (err) return console.log("err", err);console.log("data", data); // <Buffer e6 96 b0...>console.log("data + ''", data + ''); // 新写入的数据
});
  • 读取出来的数据默认是 Buffer 格式的,可以将其转成字符串形式
  • 读取成功 - errnulldata 为文件内容;读取失败 - err 为错误信息,dataundefined

unlink[Sync]

fs.unlink(path, callback):删除文件

fs.unlinkSync(path):返回 undefined

  • path:文件的路径
  • callBack:接收 1 个参数 err,默认为 null
const fs = require('fs');// 同步删除文件
fs.unlinkSync('./writeFileSync.txt');// 异步删除文件
fs.unlink('./writeFile.txt',err => console.log("err", err) // err null
);

操作目录

mkdir[Sync]

fs.mkdir(path[, options], callback):创建目录

fs.mkdirSync(path[, options]):返回 undefined

  1. path:新建的文件夹的路径

  2. options:配置对象

    • recursive:是否可以递归创建,默认为 false
  3. callback:回调函数,接收 1 个参数 err,默认为 null

const fs = require('fs');// 同步创建文件夹
fs.mkdirSync('./mkdirSync');// 异步创建文件夹
fs.mkdir('./mkdir',err => console.log("err", err) // err null
);

通过配置 option 可以实现递归创建文件夹

const fs = require('fs');// 同步创建递归文件夹
fs.mkdirSync('./reMkdirSync/mkdirSync', { recursive: true });// 异步创建递归文件夹 
fs.mkdir('./reMkdir/mkdir', { recursive: true },err => console.log("err", err) // err null
);

readdir[Sync]

fs.readdir(path[, options], callback):读取目录的内容

fs.readdirSync(path[, options]):返回目录的内容

  1. path:文件夹的路径
  2. options:配置对象
    • encoding:默认为 'utf8'、可设置为 'buffer'
    • withFileTypes:是否显现文件类型,默认为 false
  3. callback:回调函数,接收 2 个参数 errfiles - 目录的内容
const fs = require('fs');// 同步获取目录信息
let syncFiles = fs.readdirSync('./reMkdirSync');
console.log("syncFiles", syncFiles); // syncFiles [ 'mkdirSync' ]// 异步获取目录信息 
fs.readdir('./reMkdir',(err, files) => console.log("files", files) // files [ 'mkdir' ]
);

files 为数组,数组元素为该目录下的文件(夹)名

可以通过配置 option 显示文件的类型

const fs = require('fs');// 同步获取目录信息
let syncFiles = fs.readdirSync('./reMkdirSync', { withFileTypes: true });
console.log("syncFiles", syncFiles); // syncFiles [ Dirent { name: 'mkdirSync', [Symbol(type)]: 2 } ]// 异步获取目录信息
fs.readdir('./reMkdir', { withFileTypes: true },(err, files) => console.log("files", files) // files [ Dirent { name: 'mkdir', [Symbol(type)]: 2 } ]
);

files 为数组,数组元素为文件对象,对象属性为 name & type

rmdir[Sync]

fs.rmdir(path, callback):删除目录

fs.rmdirSync(path):返回 undefined

  1. path:文件夹的路径
  2. callback:回调函数,接收 1 个错误信息的参数 err,默认为 null
const fs = require('fs');// 同步删除目录
fs.rmdirSync('./mkdirSync');// 异步删除目录
fs.rmdir("./mkdir", err => console.log("err", err)); // err null

rm[Sync]

fs.rm(path[, options], callback):删除文件(夹)

fs.rmSync(path[, options]):返回 undefined

  1. path:文件夹的路径

  2. options:配置对象

    • force:为 true 时,如果 path 不存在,则异常将被忽略,默认为 false

    • recursive:如果为 true,则执行递归删除,默认为 false。在递归模式下,操作将在失败时重试

      maxRetries:表示重试次数,默认为 0(如果 recursive 选项为 false,则忽略此选项)

      retryDelay:重试之间等待的时间(以毫秒为单位),默认为 100(如果 recursive 选项为 false,则忽略此选项)

  3. callback:回调函数,接收 1 个参数 err,默认为 null

const fs = require("fs");// 同步、递归删除文件夹
fs.rmSync("./reMkdirSync", { recursive: true });// 异步、递归删除文件夹
fs.rm("./reMkdir", { recursive: true },err => console.log("err", err)
);

其他操作

rename[Sync]

fs.rename(oldPath, newPath, callback):文件(夹)重命名

fs.renameSync(oldPath, newPath):返回 undefined

  1. oldPath:文件的原路径
  2. newPath:文件的新路径
  3. callback:回调函数,接收一个参数 err,默认为 null
const fs = require('fs');// 同步重命名
fs.renameSync('./oldSync.txt', './newSync.txt');// 异步重命名
fs.rename('./old.txt', './new.txt',err => console.log("err", err) // err null
);

因为参数写的是路径,所以也可以在重命名的同时,把文件剪切到其他位置

const fs = require('fs');// 同步重命名 并剪切到 folder 文件夹下
fs.renameSync('./newSync.txt', './folder/newSync.txt');// 异步重命名 并剪切到 folder 文件夹下 
fs.rename('./new.txt', './folder/new.txt',err => console.log("err", err) // err null
);

如果 newPath 已经存在,则它将被覆盖。 如果在 newPath 中有目录,则会引发错误

const fs = require('fs');// 同步剪切 并覆盖同名文件
fs.renameSync('./folder/newSync.txt', './newSync.txt');// 异步剪切 并覆盖同名文件
fs.rename('./folder/new.txt', './new.txt',err => console.log("err", err)
);

existsSync

fs.existsSync(path):查看文件(夹)是否存在

  1. path:文件的路径
  • 如果文件存在,则返回 true;否则返回 false
const fs = require('fs');let result = fs.existsSync('./writeFile.txt');
console.log("result", result); // result false
  • 该操作的同步方法已被弃用

stat[Sync]

fs.stat(path[, options], callback):获取文件状态

fs.statSync(path[, options]):返回文件状态

  1. path:文件的路径

  2. options:对获取操作的设置

    • bigintstatus 中的数值是否为 bigint,默认为 false
  3. callBack:接收 2 个参数:

    • err:错误信息,默认为 null
    • status:状态对象 fs.Stats ,该对象中保存了当前对象状态的相关信息。eg:大小size、创建时间birthtime
  • 调用 isDirectory 方法可以查看当前对象是否为目录
  • 调用 isFile 方法可以查看当前对象是否为文件
const fs = require('fs');let syncStatus = fs.statSync('./newSync.txt');
console.log("syncStatus", syncStatus); // syncStatus Stats {...}
console.log("syncStatus.isDirectory()", syncStatus.isDirectory()); // false -- 是否为目录
console.log("syncStatus.isFile()", syncStatus.isFile()); // true -- 是否为文件fs.stat('./new.txt', (err, status) => {if (err) return console.log("err", err); // 如果该文件不存在,则报错console.log("status", status); // status Stats {...}console.log("status.isDirectory()", status.isDirectory()); // falseconsole.log("status.isFile()", status.isFile()); // true
});

truncate[Sync]

fs.truncate(path[, len], callback):截取文件内容

fs.truncateSync(path[, len]):返回 undefined

  1. path:文件的路径
  2. len:将文件数据截到指定大小 (byte),默认为 0
  3. callback:回调函数,接收 1 个参数 err,默认为 null
const fs = require('fs');// 同步截取文件
fs.truncateSync('./newSync.txt', 5);// 异步截取文件
fs.truncate('./new.txt', 5,err => console.log("err", err)
);
  • 注意这里,一个中文字符占 2 / 3 个字节,所以截取指定字节后,可能会出现乱码

watchFile

fs.watchFile(filename[, options][, listener]):监听文件数据的变化

  1. filename:文件的路径

  2. options:配置对象

    • bigint:默认为 false

    • persistent:只要正在监视文件,进程是否应继续运行。默认为 true

    • interval:监听的间隔时间,默认为 5007

  3. listener:回调函数,监听的文件被修改后调用,接收 2 个参数:

    • current:文件当前的状态,是 fs.status 对象

    • previous:文件修改前的状态,也是 fs.status 对象

  • 返回值:fs.StatWatcher 对象,存储着一些监听的信息。eg:大小size
const fs = require('fs');let wf = fs.watchFile('new.txt', (current, previous) => {console.log('文件当前大小' + current.size);console.log('文件先前大小' + previous.size);
});
console.log("wf", wf);

watch

fs.watch(filename[, options][, listener]):监听文件(夹)变化(改动数据 & 移动 / 重命名)

  1. filename:文件(夹)路径
  2. options:配置对象
    • encoding:指定用于传给监听器的文件名的字符编码
      如果只设置 encoding,可以直接写成 String 形式
    • persistent:只要正在监视文件,进程是否应继续运行。默认为 true
    • recursive:是应监视所有子目录,还是仅监视当前目录。默认为 false(仅在 macOS 和 Windows 上受支持)
  3. listener:回调函数,接收 2 个参数:
    • eventType:参数值为 rename / change
    • filename:触发事件的文件(夹)名称
const fs = require('fs');fs.watch('./new.txt', (eventType, filename) => {console.log("eventType", eventType);console.log("filename", filename);
});
  • 修改文件的数据时,会输出:eventType change filename new.txt
  • 修改文件名 / 删除文件时,会输出:eventType rename filename new.txt
    修改文件名 / 删除文件之后,监听事件失效

流式文件写入 & 读取

流式文件写入 / 读取适合操作大文件

流式写入

createWriteStream

① 创建可写流:fs.createWriteStream(path[, options])

  1. path:文件路径
  2. options:配置对象
    • flags:文件系统标志,默认值为 'w'
    • encoding:数据的编码格式,默认为 utf8
  • 返回值:WriteStream 对象
const fs = require('fs');
let ws = fs.createWriteStream('./WS.txt');
  • 创建可写流后,可写流会自动开启,写入完成后需要手动关闭

写入 - write

② 写入数据:ws.write(data)

  1. data:需要写入的数据
const fs = require('fs');
let ws = fs.createWriteStream('./WS.txt');let content = '需要写入的内容';
ws.write(content);
ws.write('  追加的内容');

监听 - open & close 事件

③ 可以通过监听流的 openclose 事件来监听流的开关

因为 openclose 操作都只会出现一次,所以这里使用 once() 绑定事件

const fs = require('fs');
let ws = fs.createWriteStream('./WS.txt');let content = '需要写入的内容';
ws.write(content);
ws.write('  追加的内容');// 监听 open 事件
ws.once('open', _ => console.log('可写流打开了'));
// 监听 close 事件
ws.once('close', _ => console.log('可写流关闭了'));
  • 可以看见,只打印了 可写流打开了,因为可写流会自动开启,但不会自动关闭

关闭 - close / end

④ 关闭可写流:ws.close([callBack]) / ws.end([callBack])

  • callBack:回调函数,关闭可写流后调用;接收一个参数 err,默认为 null
const fs = require('fs');
let ws = fs.createWriteStream('./WS.txt');let content = '需要写入的内容';
ws.write(content);
ws.write('  追加的内容');ws.once('open', _ => console.log('可写流打开了'));// 调用 close 方法关闭可写流
ws.close(_ => console.log('可写流关闭了'));

流式读取

createReadStream

① 创建可读流:fs.createReadStream(path)

  1. path:文件的路径
  • 返回值:ReadStream 对象
const fs = require('fs');
let rs = fs.createReadStream('./WS.txt');
  • 创建可读流后,可读流会自动开启。但此时还不会读取数据!
  • 我们可以通过 rs.readableFlowing 查看数据是否已经在读取
    null-未读取、true-正在读取、false-读取完,已关闭

开启 - data 事件

② 给可读流绑定一个 data 事件,绑定完毕后,会自动开始读取数据。每次最多读取 65536 byte

回调函数接收一个参数 datadata 就是可读流传出的数据(二进制数据)

const fs = require('fs');
let rs = fs.createReadStream('./WS.txt');rs.on('data', data => {console.log('开始读取数据');console.log("data", data);
});
  • 读取完后,可读流会自动关闭

监听 open & close 事件

③ 可以通过监听流的 openclose 事件来监听流的开关

因为 openclose 操作都只会出现一次,所以这里使用 once() 绑定事件

const fs = require('fs');
let rs = fs.createReadStream('./WS.txt');// 监听 open & close 事件
rs.once('open', _ => console.log('readStream open!'));
rs.once('close', _ => console.log('readStream close!'));rs.on('data', data => {console.log('开始读取数据');console.log("data", data);
});

配合可写流使用

const fs = require('fs');
let rs = fs.createReadStream('./rs.txt');
let ws = fs.createWriteStream('./ws.txt');// 监听 data 事件,开启可读流
rs.on('data', data => {console.log('开始读取数据');console.log("data", data + ""); // 打印可读流里面的数据ws.write(data); // 写入读取到的数据
});// 监听可读流
rs.once('open', _ => console.log('ReadStream open!'));
rs.once('close', _ => {console.log('ReadStream close!');ws.end(); // 可读流关闭后,手动关闭可写流
});// 监听可写流
ws.once('open', _ => console.log('WriteStream open!'));
ws.once('close', _ => console.log('WriteStream close!'));

管道 pipe

  • pipe():可以将可读流中的数据,直接传到可写流中
const fs = require('fs');
let rs = fs.createReadStream('./WS.txt');
let ws = fs.createWriteStream('./123.txt');rs.pipe(ws); // 开启可读流,写入读取到的数据,写入完毕后自动关闭可写流// 监听可读流
rs.once('open', _ => console.log('ReadStream open!'));
rs.once('close', _ => console.log('ReadStream close!'));// 监听可写流
ws.once('open', _ => console.log('WriteStream open!'));
ws.once('close', _ => console.log('WriteStream close!'));

同步文件写入

openSync

① 打开文件:fs.openSync(path[, flags])

  1. path:文件路径

  2. flags:文件系统标志

    • 'r' (read):读取数据。如果文件不存在,则报错(默认)

    • 'w' (write):写入数据。如果文件不存在,则创建该文件;否则覆盖文件原内容

    • 'a' (add):追加数据。如果文件不存在,则创建该文件;否则追加内容

  • 返回值:表示文件描述符的整数 fd
const fs = require('fs');// 打开文件
let fd = fs.openSync('new.txt', 'w');
console.log("fd"); // fd 3

writeSync

② 写入内容:fs.writeSync(fd, data[, position[, encoding]])

  1. fd:表示文件描述符的整数
  2. data:需要写入的内容
  3. position:开始写入的位置(eg:2 → 空两位再开始写数据)
  4. encoding:写入的数据编码格式,默认为 utf8
  • 返回值:写入的字节数
  • 如果 data 是普通的对象,则它必须具有自己的(不是继承的)toString 方法
const fs = require('fs');let fd = fs.openSync('hello.txt', 'w');// 写入数据
let len = fs.writeSync(fd, 'hello superman');
console.log("len", len); // len 14

closeSync

③ 关闭文件:fs.closeSync(fd)

  1. fd:表示文件描述符的整数
const fs = require('fs');let fd = fs.openSync('hello.txt', 'w');
fs.writeSync(fd, 'hello superman');// 关闭文件
fs.closeSync(fd);

写入完成后,需要关闭文件,避免资源的浪费

异步文件写入

open

① 打开文件:fs.open(path[, flags], callback)

  1. path:文件的路径

  2. flags:文件系统标志

    • 'r' (read):读取数据。如果文件不存在,则报错(默认)

    • 'w' (write):写入数据。如果文件不存在,则创建该文件;否则覆盖文件原内容

    • 'a' (add):追加数据。如果文件不存在,则创建该文件;否则追加内容

  3. callBack:回调函数,打开文件后调用,接收 2 个参数:

    • err:错误信息,默认为 null

    • fd:表示文件描述符的整数

const fs = require('fs');// 打开文件
fs.open('hello.txt', 'w',_ => console.log(arguments) // [Arguments] { '0': null, '1': 3 }
);

write

② 写入数据:fs.write(fd, string[, position[, encoding]], callback)

  1. fd:表示文件描述符的整数

  2. string:需要写入的内容

  3. position:开始写入的位置(eg:2 → 空两位再开始写数据)一般不写

  4. encoding:写入的数据编码格式,默认为 utf8,一般不写

  5. callBack:回调函数,接收 3 个参数:

    • err:错误信息,默认为 null

    • len:写入的字节数

    • data:写入的数据内容

const fs = require('fs');// 打开文件
fs.open('hello.txt', 'w', (err, fd) => {// 写入数据fs.write(fd, '异步写入的内容', _ => {console.log(arguments); // [Arguments] { '0': null, '1': 21, '2': '异步写入的内容' }});
});

close

③ 关闭文件:fs.close(fd, callBack)

  1. fd:表示文件描述符的整数
  2. callBack:回调函数,接收 1 个异常参数 err,默认为 null
const fs = require('fs');// 打开文件
fs.open('hello.txt', 'w', function (err, fd) {if (err) return console.log("err", err);console.log("open");// 写入数据fs.write(fd, '异步写入的内容', err => {if (err) return console.log("err", err);console.log("write");// 关闭文件fs.close(fd, function (err) {if (err) return console.log("err", err);console.log('close');});});
});

http://www.ppmy.cn/news/238881.html

相关文章

node的fs模块

node的fs模块 前几天一个月薪35k的兄弟&#xff0c;给我推了一个人工智能学习网站&#xff0c;看了一段时间挺有意思的。包括语音识别、机器翻译等从基础到实战都有&#xff0c;很详细&#xff0c;分享给大家。大家及时保存&#xff0c;说不定啥时候就没了。 一、简述 fs模块…

fs概述及基本使用

PRI是实际物理线路, sip trunk是ip虚拟连接 ACD(Automatic Call Distributor) 自动呼叫分配,也叫智能选择座席. ACD掌握坐席状态&#xff0c;是否分配呼叫 若acd未拦截&#xff0c;则sip终端代理&#xff08;话机&#xff09;能判别当前状态、指示用户放音、回复响应 IVR(In…

FSL5.0使用教程

关于如何在Windows中安装可以参考我的博客&#xff1a;window下安装脑图像处理软件FSL 如有问题&#xff0c;欢迎加入交流群共同探讨&#xff1a;515574325 官方文档&#xff1a;https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FslOverview 我用的是Ubantu16.04,安装的是fsl-compl…

电销机器人价格费用如何?对比过才知道

电话营销作为当前企业开发客户最直接的一种营销方式&#xff0c;虽然电话营销很多缺点有客户难寻、人员流动大、培训时间长、销售成本高等&#xff0c;但是丝毫不影响企业用它来拓客&#xff0c;而电销机器人就是针对这些出现的问题而研发&#xff0c;专门针对电话销售的人员拓…

小宝机器人_家用教育智能机器人

小宝机器人—"打令"机器人 小宝机器人官网排名小宝机器人官网排名下面我来为大家推荐小宝机器人高性价比的大品牌商家可以找茂名市齐聚机器人有限公司&#xff0c;经营各种智能产品的,一起来看看吧 小宝机器人它不仅是段子手、小管家、还是一只能行走会卖萌的小可爱…

一个智能机器人的外观设计需要花费多少钱?

设计一个智能机器人外观设计需要花费多少钱?针对一般中小企业来讲&#xff0c;设计成本相对性比较高。机器人的设计成本为10W—12W&#xff0c;加之接着的出模等。成本过高&#xff0c;早期担负的成本也非常大。 因而&#xff0c;很多初创公司会选择自己做机器人外观设计&…

ai人工智能机器人

随着时间的推移&#xff0c;人工智能的发展越来越成熟&#xff0c;智能时代也离人们越来越近&#xff0c;近几年人工智能越来越火爆&#xff0c;人工智能的应用已经开始渗透到各行各业&#xff0c;与生活交融&#xff0c;成为人们无法拒绝&#xff0c;无法失去的一个重要存在。…

智能语音机器人,铁打的机器,流水的价格

现如今人工智能大热&#xff0c;越来越多的产品打上了智能的标签来涨价&#xff0c;所以&#xff0c;当人们一听到“智能”两个字的时候&#xff0c;会第一时间觉得贵。那么&#xff0c;智能电话机器人&#xff0c;这种帮助企业在电销过程中筛选客户的工具&#xff0c;价格到底…