我需要在客户端生成的文本数据中添加UTF-8字节顺序标记,该如何实现?
使用new Blob(['\xEF\xBB\xBF' + content])
会得到'"my data"'
。
即使是'\uBBEF\x22BF'
(其中'\x22' == '"'
是content
中的下一个字符),也不起作用。
能否在JavaScript中为生成的文本添加UTF-8 BOM?
是的,在这种情况下我确实需要UTF-8 BOM。
我需要在客户端生成的文本数据中添加UTF-8字节顺序标记,该如何实现?
使用new Blob(['\xEF\xBB\xBF' + content])
会得到'"my data"'
。
即使是'\uBBEF\x22BF'
(其中'\x22' == '"'
是content
中的下一个字符),也不起作用。
能否在JavaScript中为生成的文本添加UTF-8 BOM?
是的,在这种情况下我确实需要UTF-8 BOM。
在字符串前面加上\ufeff
。请参阅http://msdn.microsoft.com/en-us/library/ie/2yfce773(v=vs.94).aspx以获取更多信息。
请查看@jeff-fischer和@casey之间的讨论关于UTF-8和UTF-16的详细信息和BOM。使上述内容正常工作的实际原因是,无论使用UTF-8还是UTF-16,字符串\ufeff
始终用于表示BOM。
请参阅The Unicode Standard 5.0,第2章中的第36页以获取详细解释。从该页面摘录:
在表2-4中,UTF-8的字节序条目标记为N/A,因为UTF-8码元大小为8位,较大码元的机器字节序问题不适用。字节的序列化顺序不得偏离UTF-8编码形式定义的顺序。对于UTF-8,不需要也不建议使用BOM,但在将UTF-8数据从使用BOM的其他编码形式转换或BOM用作UTF-8签名的上下文中可能会遇到。我也遇到了同样的问题,这是我想出的解决方案:
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的答案是正确的。 - Timothy Zorn我正在编辑我的原始回答。上面的回答确实需要详细解释,因为这是Node.js中的一个复杂解决方案。
简单的答案是,是的,这段代码是有效的。
长的答案是,不,FEFF不是utf-8的字节顺序标记。显然,Node在编写文件编码时采取了某种快捷方式。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的第3个选项参数将其转换为正确的字节顺序标记。您传递给编码字符串的第3个参数。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 小端序示例:
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作为占位符标记,在写入时被替换。
这是我的解决方案:
var blob = new Blob(["\uFEFF"+csv], {
type: 'text/csv; charset=utf-18'
});
charset=utf-18
是个打字错误。 - foxiris这适用于我:
let blob = new Blob(["\ufeff", csv], { type: 'text/csv;charset=utf-8' });
BOM(字节顺序标记)可能是必要的,因为一些程序需要它来使用正确的字符编码。
例如: 在默认字符编码为Shift_JIS而不是UTF-8的系统中,在MS Excel中打开没有BOM的csv文件时,它将以默认编码打开。这将导致垃圾字符。如果你指定UTF-8的BOM,它就会修复它。
这对我来说解决了问题。使用authorize.net api和cloudflare workers时,我遇到了BOM:
const data = JSON.parse((await res.text()).trim());
\ufeff
实际上是 UTF-16 BOM (字节顺序标记),而不是 UTF-8 BOM。详情请参考维基百科:Byte order mark。 - carlosrafaelgn