以前に受け入れられた答えは間違っています。
u'\ufffe'
キャラクターではありません。あなたがそれをユニコード文字列で得るならば、誰かが力強く詰め込んだ。
BOM(別名ZERO WIDTH NO-BREAK SPACE)はu'\ufeff'
>>> UNICODE_BOM = u'\N{ZERO WIDTH NO-BREAK SPACE}'
>>> UNICODE_BOM
u'\ufeff'
>>>
これ(Ctrl-FでBOMを検索)とこれとこれ(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の場合は2つの異なるBOMをチェックし、 UTF-32の場合は少なくとも2つの異なるBOMをチェックする必要があります。それぞれの方法が1つしかない場合は、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はそれらのエンコードを提供せず、実際の発生について聞いたことがないので、気にしません。