【问题标题】:Buffer.byteLength returning drastically different byte lengthBuffer.byteLength 返回截然不同的字节长度
【发布时间】:2016-05-15 23:53:25
【问题描述】:

使用 Node.js v5.1.0,我正在尝试确定缓冲区的内容长度。因此,我正在这样做:

Buffer.byteLength(self.data, 'utf8')

self.data 看起来像这样:

<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 f0 00 f0 00 00 ff db 00 43 00 05 03 04 04 04 03 05 04 04 04 05 05 05 06 07 0c 08 07 07 07 07 0f 0b 0b 09 ... >

我正在加载的图像在文件系统 (OS X) 上为 109,055 字节(磁盘上为 111 KB),但我的内容长度计算返回 198,147 字节。如果我将编码设置为ascii,它将返回 104,793 个字节。更接近,但仍然不正确。

我计算正确吗?我需要对缓冲区做些什么来让它返回正确的值吗?如果我做对了,为什么会出现差异?如果我做错了,请分享;)

【问题讨论】:

  • 你不是说self.data.byteLength吗?
  • 哈!是的,这完全有效。谢谢。如果你愿意,把它作为答案扔进去?而且,如果您知道为什么存在另一种方式,可以工作,但返回错误的值,那也太棒了;)
  • Buffer.byteLength 需要一个字符串作为第一个参数,而不是缓冲区,所以可能有一个正在进行的转换与它混淆。 self.data 中的数据是文本吗?

标签: javascript node.js buffer


【解决方案1】:

如文档中所述,Buffer.byteLength() 返回假定特定编码的字符串的字节长度。

Buffer 类型实际上是一个ArrayBuffer,这意味着它的长度可以通过byteLength 属性获取。此外,Node 的实现添加了一个提供相同长度的length 属性。

【讨论】:

    【解决方案2】:

    我认为区别如下:

    • buffer.length: 缓冲区已用+保留长度。
    • buffer.byteLength:缓冲区的使用长度。
    • buffer.toString().length:默认字符串渲染/解释缓冲区字节的字符数。您可以通过提供不同的编码来更改该渲染/解释。 (例如toString("ascii")
    • Buffer.byteLength(buffer, targetEncoding):将“缓冲区”中的字节理解为使用 UTF-8 编码(即,字节旨在被呈现/解释为 UTF-8 字符串),这将返回存储该 UTF-所需的字节数8 个指定编码的字符串 (targetEncoding)。

    关于最后一项 (Buffer.byteLength()),我不完全确定我的解释是否正确,但这是我从这里的简要描述中可以得出的最好结论:https://nodejs.org/api/buffer.html#buffer_class_method_buffer_bytelength_string_encoding

    编辑:根据this comment,上面的描述对于buffer.lengthbuffer.byteLength 之一似乎是不正确的(因为他们有一个缓冲区,其byteLength 高于其length)。如果有人找到不匹配的解释,请评论或编辑这篇文章并修复!

    【讨论】:

    • 我试图获取 http 响应的内容长度。当我使用buffer.lengthbuffer.toString().length, 时,我得到了相同的值52700。但是当我尝试buffer.byteLength 时,我得到了59241。此外,当我使用Buffer.byteLength(buffer, 'utf8') 时,我得到了89212。响应头中的Content-Length59241。这种方法有什么区别,为什么它们得到不同的值?这让我很困惑。你能帮帮我吗?
    • @ZHANGLuyao 我也很困惑!我尽我最大的努力从网上找到的信息中定义了四种方法,但我很可能误解了其中的一些;特别是,对于您的情况,byteLength 大于 length 的事实表明我对这两者的定义是不正确的(他们会提出相反的建议)。 :/所以不幸的是,我显然在同一条船上。不过,如果您更准确地找出区别,请随时提出修改建议!
    【解决方案3】:

    OP 中的混淆在于 Buffer.byteLength() 函数,它以字符串和编码作为参数,与缓冲区对象上的 .byteLength 属性不同。

    投票最多的答案也混淆了这两个概念(Buffer.byteLength returning drastically different byte length),但我不能再改变我对它的投票了。

    这里有一个解释:

    let buf = Buffer.alloc(4); // <Buffer 00 00 00 00>
    buf.length; // 4
    buf.byteLength; // 4
    buf.byteLength === buf.Length //true
    

    此时我们知道.byteLength.length作为缓冲区对象的属性是严格相等的。

    buf.write('ab'); // 2 - returns length of string 'ab' written to buf
    buf.length // 4
    buf.byteLength // 4
    

    .length。和.byteLength 返回4。正如链接的答案所声称的那样,保留长度和使用长度之间没有区别。

    对于Buffer.byteLength(string, encoding='utf-8') 函数(不同于.byteLength 属性),接受的答案是正确的,它给出了用指定编码的字符串的字节长度编码参数(默认 utf-8)。

    【讨论】:

    • 我不确定这如何解决我最初的问题?我认为这更适合作为对您链接到的答案的评论。
    • @brandonscript - 原始问题中的混淆是 Buffer.byteLength() 函数返回具有给定编码的字符串表示的字节长度。让我进行重构以使其更清楚。不幸的是,cmets 不支持多行代码示例,所以以答案格式写了这个,以便之后来搜索的人(比如我自己)更清楚
    猜你喜欢
    • 2013-02-26
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多