|
■No92531 (WebSurfer さん) に返信 > 横レス&本題とは直接関係ない話ですみませんが・・・
脱線ついでに言えば、Unicode における バイト・オーダー・マーク判定もまた、 データからの「推測」の一部と言えるかと思います。
ファイルの先頭以外に U+FEFF の文字が存在していた場合、それは BOM ではなく、 常に "ZERO WIDTH NON-BREAKING SPACE" の文字として扱われる仕様ですが、 この文字が先頭にあった場合、それが常に BOM として扱われるとは限りません。
そもそも先頭に BOM を置くようになったのは、リトルエンディアン/ビッグエンディアンの 判定マークとなることを発端としているわけですが、BOM の存在は必須ではありません。 (UTF-8 においては、この意味合いが変化していますが)
そして .NET にも、Encoding.GetPreamble() の On/Off を制御するためのコンストラクタはあるのですが、 それが ZWNBSP と BOM を区別できるようにはなっているかというと微妙なところ。 new System.Text.UnicodeEncoding(bigEndian:false, byteOrderMark:false) new System.Text.UnicodeEncoding(bigEndian:false, byteOrderMark:true) new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier:false) new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier:true)
というのも、UTF-16BE や UTF-16LE の場合、RFC2781 において MUST NOT prepend a BOM と 記されていることから、そもそも BOM が存在できないはずなのです。
しかし .NET Framework の実装はそうなっておらず、下記は { 0xFF, 0xFE } を返します。 System.Text.Encoding.GetEncoding("UTF-16LE").GetPreamble()
たとえば、FF,FE,41,00,42,00,43,00 の 8 バイトなファイルの場合、 下記のような解釈がありえます。
(1) BOM つき UTF-16 な 3 文字 …… [U+0041]"A", [U+0042]"B", [U+0043]"C" (2) UTF-16LE な 4 文字 …… [U+FEFF]"ZWNBSP", [U+0041]"A", [U+0042]"B", [U+0043]"C" (3) 倍精度浮動小数点数 …… 「2.1139322086691184E-307」 (4) 単精度浮動小数点数が 2 つ …… 「6.060783E-39」「6.153071E-39」
このファイルが、『そもそもテキストファイルかどうかも不明』という状態だとしたら、 (3) や (4) どころか、あるいはそれ以外の可能性も生じます。
なので、ある程度の『前提条件』が必要になってきます。
WebSurfer さんが書かれた > BOM が付いていればある程度可能ではないかと思います。 というのも、前提条件の一つと言えるでしょう。
もしも前提条件が、『UTF16 のリトルエンディアンで記されたファイル』であることで あったとしたら、そもそも文字コードを「推察」する必要は無いでしょう。 ファイルの内容を読み取るまでも無く、(1) で確定となります。
あるいは『BOM 付の Unicode テキストファイルである』という前提条件だったとすれば、 先頭の数バイトを捕らえることで、(1) であることを導くことができます。
『BOM 無しの Unicode テキストファイルである』という前提条件だったとすれば、 (2) と「推察」できるでしょう。バイナリ列からして、UTF-8 や UTF-32 の系統でないことは明確ですし。
厄介なのは『BOM の有無は分からないけど、とにかく Unicode テキストのはず』という条件の場合で、 本来であれば、(2) の可能性が残されています。しかし実際には、日常で ZWNBSP が使われることは 殆どありませんし、それがファイル先頭に置かれるのはさらに稀なので、実運用上は (1) である可能性が高いと「推察」されます。.NET Framework 上でもそういう扱いになっているかと。
|