[Node.js] 03 - Buffer, Stream and File IO
Buffer类
创建 Buffer 类
// 创建一个长度为 10、且用 0 填充的 Buffer。 const buf1 = Buffer.alloc(10); // 创建一个长度为 10、且用 0x1 填充的 Buffer。 const buf2 = Buffer.alloc(10, 1);
------------------------------------------------------------------ // 创建一个长度为 10、且未初始化的 Buffer。 // 这个方法比调用 Buffer.alloc() 更快, // 但返回的 Buffer 实例可能包含旧数据, // 因此需要使用 fill() 或 write() 重写。 const buf3 = Buffer.allocUnsafe(10);
------------------------------------------------------------------- // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。 const buf4 = Buffer.from([1, 2, 3]); // 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。 const buf5 = Buffer.from('tést'); // 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。 const buf6 = Buffer.from('tést', 'latin1');
写 Buffer类
buf = Buffer.alloc(256); len = buf.write("www.runoob.com"); console.log("写入字节数 : "+ len);
读 Buffer类
1. 查看其中内容:
一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
const buf = Buffer.from('runoob', 'ascii'); // 输出 72756e6f6f62 console.log(buf.toString('hex'));
ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。 utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。 utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。 ucs2 - utf16le 的别名。 base64 - Base64 编码。 latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。 binary - latin1 的别名。 hex - 将每个字节编码为两个十六进制字符。
2. 转换为 JSON 对象:
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); // 隐式地调用了 toJSON() // 输出: {"type":"Buffer","data":[1,2,3,4,5]} console.log(json); const copy = JSON.parse(json, (key, value) => { return value && value.type === 'Buffer' ? Buffer.from(value.data) : value; }); // 输出: <Buffer 01 02 03 04 05> console.log(copy);
- JSON.parse
服务器 --> 字符串 --> JavaScript 对象。
JSON.parse(text[, reviver])
对text进行parse后,再进行一次处理,示范试下:
<script> var text = '{ "name":"Runoob", "initDate":"2013-12-14", "site":"www.runoob.com"}';
var obj = JSON.parse(text, function (key, value) { if (key == "initDate") { return new Date(value); } else { return value; }}); document.getElementById("demo").innerHTML = obj.name + "创建日期:" + obj.initDate; </script>
缓冲区合并
/*
* Buffer.concat(list[, totalLength])
*/
var buffer1 = Buffer.from(('菜鸟教程')); var buffer2 = Buffer.from(('www.runoob.com')); var buffer3 = Buffer.concat([buffer1,buffer2]); console.log("buffer3 内容: " + buffer3.toString());
缓冲区比较
var buffer1 = Buffer.from('ABC'); var buffer2 = Buffer.from('ABCD'); var result = buffer1.compare(buffer2); // 是比较大小 if(result < 0) { console.log(buffer1 + " 在 " + buffer2 + "之前"); }else if(result == 0){ console.log(buffer1 + " 与 " + buffer2 + "相同"); }else { console.log(buffer1 + " 在 " + buffer2 + "之后"); }
缓冲区拷贝
/**
* buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) */
var buf1 = Buffer.from('abcdefghijkl'); var buf2 = Buffer.from('RUNOOB'); //将 buf2 插入到 buf1 指定位置上 buf2.copy(buf1, 2); console.log(buf1.toString()); Result: abRUNOOBijkl
缓冲区裁剪
/**
* buf.slice([start[, end]]) */
var buffer1 = Buffer.from('runoob');
// 剪切缓冲区 var buffer2 = buffer1.slice(0,2); console.log("buffer2 content: " + buffer2.toString()); Result: buffer2 content: ru
缓冲区长度
var buffer = Buffer.from('www.runoob.com'); // 缓冲区长度 console.log("buffer length: " + buffer.length);
Node.js 文件系统
包括:文件操作和流操作
文件操作
Node 导入文件系统模块(fs),有异步、同步读取文件之分:
var fs = require("fs"); // 1.异步读取 fs.readFile('input.txt', function (err, data) { if (err) { return console.error(err); } console.log("异步读取: " + data.toString()); }); // 2.同步读取 var data = fs.readFileSync('input.txt'); console.log("同步读取: " + data.toString()); console.log("程序执行完毕。");
- 同步也可能会影响异步:
如下是异步读文件。However, “线程delay 4秒会cover到这个异步,竟然使异步也delay 4sec.
- 删除文件:unlink
以下接口参见原文:
- readFile(),readFileSync()
- writeFile(),writeFileSync()
- exists(path, callback)
- mkdir(),writeFile(),readFile()
- mkdirSync(),writeFileSync(),readFileSync()
- readdir(),readdirSync()
- stat()
这里再详述若干有意思的接口:
watchfile方法监听一个文件,如果该文件发生变化,就会自动触发回调函数。
var fs =require('fs'); var path =require('path'); var file1 =path.resolve('/test1/one.txt');
//监视文件 //当前程序没有结束,一直在监视文件 var listener=function(curr,prev){ console.log('监视文件发生修改'); };
fs.watchFile(file1, {interval:100}, listener);
//取消监视文件 //当前程序程序结束退出 fs.unwatchFile(file1,listener);
文件部分内容放入buffer中,提高了文件处理效率。
文件流操作
Stream 有四种流类型:
-
Readable - 可读操作。
-
Writable - 可写操作。
-
Duplex - 可读可写操作.
-
Transform - 操作被写入数据,然后读出结果。
所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:
-
data - 当有数据可读时触发。
-
end - 没有更多的数据可读时触发。
-
error - 在接收和写入过程中发生错误时触发。
-
finish - 所有数据已被写入到底层系统时触发。
读取流
触发机制:Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。
var fs = require("fs"); var data = ''; // 创建可读流 var readerStream = fs.createReadStream(__dirname + 'input.txt', 'utf8'); // readerStream.setEncoding('UTF8'); // 一处编码方式设置即可
// 处理流事件 --> data, end, and error readerStream.on('data', function(chunk) { data += chunk; }); readerStream.on('end',function(){ console.log(data); }); readerStream.on('error', function(err){ console.log(err.stack); }); console.log("程序执行完毕");
写入流
var fs = require("fs"); var data = '菜鸟教程官网地址:www.runoob.com'; // 创建一个可以写入的流,写入到文件 output.txt 中 var writerStream = fs.createWriteStream('output.txt'); // 使用 utf8 编码写入数据 writerStream.write(data,'UTF8'); // 标记文件末尾 writerStream.end(); // 处理流事件 --> data, end, and error writerStream.on('finish', function() { console.log("写入完成。"); }); writerStream.on('error', function(err){ console.log(err.stack); }); console.log("程序执行完毕");
管道操作
管道流
简单的复制内容的操作
var fs = require("fs"); // 创建一个可读流 var readerStream = fs.createReadStream('input.txt'); // 创建一个可写流 var writerStream = fs.createWriteStream('output.txt'); // 管道读写操作 // 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中 readerStream.pipe(writerStream); console.log("程序执行完毕");
链式流
链式流一般用于管道操作。
读文件 --> 压缩文件。
var fs = require("fs"); var zlib = require('zlib'); // 压缩 input.txt 文件为 input.txt.gz fs.createReadStream('input.txt') .pipe(zlib.createGzip()) .pipe(fs.createWriteStream('input.txt.gz')); console.log("文件压缩完成。");
读文件 --> 解压文件。
var fs = require("fs"); var zlib = require('zlib'); // 解压 input.txt.gz 文件为 input.txt fs.createReadStream('input.txt.gz') .pipe(zlib.createGunzip()) .pipe(fs.createWriteStream('input.txt')); console.log("文件解压完成。");
os模块
返回当前操作系统的换行符
const fs = require(`fs`); // bad fs.readFile('./myFile.txt', 'utf8', (err, data) => { data.split('\r\n').forEach(line => { // do something }); }); // good const os = require('os'); fs.readFile('./myFile.txt', 'utf8', (err, data) => { data.split(os.EOL).forEach(line => { // do something }); });
os.tmpdir
方法返回操作系统默认的临时文件目录。
os.arch
方法返回当前计算机的架构。
require(`os`).arch() // "x64"
列出当前系列的所有IP地址
var os = require('os'); var interfaces = os.networkInterfaces(); for (item in interfaces) { console.log('Network interface name: ' + item);
for (att in interfaces[item]) { // 看上去interface是个map var address = interfaces[item][att]; console.log('Family: ' + address.family); console.log('IP Address: ' + address.address); console.log('Is Internal: ' + address.internal); console.log(''); } console.log('=================================='); }
(完)