将 UTF-8 BOM 添加到字符串/Blob
Posted
技术标签:
【中文标题】将 UTF-8 BOM 添加到字符串/Blob【英文标题】:Adding UTF-8 BOM to string/Blob 【发布时间】:2013-07-26 14:18:38 【问题描述】:我需要在客户端生成的文本数据中添加一个 UTF-8 字节顺序标记。我该怎么做?
当然,使用new Blob(['\xEF\xBB\xBF' + content])
会产生'"my data"'
。
'\uBBEF\x22BF'
也不起作用('\x22' == '"'
是 content
中的下一个字符)。
是否可以将 javascript 中的 UTF-8 BOM 预先添加到生成的文本中?
是的,在这种情况下我确实需要 UTF-8 BOM。
【问题讨论】:
【参考方案1】:将\ufeff
添加到字符串中。见http://msdn.microsoft.com/en-us/library/ie/2yfce773(v=vs.94).aspx
请参阅 @jeff-fischer 和 @casey for details on UTF-8 and UTF-16 和 BOM 之间的讨论。使上述工作真正起作用的是字符串\ufeff
始终用于表示 BOM,而不管使用的是 UTF-8 还是 UTF-16。
有关详细说明,请参阅The Unicode Standard 5.0, Chapter 2 中的第 36 页。该页面的引用
表 2-4 中的 UTF-8 字节序条目被标记为 N/A,因为 UTF-8 代码单元大小为 8 位,通常的机器问题是 较大代码单元的字节序不适用。序列化的顺序 字节数不得偏离 UTF-8 定义的顺序 编码形式。既不需要也不建议使用 BOM UTF-8,但可能会在使用 UTF-8 数据的环境中遇到 从使用 BOM 或 BOM 所在位置的其他编码形式转换而来 用作 UTF-8 签名。
【讨论】:
老兄...是的。这完美地工作。谢谢!其他问题有很多错误/无效的答案。 警告其他阅读本文的人:注意,\ufeff
实际上是 UTF-16 BOM 而不是 UTF-8 BOM en.wikipedia.org/wiki/Byte_order_mark
很好的解决方案。谢谢@erik-töyrä
@mEnE 因为 \t (codepoint U+0009)
稍微澄清一下:字符 \uFEFF 是所有 UTF(8、16 LE 和 16 BE)的 BOM 字符。但是,它被编码为字节: - 0xEF 0xBB 0xBF - 0xFF 0xFE - 0xFE 0xFF。区分内部 unicode 字符 (\ufeff) 以及表示该字符的各种方式(以字节为单位)非常重要。 :)【参考方案2】:
我正在编辑我的原始答案。上面的答案确实需要详细说明,因为这是 Node.js 的一个复杂的解决方案。
简短的回答是,是的,此代码有效。
长答案是,不,FEFF 不是 utf-8 的字节顺序标记。显然节点采用了某种快捷方式来在文件中编写编码。 FEFF 是 UTF16 Little Endian 编码,可以在 Byte Order Mark ***文章中看到,也可以在写入文件后在二进制文本编辑器中查看。我已经验证是这种情况。
http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
显然,Node.JS 使用 \ufeff 来表示任意数量的编码。它采用 \ufeff 标记并根据 writeFile 的第三个选项参数将其转换为正确的字节顺序标记。您传入编码字符串的第三个参数。 Node.JS 采用此编码字符串并将 \ufeff 固定字节编码转换为任何一个实际编码的字节顺序标记。
UTF-8 示例:
fs.writeFile(someFilename, '\ufeff' + html, encoding: 'utf8' , function(err)
/* The actual byte order mark written to the file is EF BB BF */
UTF-16 Little Endian 示例:
fs.writeFile(someFilename, '\ufeff' + html, encoding: 'utf16le' , function(err)
/* The actual byte order mark written to the file is FF FE */
因此,正如您所见,\ufeff 只是一个标记,表示任意数量的结果编码。使其进入文件的实际编码直接取决于指定的编码选项。字符串中使用的标记实际上与写入文件的内容无关。
我怀疑这背后的原因是因为他们选择不写入字节顺序标记,并且 UTF-8 的 3 字节标记不容易编码到要写入磁盘的 javascript 字符串中。因此,他们使用 UTF16LE BOM 作为字符串中的占位符标记,在写入时被替换。
【讨论】:
好吧,如果你看一下字节顺序标记和我最初所说的,那就对了。如您在问题中所述,FEFF 字节顺序标记不是 UTF-8 的字节顺序标记。最初的答案似乎偶然发现了正确的答案,或者至少根本没有详细说明。他们做对的唯一原因是选项编码默认为 utf-8。不是因为他们提供的字节顺序标记实际上是 UTF-8 字节顺序标记。 请随时从我的回答中删除您的标记。没有错。 我对此有点困惑,因为问题根本没有提到节点。 具体来说,您可以see here 表明 BOM 始终是相同的字符 (U+FEFF),而不是不同的字符,具体取决于文本所在的 Unicode 类型或字节序。确实写入的字节不同,但这是因为使用不同的编码写入相同的字符。 在已接受的答案中添加了更多详细信息,以详细说明其工作原理。随意编辑你认为合适的。【参考方案3】:我遇到了同样的问题,这是我想出的解决方案:
var blob = new Blob([
new Uint8Array([0xEF, 0xBB, 0xBF]), // UTF-8 BOM
"Text",
... // Remaining data
],
type: "text/plain;charset=utf-8" );
使用Uint8Array
可防止浏览器将这些字节转换为字符串(在 Chrome 和 Firefox 上测试)。
您应该将 text/plain
替换为您想要的 MIME 类型。
【讨论】:
这是使用Blob
或使用实际字节而不是JS 字符串时的正确方法。当您使用 JS 字符串而不是实际字节时,Erik 和 Jeff 的答案是正确的。【参考方案4】:
这是我的解决方案:
var blob = new Blob(["\uFEFF"+csv],
type: 'text/csv; charset=utf-18'
);
【讨论】:
你能解释一下为什么这是有效的吗,utf-18 甚至是一个有效的编码以上是关于将 UTF-8 BOM 添加到字符串/Blob的主要内容,如果未能解决你的问题,请参考以下文章