likes
comments
collection
share

Node.js中的文件操作

作者站长头像
站长
· 阅读数 16

在开始学习node.js之前我们先介绍一下buffer ===> 缓冲器

Buffer概念

Buffer是一个类似于数组的对象,用于表示固定长度的字节序列

Buffer本质是一段内存空间,专门来处理二进制数据。

Node.js中的文件操作

Buffer特点

  • 大小固定且无法调整
  • 性能较好,可直接对计算机内存进行操作
  • 每个元素的大小为1字节(byte),也就是8比特(bit)

Buffer的使用

Node.js 中创建 Buffer 的方式主要如下几种:

  1. Buffer.alloc()

     // 创建长度为 10 字节的Buffer,相当于申请了10字节的空间
     // alloc() 在申请空间的同时会将每个字节值置为0
     let buf = Buffer.alloc(10);
     // <Buffer 00 00 00 00 00 00 00 00 00 00>
    
  2. Buffer.allocUnsafe()

     // 创建了一个长度为 10 字节的Buffer,在创建的过程中不会将每个字节值置为0,那么也就意味着buffer中可能存在脏数据,所以这里是 Unsafe
     let buf = Buffer.allocUnsafe(10);
    
  3. Buffer.from()

     // 可以通过字符串或者数据创建Buffer
     // 通过字符串创建Buffer
     let buf = Buffer.from("hello");
     // <Buffer 68 65 6c 6c 6f>
     // 通过数组创建Buffer
     let buf= Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
     //<Buffer 69 6c 6f 76 65 79 6f 75>  十六进制
    

Buffer 与字符串的转化

调用toString()的方法将Buffer转换为字符串

 let buf= Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);
 console.log(buf.toString());
 ​

toString()默认是按照utf-8 编码方式进行转换

Buffer的读写

由于buffer是一个类似于数组的对象,所以可以通过[] 的方式对数据进行处理

 // 读取
 console.log(buf[0]);
 // 修改
 buf[1] = 97;

注意:

如果修改的数值超过 255 ,则超过的8位数据会被舍弃

一个utf-8的字符一般占3个字节

 buf[0] = 361;// 舍弃高位的数字  0001 0110 1001  => 0110 1001
 let buf = Buffer.from('你好');
 console.log(buf);
 // <Buffer e4 bd a0 e5 a5 bd> ===> 三个字节

fs模块

fs全称为file system,称之为文件系统,是Node.js 中的内置模块,可以对计算机的磁盘进行操作。

文件的写入

文件写入就是将 数据 保存到 文件 中,我们可以使用如下几个方法来实现该效果

方法说明
writeFile()异步写入
writeFileSync()同步写入
appendFile()/appendFileSync()追加写入
createWriteStreame()流式写入

writeFile()异步写入

JavaScript 主线程不会等待 writeFile() 的执行完成,也就是不会阻塞JavaScript主线程

语法: writeFile(file, data[, options], callback)

参数说明:

  • file 文件名
  • data 待写入的数据
  • option 选项设置(可选)
  • callback 写入的回调函数

返回值: undefined

 // require 是 Node.js 环境中的 ‘全局’ 变量,用来导入模块
 //将 『三人行,必有我师焉。』 写入到当前文件夹下的『座右铭.txt』文件中
 const fs = require('fs');
 fs.writeFile('./data.txt','三人行,必有我师焉。',err => {
   //如果写入失败,则回调函数调用时,会传入错误对象,如写入成功,会传入 null
   if (err) {
     console.log(err);
     return;
   }
   console.log("写入成功");
 })

writeFileSync()同步写入

JavaScript 主线程会等待 writeFileSync() 的执行完成,也就是会阻塞JavaScript主线程

语法: fs.writeFileSync(file, data[, options])

返回值:undefined

 const fs = require('fs');
 fs.writeFileSync('./data.text','hello');

appendFile / appendFileSync追加写入

writeFileSync() 与 writeFile() 对相同文件进行内容的写入时会对原有的数据进行覆盖,而不是追加数据

语法:

fs.appendFile(file, data[, options], callback)

fs.appendFileSync(file, data[, options])

返回值: 二者都为 undefined

 // 异步追加
 fs.appendFile('./data.txt','smart',err => {
   if (err) {
     console.log(err)
     return;
   }
   console.log("追加成功")
 })
 // 同步追加
 fs.appendFileSync('./data.txt','phone');

createWriteStream 流式写入

语法: fs.createWriteStream(path[, options])

参数说明:

  • path 文件路径
  • option 选项配置(可选)

返回值: Object

 let ws = fs.createWriteStream('./data.txt');
 ws.write('半亩方塘一鉴开\r\n');
 ws.write('天光云影共徘徊\r\n');
 ws.write('问渠那得清如许\r\n');
 ws.write('为有源头活水来\r\n');
 // 关闭通道
 ws.close();

程序打开一个文件时非常消耗资源的,而流式写入会创建一个通道,直到写入完毕才关闭通道ws.close(),以此来减少文件打开与关闭的次数。流式写入方式适用于 大文件写入或者频繁写入 的场景, writeFile 适合于 写入频率较低的场景

文件的读取

通过程序,从文件中读取数据

方法说明
readFile()异步读取
readFileSync()同步读取
createReadStream()流式读取

readFile异步读取

语法: fs.readFile(path[, options], callback)

参数说明:

  • path 被读取的文件路径
  • option 选项配置 (可选)
  • callback 回调函数

返回值: undefined

 const fs = require('fs');
 fs.readFile('./data.txt',(err,data) => {
   if (err) {
     console.log("读取失败");
     return;
   }
   // data 是成功读取文件数据,此时data是一个Buffer
   // 所以应调用toString() 方法,将其转会为字符串格式
   console.log(data.toString());
 })

readFileSync 同步读取

语法:fs.readFileSync(path[, options])

参数说明:

  • path 文件路径
  • options 选项配置

返回值:String || Buffer

 let data = fs.readFileSync('./data.txt');
 // 返回值 data 是一个 Buffer 
 // 要想得到字符串的形式需调用 toString() 方法
 console.log(data.toString()); 

createReadStream流式读取

语法:fs.createReadStream(path[, options])

参数说明:

  • path 文件路径
  • options 选项配置

返回值: Object

 // 创建流式读取对象
 let rs = fs.createReadStream('./data.txt');
 // 每次取出 65536Byte ≈ 64 KB 数据后执行一次data事件
 rs.on('data',message => {
   // 所得到的message依旧是Buffer ,所以想要得到字符串仍需调用 toString() 方法
   console.log(message.toString());
 })
 // end 事件,此事件是可选事件,用来监听流式读取的结束
 rs.on('end',() => {
   console.log('读取完成');
 })

文件的复制

我们可以利用流式读取与流式写入相配合进行文件的复制

 let fs = require('fs');
 ​
 // 文件的流式读取
 let rs = createReadStream('./data.txt');
 // 文件的流式写入
 let ws = createWriteStream('./newData.txt');
 ​
 // 给文件的流式读取添加 data 事件
 rs.on('data',message => {
   // 每读取一小块就写入一下块
   ws.write(message);
 })
 ​
 // 监听流式读取的结束
 rs.on('end',() => {
   console.log('读取完成');
 })

文件的移动与重命名

在 Node.js 中,我们可以使用 renamerenameSync 来移动或重命名 文件或文件夹

语法:

fs.rename(oldPath, newPath, callback)

fs.renameSync(oldPath, newPath)

参数说明:

  • oldPath 文件当前的路径
  • newPath 文件新的路径
  • callback 操作后的回调

无论移动文件也好还是文件的重命名也好,其实本质上都是文件的路径转移(从当前路径转移到目标路径)

异步操作

 fs.rename('./data.txt','./message.txt',(err) => {
   if (err) {
     console.log("移动失败");
     return;
   }
   console.log('移动完成');
 })

同步操作

 fs.renameSync('./data.txt','../master/user/newData.txt');

文件删除

在 Node.js 中,我们可以使用 unlinkunlinkSync 来删除文

语法:

fs.unlink(path, callback)

fs.unlinkSync(path)

参数说明:

  • path 文件路径
  • callback 操作后的回调
 const fs = require('fs');
 ​
 // 异步的文件删除
 fs.unlink('./data.txt',(err) => {
   if (err) {
     console.log("删除失败");
     return;
   }
   console.log('删除完成');
 })
 ​
 //同步的文件删除
 fs.unlinkSync('./data.txt')

其实更推荐还是用异步的fs.rm()或者同步的fs.rmSync() 去进行文件的删除

异步

 const fs = require('fs');
 fs.rm('./data.txt',(err) => {
   if (err) {
     console.log("删除失败");
     return;
   }
    console.log('删除完成');
 })

同步

 const fs = require('fs');
 fs.rm('./data.txt');

文件夹操作

方法说明
mkdir() / mkdirSync()创建文件夹
readdir() / readdirSync()读取文件夹
rmdir() / rmdirSync()删除文件夹

mkdir 创建文件夹

在 Node.js 中,我们可以使用mkdirmkdirSync来创建文件夹

语法:

fs.mkdir(path[, options], callback)

fs.mkdirSync(path[, options])

参数说明:

  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback 操作后的回调
 //异步创建文件夹
 fs.mkdir('./public',(err) => {
   if(err) throw err;
   console.log('创建成功');
 })
 ​
 //递归异步创建
 fs.mkdir('./public/a/b/c',{recursive:ture}, (err) => {
   if(err) throw err;
   console.log('递归创建成功');
 })
 ​
 //递归同步创建文件夹
 fs.mkdirSync('./x/y/z', {recursive: true});

readdir读取文件夹

在 Node.js 中,我们可以使用 readdirreaddirSync 来读取文件夹

语法:

fs.readdir(path[, options], callback)

fs.readdirSync(path[, options])

参数说明:

  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback 操作后的回调
 //异步读取
 fs.readdir('./',(err) => {
   if(err) throw err;
   console.log(data);
 })
 ​
 //同步读取
 let data = fs.readdirSync('./论语');
 console.log(data);

读取所得到的 data 是一个数组,数组中的每一个元素都是一个包含扩展类型的文件名

例如

Node.js中的文件操作

rmdir删除文件

在 Node.js 中,我们可以使用 rmdirrmdirSync 来删除文件夹

语法:

fs.rmdir(path[, options], callback)

fs.rmdirSync(path[, options])

参数说明:

  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback 操作后的回调
 //异步删除文件夹
 fs.rmdir('./page',err => {
   if(err) throw err;
   console.log('删除成功');
 })
 //异步递归删除文件夹  (不建议)
 fs.rm('./a',{recursive:true}, err => {
   if(err) {
     console.log(err);
 }
   console.log('递归删除')
 })
 //同步递归删除文件夹 (不建议)
 fs.rmdirSync('./x', {recursive: true})

递归删除时最好使用以下代码:

 fs.rm('./a',{recursive: true},err => {
    if(err) {
     console.log(err);
 }
   console.log('递归删除')
 })

查看文件资源的状态(属性信息)

在 Node.js 中,我们可以使用 statstatSync 来查看资源的详细信息

语法:

fs.stat(path[, options], callback)

fs.statSync(path[, options])

参数说明:

  • path 文件夹路径
  • options 选项配置( 可选 )
  • callback 操作后的回调

返回值:是一个包含文件资源状态信息的对象

 //异步获取状态
 fs.stat('./video.mp4',(err,data) => {
   if(err){
     console.log('操作失败');
     return;
   }
   console.log(data);
 }) 
 ​
 //同步获取状态
 let data = fs.statSync('./data.txt');

Node.js中的文件操作

结果值对象结构:

  • size 文件体积
  • birthtime 创建时间
  • mtime 最后修改时间
  • isFile 检测是否为文件
  • isDirectory 检测是否为文件夹
  • 等等。。。。。。

__dirname

__dirname是Node.js 中所内置的变量,它保存着当前文件所在目录的绝对路径,可以使用 __dirname 与文件名拼接成绝对路径。

 let data = fs.readFileSync(__dirname+'/data.txt');

特别注意:

当使用__dirname进行绝对路径的拼接时,就不可以在路径中出现./ 以及同等意义的路径

例如以下代码是错误的:

 // 这是一个错误的代码示例
 let data = fs.readFileSync(__dirname+'./data.txt');
 // 这也是一个错误的代码示例
 let data = fs.readFileSync(__dirname+'../data.txt');

path模块

path 模块提供了操作路径 的功能,我们将介绍如下几个较为常用的几个 API:

API说明
path.resove()拼接规范的绝对路径 (常用)
path.sep()获取操作系统的路径分隔符(``或/)
path.parse()解析路径并返回对象
path.basename()获取路径的基础名称
path.dirname()获取路径的目录名
path.extname()获得路径的扩展名

path.resove

 const fs = require('fs');
 const path = require('path');
 ​
 // 写法一:
 console.log(path.resove(__dirname,'data.txt'));
 // 写法二:
 console.log(path.resove(__dirname.'./data.txt'));

以下代码为错误写法:

 console.log(path.resove(__dirname,'/index.html'));

在这里的/data.txt中的 /是根路径,在进行路径拼接时会直接跳到盘符的根路径

Node.js中的文件操作

显然,这并非index.html文件的真实绝对路径。

path.parse

 let str = 'D:\nodeJS\pathCode\代码\path.js';
 console.log(path.parse(str));

Node.js中的文件操作

path.parse()方法的返回值是一个包含路径信息的对象