BOM 字符复制到 JSON in Python 3

BOM character copied into JSON in Python 3

在我的应用程序中,用户可以上传文件(文本文件),我需要读取它并为另一个 API 调用构造 json 对象。

我用

打开文件
f = open(file, encoding="utf-8")

获取第一个词并构造Json对象,...

我的问题是某些文件(尤其是来自Microsoft 环境的文件)开头有BOM 对象。问题是我的 Json 现在里面有这个字符

{
   "word":"\ufeffMyWord"
}

当然,API 从此时起不再工作。

我显然错过了什么,因为,utf-8 不应该删除 BOM 对象吗? (因为它不是 utf-8-sig)。

如何克服这个问题?

不,UTF-8 标准没有定义 BOM 字符。这是因为 UTF-8 没有像 UTF-16 和 UTF-32 那样的字节顺序歧义问题。 Unicode 联盟不建议在 UTF-8 编码文件的开头使用 U+FEFF,而如果存在指定编解码器的替代方案,IETF 会积极反对。来自 Wikipedia article on BOM usage in UTF-8:

The Unicode Standard permits the BOM in UTF-8, but does not require or recommend its use.

[...]

The IETF recommends that if a protocol either (a) always uses UTF-8, or (b) has some other way to indicate what encoding is being used, then it "SHOULD forbid use of U+FEFF as a signature."

Unicode 标准只有 'permits' BOM,因为它是一个常规字符,就像其他字符一样;它是一个零宽度的不间断 space 字符。因此,Unicode 联盟建议在解码时不要删除它,以保留信息(以防它有不同的含义,或者你想保持与已经依赖的工具的兼容性)它)。

您有两个选择:

  • 先去掉字符串,U+FEFF被认为是白色的space所以用str.strip()去掉。或者明确地去掉 BOM:

    text = text.lstrip('\ufeff')  # remove the BOM if present
    

    (从技术上讲,这将删除任意数量的零宽度不间断 space 字符,但这可能正是您想要的)。

  • 改为使用 utf-8-sig 编解码器打开文件。添加该编解码器是为了处理此类文件,在解码之前从开头明确删除 UTF-8 BOM 字节序列(如果存在)。它可以处理没有这些字节的文件。

UTF-8 不会删除 BOM(字节顺序标记)。您必须检查文件是否包含 BOM,将其删除。

if text.startswith(codecs.BOM_UTF8):
  headers[0] = (headers[0])[3:]
  print "Removed BOM"
else:
  print "No BOM char, Process your file"