Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js - Buffer、Stream 与 fs #26

Open
HXWfromDJTU opened this issue Oct 18, 2020 · 0 comments
Open

Node.js - Buffer、Stream 与 fs #26

HXWfromDJTU opened this issue Oct 18, 2020 · 0 comments

Comments

@HXWfromDJTU
Copy link
Owner

前言

在了解Node.js内存的分配的时候,堆外内存是一个神秘的存在,仅知道它是通过Node.js中的C++代码向内存申请使用的。这其中最具代表的必须要数Node.js中的BufferStream了。

Buffer字面的意义是缓冲区,暂存器,了解过操作系统组成原理的同学一定不会陌生。在计算机中,缓冲器是存储变量,方便CPU直接读取的一款存储区域。而Stream则是类比数据字节的顺序的移动像是水流一样。

Buffer

作为前端工程师,在进阶学习Node.js时遇到Buffer常常比较陌生,因为虽然同是Javascript,但在浏览器场景下处理文件流、视频流是相对比较少的情况,而服务端Javascript的情况恰恰相反。

Buffer 对象用于表示固定长度的字节序列。 --- 《Node.js文档》

Buffer是一个像Array的对象,但它主要用于操作字节。 --- 《深入浅出Node.js》

Buffer与数组、字符串的关系

  • Buffer类似于数组,可以使用下标访问,并且有length属性。
  • 大小在创建时就固定,且无法调整。
  • Buffer每一个元素都是一个两位的十六进制数
    const buff = Buffer.from('swain wong')
    console.log(buff) // <Buffer 73 77 61 69 6e 20 77 6f 6e 67>
  • Buffer可以和String进行相互转换,并且可以指定字符集编码
  • Buffer格式的内容更便于在网络中传输,而String形式的内容更便于进行修改操作。

内存分配

Buffer 是一个典型的Javascript 与 C++ 结合的模块,它将性能相关部分用 C++ 实现,将非心梗相关部分用Javascript实现。 --- 《Node.js 深入浅出》

  • Buffer所占的内存并不受V8所支配,属于堆外内存,但包含在RSS之内。
  • 内核用8 KB来界定大对象小对象
    • 小对象直接使用内存池中的内存。
    • 大对象直接使用C++层面申请的内存进行载入。

Stream

流(stream)是 Node.js 中处理流式数据的抽象接口。 stream 模块用于构建实现了流接口的对象。 --- 《Node.js官网文档》

数据的流动就像是生活中水的流动褨,流是可以描述所有常见输入-输出类型数据的统一模型。就像是水流有方向,数据的排列也有方向性一样,数据流本身也具有方向性,对于某一端可写,对于另一端边仅仅可读了。

四种基本 Stream

流种类 具体实现
Writable Stream HTTP Request(client) HTTP Response(server) fs write stream
Readable Stream HTTP Response(server) HTTP Request(client) fs read stream
Duplex 既可读又可写的流 TCP Sockets zlib streams crypto streams
Treansform 在读写过程中即可以修改或者转换数据的Duplex zlib streams crypto streams

与EventEmitter的关系

Node.js的API设计中,Stream被设计为事件驱动相关的,继承实现了EventEmitter。四种基本的Stream都包含有closeerrordatafinish的接口用于流数据的读取。

fs

fs 模块可用于与文件系统进行交互(以类似于标准 POSIX 函数的方式)。 --- 《Node.js官方文档》

不难看出,从BufferStream再到fs模块,对数据处理的粒度是越来越大的。而Node.jsfs模块的实现上确实也是继承了上述两个模块的api来实现的。

  • 继承Stream的文件流,对外暴露fs.createReadStreamfs.createWriteStream
  • 对文件的同步与异步操作
    • fs.readFileSyncfs.writeFileSync
    • fs.readFilefs.writeFile
  • 以上两种fs处理文件的形式,区别在于第一种的处理会将文件处理为流的形式。第二种会将文件视作一个整体,统一为整个文件分配内存大小,并将内容放入到一个大的缓冲区中。

小结

BufferStreamfile在后端中是很成熟的概念,且不说Node.js在服务端处理文件流的底层逻辑,仅Node.js作为前端工具链对前端文件进行打包的时候,最基础的步骤就是:读取文件内容 ==> 处理文件内容 ==> 生成处理后的内容。了解BufferStreamfs对我们理解很多前端自动化工具打下了坚实的基础。

参考资料

[1] 认识node核心模块--从Buffer、Stream到fs
[2] Node.js v14.13.1 文档 - fs文件系统
[3] Introduction to NodeJS Streams

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant