深入Node模块Buffer-学会操作二进制

2019/04/10 10:10
阅读数 18

<section id="nice" data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px; color: black; padding: 10px; line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: left; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;"><figure data-tool="mdnice编辑器" style="margin: 0; margin-top: 10px; margin-bottom: 10px;"><img src="https://tva1.sinaimg.cn/large/006tNbRwly1gb0x34mmf0j30mi0comxn.jpg" alt style="display: block; margin: 0 auto; width: 100%;"></figure> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">Buffer 作为 nodejs 中重要的概念和功能,为开发者提供了操作二进制的能力。本文记录了几个问题,来加深对 Buffer 的理解和使用:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">认识缓冲器</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">如何申请堆外内存</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">如何计算字节长度</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">如何计算字节长度</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">如何转换字符编码</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">理解共享内存与拷贝内存</section></li></ul> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">认识 Buffer(缓冲器)</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">Buffer 是 nodejs 核心 API,它提供我们处理二进制数据流的功能。Buffer 的使用和 ES2017 的 Uint8Array 非常相似,但由于 node 的特性,专门提供了更深入的 api。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">Uint8Array 的字面意思就是:8 位无符号整型数组。一个字节是 8bit,而字节的表示也是由两个 16 进制(4bit)的数字组成的。</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf = Buffer.alloc(<span class="hljs-number" style="color: #008080; line-height: 26px;">1</span>); <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(buf); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: &lt;Buffer 00&gt;</span> </code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">如何申请堆外内存</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">Buffer 可以跳出 nodejs 对堆内内存大小的限制。nodejs12 提供了 4 种 api 来申请堆外内存:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.from()</code></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.alloc(size[, fill[, encoding]])</code></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.allocUnsafe(size)</code></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.allocUnsafeSlow(size)</code></section></li></ul> <h3 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 20px; margin: 20px auto 5px; border-top: 1px solid rgb(221, 221, 221); box-sizing: border-box;"><span style="margin-top: -1px; padding-top: 6px; padding-right: 5px; padding-left: 5px; font-size: 17px; border-top: 2px solid rgb(33, 33, 34); display: inline-block; line-height: 1.1;">Buffer.alloc vs Buffer.allocUnsafe</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">在申请内存时,可能这片内存之前存储过其他数据。如果不清除原数据,那么会有数据泄漏的安全风险;如果清除原数据,速度上会慢一些。具体用哪种方式,根据实际情况定。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Buffer.alloc:申请指定大小的内存,并且清除原数据,默认填充 0</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">Buffer.allocUnsafe:申请指定大小内存,但不清除原数据,速度更快</section></li></ul> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">根据提供的 api,<strong style="font-weight: bold; color: black;">可以手动实现一个<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">alloc</code></strong>:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">function</span> <span class="hljs-title" style="color: #900; font-weight: bold; line-height: 26px;">pollifyAlloc</span>(<span class="hljs-params" style="line-height: 26px;">size, fill = <span class="hljs-number" style="color: #008080; line-height: 26px;">0</span>, encoding = <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span></span>) </span>{ <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf = Buffer.allocUnsafe(size); buf.fill(fill, <span class="hljs-number" style="color: #008080; line-height: 26px;">0</span>, size, encoding); <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">return</span> buf; } </code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 20px; margin: 20px auto 5px; border-top: 1px solid rgb(221, 221, 221); box-sizing: border-box;"><span style="margin-top: -1px; padding-top: 6px; padding-right: 5px; padding-left: 5px; font-size: 17px; border-top: 2px solid rgb(33, 33, 34); display: inline-block; line-height: 1.1;">Buffer.allocUnsafe vs Buffer.allocUnsafeSlow</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">从命名上可以直接看出效果,<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.allocUnsafeSlow</code>更慢。因为当使用 <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.allocUnsafe</code> 创建新的 Buffer 实例时,如果要分配的内存小于 4KB,则会从一个预分配的 Buffer 切割出来。 这可以避免垃圾回收机制因创建太多独立的 Buffer 而过度使用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">这种方式通过消除跟踪和清理的需要来改进性能和内存使用。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">如何计算字节长度</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">利用 Buffer,可以获得数据的真实所占字节。例如一个汉字,它的字符长度是 1。但由于是 utf8 编码的汉字,所以占用 3 个字节。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">直接利用<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.byteLength()</code>可以获得字符串指定编码的字节长度:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> str = <span class="hljs-string" style="color: #d14; line-height: 26px;">"本文原文地址: xxoo521.com"</span>;

<span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(Buffer.byteLength(str, <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span>)); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: 31</span> <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(str.length); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: 19</span> </code></pre>

<p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">也可以直接访问 Buffer 实例的 length 属性(不推荐):</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(Buffer.from(str, <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span>).length); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: 31</span> </code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">如何转换字符编码</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">Nodejs 当前支持的编码格式有:ascii、utf8、utf16le、ucs2、base64、latin1、binary、hex。其他编码需要借助三方库来完成。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">下面,是用<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.from()</code>和<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">buf.toString()</code>来封装的 nodejs 平台的编码转换函数:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">function</span> <span class="hljs-title" style="color: #900; font-weight: bold; line-height: 26px;">trans</span>(<span class="hljs-params" style="line-height: 26px;">str, from = <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span>, to = <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span></span>) </span>{ <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf = Buffer.from(str, <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">from</span>); <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">return</span> buf.toString(to); }

<span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: 5Y6f5paH5Zyw5Z2AOiB4eG9vNTIxLmNvbQ==</span> <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(trans(<span class="hljs-string" style="color: #d14; line-height: 26px;">"原文地址: xxoo521.com"</span>, <span class="hljs-string" style="color: #d14; line-height: 26px;">"utf8"</span>, <span class="hljs-string" style="color: #d14; line-height: 26px;">"base64"</span>)); </code></pre>

<h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">共享内存与拷贝内存</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">在生成 Buffer 实例,操作二进制数据的时候,千万要注意接口是基于共享内存,还是基于拷贝底层内存。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">例如对于生成 Buffer 实例的<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">from()</code>,不同类型的参数,nodejs 底层的行为是不同的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">为了更形象地解释,请看下面两段代码。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;"><strong style="font-weight: bold; color: black;">代码 1</strong>:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf1 = Buffer.from(<span class="hljs-string" style="color: #d14; line-height: 26px;">"buffer"</span>); <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf2 = Buffer.from(buf1); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// 拷贝参数中buffer的数据到新的实例</span> buf1[<span class="hljs-number" style="color: #008080; line-height: 26px;">0</span>]++;

<span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(buf1.toString()); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: cuffer</span> <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(buf2.toString()); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: buffer</span> </code></pre>

<p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;"><strong style="font-weight: bold; color: black;">代码 2</strong>:</p> <pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px;"><code class="hljs" style="overflow-x: auto; padding: 16px; color: #333; background: #f8f8f8; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;"><span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> arr = <span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">new</span> <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">Uint8Array</span>(<span class="hljs-number" style="color: #008080; line-height: 26px;">1</span>); arr[<span class="hljs-number" style="color: #008080; line-height: 26px;">0</span>] = <span class="hljs-number" style="color: #008080; line-height: 26px;">97</span>;

<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">const</span> buf1 = Buffer.from(arr.buffer); <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(buf1.toString()); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: a</span>

arr[<span class="hljs-number" style="color: #008080; line-height: 26px;">0</span>] = <span class="hljs-number" style="color: #008080; line-height: 26px;">98</span>; <span class="hljs-built_in" style="color: #0086b3; line-height: 26px;">console</span>.log(buf1.toString()); <span class="hljs-comment" style="color: #998; font-style: italic; line-height: 26px;">// output: b</span> </code></pre>

<p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">在第二段代码中,传入<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.from</code>的参数类型是<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">arrayBuffer</code>。因此<code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">Buffer.from</code>仅仅是创建视图,而不是拷贝底层内存。buf1 和 arr 的内存是共享的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">在操作 Buffer 的过程中,需要特别注意共享和拷贝的区别,发生错误比较难排查。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">参考链接</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a href="http://nodejs.cn/api/buffer.html" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">Buffer 文档</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">MDN Uint8Array</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a href="https://nodejs.org/en/knowledge/advanced/buffers/how-to-use-buffers/" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">How to use Buffers in Node.js</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a href="https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">Do you want a better understanding of Buffer in Node.js? Check this out.</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a href="https://medium.com/better-programming/an-introduction-to-buffer-in-node-js-2237a9bce9da" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">An Introduction to Buffer in Node.js</a></section></li></ul> <h2 data-tool="mdnice编辑器" style="margin-top: 40px; margin-bottom: 20px; font-weight: bold; color: black; font-size: 24px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;"><span style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">最后</span></h2> <ol data-tool="mdnice编辑器" style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">觉得不错,<strong style="font-weight: bold; color: black;">帮忙点个推荐呗</strong>,您的支持是对我最大的激励</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">欢迎我的公众号:<strong style="font-weight: bold; color: black;">「心谭博客」</strong>,只专注于<strong style="font-weight: bold; color: black;">前端</strong> + <strong style="font-weight: bold; color: black;">算法</strong>的原创分享</section></li></ol> <p data-tool="mdnice编辑器" style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;">由于个人精力有限,很多系列和历史文章没有即时同步,<strong style="font-weight: bold; color: black;">请前往<a href="https://xxoo521.com/frontend/" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">「前端图谱」</a>&amp;<a href="https://xxoo521.com/algorithm/" style="text-decoration: none; word-wrap: break-word; font-weight: bold; color: rgb(239, 112, 96); border-bottom: 1px solid rgb(239, 112, 96);">「算法题解」</a></strong>,保证您有所收获。</p> </section>

原文出处:https://www.cnblogs.com/geyouneihan/p/12249010.html

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部