Buffer

什么是Buffer?

Buffer 是Node.js API 的⼀部分 主要用来处理二进制文件流和TCP流的文件缓存区 内存缓冲区
优势:Buffer 使用堆外内存,不占用堆内存
形式上是字节的形式,8位⼀个字节|0000 0001|0010 0011|0100 0101|0110 0111|

  1. // Buffer 类是全局的对象,可以直接使⽤,官⽅推荐显式引⽤
  2. import { Buffer } from 'buffer';
  3. // new Buffer() 建议弃⽤
  4. Buffer.from()
  5. Buffer.from(array)
  6. Buffer.from(arrayBuffer[, byteOffset[, length]])
  7. Buffer.from(buffer)
  8. Buffer.from(object[, offsetOrEncoding[, length]])
  9. Buffer.from(string[, encoding])
  1. Buffer.alloc(size[, fill[, encoding]])
  2. //fill:默认0, encoding默认值: 'utf8'
  3. // 创建⻓度为 10 的以零填充的缓冲区。
  4. const buf1 = Buffer.alloc(10);
  5. // 创建⻓度为 10 的缓冲区,
  6. // 使⽤值为 `1` 的字节填充。
  7. const buf2 = Buffer.alloc(10, 1);
  8. const buf3 = Buffer.allocUnsafe(10);
  9. // allocUnsafe 优劣
  10. fs.readFile(path[, options], callback)
  11. callback <Function>
  12. data <string> | <Buffer>

Buffer 的应用场景

  1. const fs = require('fs');
  2. const path = require('path');
  3. // function to encode file data to base64 encoded string
  4. function base64_encode(file) {
  5. let bitmap = fs.readFileSync(file);
  6. return Buffer.from(bitmap).toString('base64');
  7. }
  8. // function to create file from base64 encoded string
  9. function base64_decode(base64str, file) {
  10. let bitmap = Buffer.from(base64str, 'base64');
  11. fs.writeFileSync(file, bitmap);
  12. console.log('******** File created from base64 encoded string********');
  13. }
  14. let base64str = base64_encode(path.join(__dirname, './play.png'));
  15. console.log(base64str);
  16. base64_decode(base64str, path.join(__dirname, 'copy.png'));
  1. const fs = require('fs');
  2. const path = require('path');
  3. //
  4. const rs = fs.createReadStream(path.join(__dirname, '1.txt'));
  5. let data = '';
  6. rs.on('data', function (chunk) {
  7. data += chunk;
  8. });
  9. rs.on('end', function () {
  10. console.log(data);
  11. });

乱码的产生

  1. const fs = require('fs');
  2. const path = require('path');
  3. // fs.createReadStream 的 options 中 highWaterMark默认是64k
  4. const rs = fs.createReadStream(path.join(__dirname, '1.txt'),{ highWaterMark: 11 });
  5. let data = '';
  6. rs.on('data', function (chunk) {
  7. data += chunk;
  8. });
  9. rs.on('end', function () {
  10. console.log(data);
  11. });

解决⽅式1

  1. // 可读流有⼀个设置编码的⽅法setEncoding():
  2. // 默认情况下没有设置字符编码,流数据返回的是 Buffer 对象。
  3. // 如果设置了字符编码,则流数据返回指定编码的字符串
  4. let rs = fs.createReadStream('test.md', {highWaterMark: 11});
  5. rs.setEncoding('utf8');

解决⽅式2

  1. // 将⼩Buffer 拼接成⼤Buffer 对象
  2. let chunks = [];
  3. let size = 0;
  4. res.on('data', function (chunk) {
  5. chunks.push(chunk);
  6. size += chunk.length;
  7. });
  8. res.on('end', function () {
  9. let buf = Buffer.concat(chunks, size);
  10. let str = iconv.decode(buf, 'utf8');
  11. console.log(str);
  12. });

Stream

什么是Stream

nodejs Stream类型

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操 作被写⼊数据,然后读出结果。

    pipe 管道 在管道中间对流进⾏处理
    ```javascript // src/pipe.js 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(“⽂件压缩完成。”);

  1. pipe实现原理
  2. ```javascript
  3. Readable.prototype.pipe = function(dest, options) {
  4. const src = this;
  5. src.on('data', ondata);
  6. function ondata(chunk) {
  7. const ret = dest.write(chunk);
  8. if (ret === false) {
  9. ...
  10. src.pause();
  11. }
  12. }
  13. ...
  14. // 保持链式调⽤
  15. return dest;
  16. };

使⽤流 完整读⽂件的优势
不需要读取完整个文件
image.png

Events 事件触发器

Node.js 的⼤部分核心API 都是围绕惯用的异步事件驱动架构构建的
常⽤API

  1. emitter.on(eventName, listener)
  2. emitter.once(eventName, listener)
  3. emitter.off(eventName, listener)
  4. emitter.emit(eventName[, ...args])
  5. /*
  6. emitter.addListener(eventName, listener)
  7. emitter.removeListener(eventName, listener)
  8. */
  1. //简单实现上述⽅法
  2. class MyEventsEmitter{
  3. constructor(){
  4. this.events = {};
  5. }
  6. // 绑定事件
  7. on(event, cbFn){
  8. if(!this.events[event]){
  9. this.events[event] = [];
  10. }
  11. this.events[event].push(cbFn);
  12. return this;
  13. }
  14. // 解绑事件
  15. off(event, cbFn){
  16. if (this._events[type]) {
  17. // 过滤掉该事件
  18. this._events[type] =
  19. this._events[type].filter(fn => {
  20. return fn !== cbFn
  21. });
  22. }
  23. }
  24. // 只响应⼀次
  25. once(event, cbFn){
  26. const onlyonce = (...args)=> {
  27. this.off(event, cbFn);
  28. cbFn.apply(this, args);
  29. }
  30. this.on(event, onlyonce);
  31. return this;
  32. }
  33. // 触发监听事件
  34. emit(event, ...args){
  35. if (this.events[event]) {
  36. this.events[event].forEach(fn => fn.call(this, ...args));
  37. }
  38. }
  39. }