Skip to content

Buffer与Stream之间转换

buffer与stream的操作

1. buffer的常用API

js
/* 创建buffer */
let buf = new Buffer(10);
console.log(buf.length);//10
//nodejs中不建议使用new Buffer
 
//  创建一个长度为10字节的空buffer
let buf2 = Buffer.alloc(10);
//创建空间并且清空为0
console.log(buf2.length);//10
//buffer大小确定后不能修改,因为他直接操作底层内存
console.log(buf2[0].toString(16));
//转为十六进制输出
 
let buf3 = Buffer.allocUnsafe(10);
//创建空间但不清空buffer

/* buffer转换为json或string */
let buf4 = Buffer.from('你好') // 将字符串转换为json
console.log(buf4.toJSON()) // { type: 'Buffer', data: [ 228, 189, 160, 229, 165, 189 ] }
console.log(buf4.toString()) // 你好
console.log(buf4.length) // 6 一个中文占3字节


/* 拼接buffer */
let buf5 = Buffer.from('hello')
let buf6 = Buffer.from('word')

// Buffer有一个静态方法 concat,用于拼接多个buffer为一个
let buf7 = Buffer.concat([buf5,buf6])
console.log(buf7.toString()); // helloword

/* 缓冲区裁剪slice */
// slice参数:开始位置,结束位置
console.log(buf8.toString()); // ell

/* 缓冲区拷贝copy (不常用) */
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])

2. stream常用

js
let fs = require("fs");
 
//创建可读流
let readF = fs.createReadStream("文件路径");
//创建可写流
let writeF = fs.createWriteStream("文件路径2");

readF.on("data",function(data){
    //写入可写流
   writeF.write(data);
});
 
//监听可读流关闭
readF.once("close",function(){
    //关闭可写流
    writeF.end();
});
 
 
//上面的方法太麻烦了所以。。。
readF.pipe(writeF);
//这句话表示上面的一片

3. 拷贝

js
const fs = require('fs')
let path = './index.html'
let target = './copy.html'
let read = fs.createReadStream(path)
 
let write = fs.createWriteStream(target)
read.pipe(write)

4. zip压缩

js
const http = require('http')
const fs = require('fs')
const zlib = require('zlib')
const htmlFilePath = './index.html'
http.createServer(
  function (req, res) {
    // res.writeHead(200, {"content-encoding": "gzip"})
    fs.createReadStream(htmlFilePath)
      // .pipe(zlib.createGzip())
      .pipe(res)
  }
).listen(8000)
http.createServer(
  function (req, res) {
    res.writeHead(200, {"content-encoding": "gzip"})
    fs.createReadStream(htmlFilePath)
    .pipe(zlib.createGzip())
    .pipe(res)
  }
).listen(8001)

压缩前 image.png 压缩后 image.png

5. stream 转 buffer

js
function streamToBuffer(stream) {  
  return new Promise((resolve, reject) => {
    let buffers = [];
    stream.on('error', reject);
    stream.on('data', (data) => buffers.push(data))
    stream.on('end', () => resolve(Buffer.concat(buffers))
  });
}

6. buffer 转 stream

js
let Duplex = require('stream').Duplex;
 
function bufferToStream(buffer) {  
  let stream = new Duplex();
  stream.push(buffer);
  stream.push(null);
  return stream;
}

7. buffer与stream互转

js
const fs = require('fs')
let Duplex = require('stream').Duplex;
 
 
let stream = new Duplex();
let b = new Buffer.from("hello")
stream.push(b);
stream.push(null);
console.log(b.toString())   // hello
let write = fs.createWriteStream('./copy2.js')
stream.pipe(write)

或者

js
var stream = require('stream');
// 创建一个bufferstream
var bufferStream = new stream.PassThrough();
//将Buffer写入
bufferStream.end(new Buffer('Test data.'));
//进一步使用
bufferStream.pipe(process.stdout)

8. Buffer 与字符编码

Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。

js
const buf = Buffer.from('runoob', 'ascii');

console.log(buf.toString('hex')); // 输出 72756e6f6f62

console.log(buf.toString('base64')); // 输出 cnVub29i

Node.js 目前支持的字符编码包括:ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。 utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。 utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。 ucs2 - utf16le 的别名。 base64 - Base64 编码。 latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。 binary - latin1 的别名。 hex - 将每个字节编码为两个十六进制字符。

9. buffer转换

Buffer对象可以与字符串之间相互转换,目前支持的字符串类型有如下几种: ASCIIUFTF-8UTF-16LE/UCS-2Base64BinaryHex

1)字符串转Buffer

字符串转buffer主要是通过构造函数完成的:

js
new Buffer(str, [encoding])

通过构造函数转换的Buffer对象,存储的只是一种编码类型,encoding参数不传递时,默认按照utf-8编码进行转码和存储。

一个Buffer内存储不同编码内容 若一个Buffer对象内,要存储不同编码的内容,可以通过write()方法实现:

js
buf.write(str, [offset], [length], [encoding])

注意: 由于可以不断写入内容到buffer对象中,并且每次写入可以指定编码,所以buffer对象中可以存储多种编码转化后的内容,需要小心的是,由于各种编码所用字节长度不同,将buffer反转回字符串时候需要谨慎处理。

2)Buffer转字符串

Buffer对象有一个toString()方法,可以将Buffer对象转换为字符串

js
buf.toString([encoding], [start], [end])

encoding不传默认为utf-8 startend可以指定局部转换还是全部转换,若buffer对象由多种编码写入,就需要在局部指定不同编码,才能转换回正常的编码。

3)Buffer不支持的编码类型

目前,Node的Buffer对象支持的编码类型有限,只有少数的几种编码类型可以在字符串和Buffer之间转换,为此,Buffer对象提供一个isEncoding()函数来判断编码是否支持转换。

js
Buffer.isEncoding(encoding) // 传入encoding(编码)会输出true/false,true表示支持转换,反之。

但是,GBK,GB2312、BIG-5都不支持转换。 若要转换,有两个第三方模块iconviconv-live都可以支持更多编码类型的转换,包括Windows 125系列,IOS-8859系列,IBM/DOS代码页系列,等等。。 其中iconv-live由纯js编写,iconv则由c++调用libiconv库完成,性能不如iconv