nodejs学习(二)Buffer、fs
一、 Buffer(缓冲区)
1. JavaScript 语言没有读取或操作二进制数据流的机制。 2. Node.js 中引入了 Buffer 类型使我们可以操作 TCP流 或 文件流。 3. Buffer 类型的对象类似于整数数组,但 Buffer 的大小是固定的、且在 V8 堆外分配物理内存。 Buffer 的大小在被创建时确定,且无法调整。( buf.length 是固定的,不允许修改 ) 4. Buffer 是全局的,所以使用的时候无需 require() 的方式来加载
1.Buffer的操作
• 使用Buffer保存字符串 let str = "你好"; let buf = Buffer.from(str , "utf-8"); • 创建指定大小的Buffer对象 let buf3 = Buffer.alloc(1024*8)
2.Buffer的转换
• Buffer与字符串间的转换 – 支持的编码: • ASCII、 UTF-8、 UTF-16LE/UCS-2、 Base64、Binary、 Hex – 字符串转Buffer • Buffer.from(str , [encoding]); – Buffer转字符串 • buf.toString([encoding] , [start] , [end]);
3.写入操作
• 向缓冲区中写入字符串
– buf.write(string[, offset[, length]][, encoding])
• 替换指定索引位置的数据
– buf[index]
• 将指定值填入到缓冲区的指定位置
– buf.fill(value[, offset[, end]][, encoding])
4.读取操作
• 将缓冲区中的内容,转换为一个字符串返回
– buf.toString([encoding[, start[, end]]])
• 读取缓冲区指定索引的内容
– buf[index]
5.其他操作
• 复制缓冲区
– buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
• 对缓冲区切片
– buf.slice([start[, end]])
• 拼接缓冲区
– Buffer.concat(list[, totalLength])
二、fs(文件系统)
• 在Node中,与文件系统的交互是非常重要的,服务器的本质就将本地的文件发送给远程的客户端
• Node通过fs模块来和文件系统进行交互
• 该模块提供了一些标准文件访问API来打开、读取、写入文件,以及与其互。
• 要使用fs模块,首先需要对其进行加载
– const fs = require("fs");
1.同步和异步调用
• fs模块中所有的操作都有两种形式可供选择同步和异步。
• 同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码。
• 异步文件系统不会阻塞程序的执行,而是
在操作完成时,通过回调函数将结果返回。
2.打开和关闭文件
• 打开文件
– fs.open(path, flags[, mode], callback)
– fs.openSync(path, flags[, mode])
• 关闭文件
– fs.close(fd, callback)
– fs.closeSync(fd)
3.打开状态
模式 说明 r 读取文件 , 文件不存在则出现异常 r+ 读写文件 , 文件不存在则出现异常 rs 在同步模式下打开文件用于读取 rs+ 在同步模式下打开文件用于读写 w 打开文件用于写操作 , 如果不存在则创建,如果存在则截断 wx 打开文件用于写操作, 如果存在则打开失败 w+ 打开文件用于读写, 如果不存在则创建, 如果存在则截断 wx+ 打开文件用于读写, 如果存在则打开失败 a 打开文件用于追加, 如果不存在则创建 ax 打开文件用于追加, 如果路径存在则失败 a+ 打开文件进行读取和追加, 如果不存在则创建该文件 ax+ 打开文件进行读取和追加,如果路径存在则失败
4.写入文件
• fs中提供了四种不同的方式将数据写入文件
– 简单文件写入
– 同步文件写入
– 异步文件写入
– 流式文件写入
1.简单文件写入
• fs.writeFile(file, data[, options], callback) • fs.writeFileSync(file, data[, options]) • 参数: – file 文件路径 – data 被写入的内容,可以是String或Buffer – options 对象,包含属性(encoding、 mode、flag) – callback 回调函数 //注意: - 该操作采用异步执行 - 如果文件已经存在则替换掉 - 默认写入的文件编码为utf8 - 回调函数有1个参数:err,表示在写入文件的操作过程中是否出错了。 - 如果出错了`err != null`,否则 `err === null`
demo:
/*
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符/要操作的文件路径
data <string> | <Buffer> | <TypedArray> | <DataView> | <Object> 要写入的数据
options <Object> | <string> 选项,可以对写入进行一些设置
encoding <string> | <null> 默认值: 'utf8'
mode <integer> 默认值: 0o666
flag <string> 请参阅对文件系统 flags 的支持。 默认值: 'w'。
callback <Function>
err <Error> | <AggregateError>
**/
//导入文件模块
var fs = require("fs");
//创建要写入的信息
var msg = "hello world! 你好,世界!";
var msg1 = "第二次写入会不会覆盖第一次的呢?"
//参数分别是文件路径,要写入的信息,编码,回调函数,回调函数需要有一个参数err
//这种是覆盖写入,文件不存在则新建文件后写入,文件存在则覆盖写入
fs.writeFile("./test.txt", msg1, "utf8", function (err) {
console.log("+++++++++++++++++++++" + err + "============")
if (err) {
console.log("写入文件出错,详细信息" + err)
throw err;
} else {
console.log("写入文件成功")
}
}
)
2.同步文件写入
• fs.writeSync(fd, buffer, offset, length[, position])
• fs.writeSync(fd, data[, position[, encoding]])
• 要完成同步写入文件,先需要通过openSync()打开文件来获取
一个文件描述符,然后在通过writeSync()写入文件。
• 参数
– fd 文件描述符,通过openSync()获取
– data 要写入的数据(String 或 Buffer)
– offset buffer写入的偏移量
– length 写入的长度
– position 写入的起始位置
– encoding 写入编码
demo:
/*
手动操作文件的步骤
1.打开文件:
fs.openSync(path[, flags[, mode]])
- path 要打开文件的路径
- flags 打开文件要操作的类型:默认为r
r:只读
w:可写的
- mode 设置文件的操作权限,一般不传(默认可读可写)
2.向文件中写入内容
fs.writeSync(fd, string[, position[, encoding]])
- fd 文件描述符
- string <string> | <Object> 要写入的内容被
- position <integer> 写入的其实位置
- encoding <string> 编码
返回: <number> 写入的字节数。
如果 string 是普通的对象,则它必须具有自有的(不是继承的)toString 函数属性。
3.保存关闭文件
fs.closeSync(fd)
fd <integer>关闭文件描述符。 返回 undefined。
*/
var fs = require("fs");
//w模式会覆盖写入
var fd = fs.openSync("test.txt", "w");
console.log("描述符:" + fd);
var length = fs.writeSync(fd, "这是同步写入的内容");
console.log("写入的长度:" + length);
fs.closeSync(fd);
3.异步文件写入
• fs.write(fd, buffer, offset, length[, position], callback)
• fs.write(fd, data[, position[, encoding]], callback)
• 要使用异步写入文件,先需要通过open()打开文件,然后在回
调函数中通过write()写入。
• 参数:
– fd 文件描述符
– data 要写入的数据(String 或 Buffer)
– offset buffer写入的偏移量
– length 写入的长度
– position 写入的起始位置
– encoding 写入编码
demo
/*
手动操作文件的步骤
1。异步打开文件:
fs.open(path[, flags[, mode]], callback)
- path 要打开文件的路径
- flags 打开文件要操作的类型:默认为r
r:只读
w:可写的
- mode 设置文件的操作权限,一般不传(默认可读可写)
- callback 回调有两个参数 (err, fd)。
err:错误对象,如果没有则为null
fd:文件描述符
返回值:该方法会返回一个文件描述符作为结果,我们可以通过该操作符来文件进行各种操作
fs.write(fd, buffer[, offset[, length[, position]]], callback)
用来异步写入一个文件
fs.close(fd[, callback])
-用来关闭文件
*/
var fs = require("fs");
fs.open("异步test.txt", "w", function (err, fd) {
//判断是否出错
if (!err) {
fs.write(fd, "这是异步写入内容", function (err) {
if (!err) {
console.log("写入成功");
fs.close(fd, function (err) {
if (!err) {
console.log("文件关闭成功");
} else {
console.log("文件关闭失败");
}
})
} else {
console.log("写入失败");
}
})
}
});
console.log("这个应该比异步的先执行完,对吧?")
4.流式文件写入
• 往一个文件中写入大量数据时,最好的方法之一 是使用流。 • 若要将数据异步传送到文件,首需要使用以下语 法创建一个Writable对象: – fs.createWriteStream(path[, options]) • path 文件路径 • options {encoding:"",mode:"",flag:""} • 一旦你打开了Writable文件流,就可以使用 write()方法来写入它,写入完成后,在调用end() 方法来关闭流。
demo
//流式写入
//创建可写流
/*
fs.createWriteStream(path[, options])
- 可以用来创建一个可写流
- path :文件路径
- options 配置参数
*/
var fs = require("fs");
var ws = fs.createWriteStream("writerstream.txt");
//可以通过监听流的打开和关闭事件来监听流的打开和关闭
/*
on(时间字符,回调函数)
-可以为对象绑定一个事件
once(事件字符串,回调函数)
- 可以为对象绑定一个一次性事件,该事件会将在出发一次后自动回滚失效
*/
ws.once("open", function () {
console.log("六打开了");
})
ws.on("close", function () {
console.log("流关闭了");
})
//通过ws像文件输入内容
ws.write("第一次输入");
ws.write("第二次输入");
ws.write("第三次输入");
//关闭流
ws.end()
5.读取文件
• fs中提供了四种读取文件的方式
– 简单文件读取
– 同步文件读取
– 异步文件读取
– 流式文件读取
1.简单文件读取
• fs.readFile(file[, options], callback) • fs.readFileSync(file[, options]) – 参数: • file 文件路径或文件描述符 • options <Object> | <String> – encoding <String> | <Null> 默认 = null – flag <String> 默认 = 'r' • callback 回调函数,有两个参数err 、 data
err 错误对象
data 返回一个buffer,要转成字符串需要data.tostring
demo1
var fs = require('fs');
fs.readFile("./test.txt", "utf-8", function (err, data) {
console.log("data:" + data);
console.log("err:" + err);
if (err) {
console.log("读取文件出错了:错误是" + err)
} else {
console.log("读取文件成功,以下为内容:")
console.log(data)
//当option的编码没有指定,返回的是一个buffer
// console.log(data.toString())
}
})
demo2:读取并写入零一个文件
var fs = require('fs'); fs.readFile("C:\\Users\\tjp40922\\Desktop\\a.png", function (err, data) { console.log("err:" + err); if (err) { console.log("读取文件出错了:错误是" + err) } else { console.log("读取文件成功") fs.writeFile("copy.png",data,function (err) { if (!err){ console.log("写入成功") }else { console.log("写入失败。。,原因是:"); console.log(err) } }) } })
2.同步文件读取
• fs.readSync(fd, buffer, offset, length,
position)
– 参数:
• fd 文件描述符
• buffer 读取文件的缓冲区
• offset buffer的开始写入的位置
• length 要读取的字节数
• position 开始读取文件的位置
3.异步文件读取
• fs.read(fd, buffer, offset, length,
position, callback)
– 参数:
• fd 文件描述符
• buffer 读取文件的缓冲区
• offset buffer的开始写入的位置
• length 要读取的字节数
• position 开始读取文件的位置
• callback 回调函数 参数err , bytesRead , buffer
4.流式文件读取
• 从一个文件中读取大量的数据时,最好的方法之一就是流式读取,这样将把一个文件作为Readable流的形式打开。
• 要从异步从文件传输数据,首先需要通过以下语法创建一个Readable流对象: – fs.createReadStream(path[, options]) • path 文件路径 • options {encoding:"",mode:"",flag:""}
• 当你打开Readable文件流以后,可以通过readable事件和read()请求,或通过data事件处理程序轻松地从它读出。
demo1
var fs = require("fs");
//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");
//监听流的开启和关闭
rs.once("open", function () {
console.log("可读流打开了");
})
rs.on("close", function () {
console.log("可读流关闭了");
})
//如果要读取一个刻度流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据
rs.on("data",function (data) {
console.log(data.toString())
})
demo2:从一个流到另一个流
var fs = require("fs");
//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");
var ws = fs.createWriteStream("tttt.txtt");
//监听流的开启和关闭
rs.once("open", function () {
console.log("可读流打开了");
})
rs.on("close", function () {
console.log("可读流关闭了");
// 在可读流关闭后也要关闭可写流
ws.end();
})
ws.once("open", function () {
console.log("可写流打开了");
})
ws.on("close", function () {
console.log("可写流关闭了");
})
//如果要读取一个刻度流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据
rs.on("data", function (data) {
console.log(data.toString())
//把可读流的数据写入可写流
//这边要注意,不能再这里关闭可写流,要不然只会昔日如一次
ws.write(data);
})
可以用更加简单的pipe
var fs = require("fs");
//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");
var ws = fs.createWriteStream("xdxx.txtt");
rs.pipe(ws);
6.其他操作
• 删除目录
– fs.rmdir(path, callback)
– fs.rmdirSync(path)
• 重命名文件和目录
– fs.rename(oldPath, newPath, callback)
– fs.renameSync(oldPath, newPath)
• 监视文件更改写入
– fs.watchFile(filename[, options], listener)
注意:
1. 异步操作无法通过 try-catch 来捕获异常,要通过判断 error 来判断是否出错。
2. 同步操作可以通过 try-catch 来捕获异常。
3. 不要使用 `fs.exists(path, callback)` 来判断文件是否存在,直接判断 error 即可
4. 文件操作时的路径问题
- 在读写文件的时候 './' 表示的是当前执行node命令的那个路径,不是被执行的js文件的路径
- __dirname, 表示的永远是"当前被执行的js的目录"
- __filename, 表示的是"被执行的js的文件名(含路径)"
5. error-first 介绍(错误优先)

浙公网安备 33010602011771号