之前接受的答案是错误的。
u'\ufffe' 不是字符。如果你把它放在一个 unicode 字符串中,那么有人已经把它塞满了。
BOM(又名零宽度无间断空间)是 u'\ufeff'
>>> UNICODE_BOM = u'\N{ZERO WIDTH NO-BREAK SPACE}'
>>> UNICODE_BOM
u'\ufeff'
>>>
读取this(Ctrl-F 搜索 BOM)和this 和 this(Ctrl-F 搜索 BOM)。
这是一个正确且拼写错误/抗脑力的答案:
将您的输入解码为unicode_str。然后这样做:
# If I mistype the following, it's very likely to cause a SyntaxError.
UNICODE_BOM = u'\N{ZERO WIDTH NO-BREAK SPACE}'
if unicode_str and unicode_str[0] == UNICODE_BOM:
unicode_str = unicode_str[1:]
奖励:与看似任意的十六进制文字集合相比,使用命名常量可以让您的读者更多地了解正在发生的事情。
更新不幸的是,标准 Python 库中似乎没有合适的命名常量。
唉,编解码器模块只提供“一个圈套和一个妄想”:
>>> import pprint, codecs
>>> pprint.pprint([(k, getattr(codecs, k)) for k in dir(codecs) if k.startswith('BOM')])
[('BOM', '\xff\xfe'), #### aarrgghh!! ####
('BOM32_BE', '\xfe\xff'),
('BOM32_LE', '\xff\xfe'),
('BOM64_BE', '\x00\x00\xfe\xff'),
('BOM64_LE', '\xff\xfe\x00\x00'),
('BOM_BE', '\xfe\xff'),
('BOM_LE', '\xff\xfe'),
('BOM_UTF16', '\xff\xfe'),
('BOM_UTF16_BE', '\xfe\xff'),
('BOM_UTF16_LE', '\xff\xfe'),
('BOM_UTF32', '\xff\xfe\x00\x00'),
('BOM_UTF32_BE', '\x00\x00\xfe\xff'),
('BOM_UTF32_LE', '\xff\xfe\x00\x00'),
('BOM_UTF8', '\xef\xbb\xbf')]
>>>
更新 2 如果您尚未对输入进行解码,并希望检查它的 BOM,您需要检查 两个 不同的 UTF-16 和 BOM UTF-32 至少有 两个 不同的 BOM。如果每种方法只有一种,那么您就不需要 BOM,对吗?
这里逐字逐句地从我自己的代码中得到我的解决方案:
def check_for_bom(s):
bom_info = (
('\xFF\xFE\x00\x00', 4, 'UTF-32LE'),
('\x00\x00\xFE\xFF', 4, 'UTF-32BE'),
('\xEF\xBB\xBF', 3, 'UTF-8'),
('\xFF\xFE', 2, 'UTF-16LE'),
('\xFE\xFF', 2, 'UTF-16BE'),
)
for sig, siglen, enc in bom_info:
if s.startswith(sig):
return enc, siglen
return None, 0
输入 s 至少应该是输入的前 4 个字节。它返回可用于解码输入的后 BOM 部分的编码,加上 BOM 的长度(如果有)。
如果您偏执,您可以允许另外 2 个(非标准)UTF-32 排序,但 Python 不为它们提供编码,我从未听说过实际发生,所以我不知道麻烦。