1. ホーム
  2. c#

テキストファイルの文字エンコードを検出する方法は?

2023-09-05 13:33:54

質問

ファイル内でどの文字エンコーディングが使用されているかを検出しようとしています。

このコードで、標準的なエンコーディングを取得しようとします。

public static Encoding GetFileEncoding(string srcFile)
    {
      // *** Use Default of Encoding.Default (Ansi CodePage)
      Encoding enc = Encoding.Default;

      // *** Detect byte order mark if any - otherwise assume default
      byte[] buffer = new byte[5];
      FileStream file = new FileStream(srcFile, FileMode.Open);
      file.Read(buffer, 0, 5);
      file.Close();

      if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
        enc = Encoding.UTF8;
      else if (buffer[0] == 0xfe && buffer[1] == 0xff)
        enc = Encoding.Unicode;
      else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
        enc = Encoding.UTF32;
      else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
        enc = Encoding.UTF7;
      else if (buffer[0] == 0xFE && buffer[1] == 0xFF)      
        // 1201 unicodeFFFE Unicode (Big-Endian)
        enc = Encoding.GetEncoding(1201);      
      else if (buffer[0] == 0xFF && buffer[1] == 0xFE)      
        // 1200 utf-16 Unicode
        enc = Encoding.GetEncoding(1200);


      return enc;
    }

私の5つの1バイトは、60、118、56、46、49です。

この5つの最初のバイトにどのエンコーディングがマッチするかを示すチャートはありますか?

どのように解決するのですか?

ファイルが BOM を持つことに依存してはいけません。 UTF-8 はそれを必要としません。 また、非 Unicode エンコーディングは BOM を持ちません。 しかし、エンコーディングを検出する他の方法があります。

UTF-32

BOMは00 00 FE FF (BEの場合) または FF FE 00 00 (LEの場合)です。

しかし、UTF-32 は BOM なしでも簡単に検出されます。 なぜなら、Unicode コードポイントの範囲は U+10FFFF に制限されているので、UTF-32 のユニットは常に 00 {00-10} xx xx (for BE) または xx xx {00-10} 00 というパターンを持っているからです(BE の場合)。00 (LEの場合) となります。 データの長さが4の倍数で、これらのパターンのいずれかに従っていれば、UTF-32と判断して差し支えはないでしょう。 バイト指向のエンコーディングでは 00 バイトがまれであるため、誤検出はほとんどありえません。

US-ASCII

BOM はありませんが、必要ありません。 ASCII は、80-FF の範囲のバイトがないことで簡単に識別することができます。

UTF-8

BOMはEF BB BFです。 しかし、これに依存することはできません。 多くの UTF-8 ファイルは BOM を持っておらず、特に Windows 以外のシステムで作成された場合はそうです。

しかし、ファイルが UTF-8 として検証された場合、そのファイルが です。 UTF-8 です。 誤検出はまれです。

具体的には、データが ASCII でないことを考慮すると、2 バイトのシーケンスに対する誤検出率はわずか 3.9% (1920/49152) です。 7 バイトのシーケンスでは、1% 未満です。 12バイトの場合、0.1%未満です。 24 バイトのシーケンスでは、100 万分の 1 未満です。

UTF-16

BOMはFE FF (BEの場合)またはFF FE (LEの場合)です。 UTF-16LE BOMはUTF-32LE BOMの最初に見つかるので、最初にUTF-32をチェックすることに注意してください。

ISO-8859-1 文字を主成分とするファイルがたまたまあった場合、ファイルのバイトの半分が 00 であることも UTF-16 の強力な指標となります。

それ以外の場合、BOM なしで UTF-16 を認識する唯一の信頼できる方法は、代理ペア (D[8-B]xx D[C-F]xx) を探すことですが、この方法を実用化するには、非 BMP 文字はあまりにもめったに使われないためです。

XML

ファイルが 3C 3F 78 6D 6C というバイトで始まっている場合 (つまり、ASCII 文字の "<?xml") は encoding= 宣言を探します。 もしあれば、そのエンコーディングを使用します。 ない場合は、デフォルトのXMLエンコーディングであるUTF-8を使用します。

EBCDICをサポートする必要がある場合、同等のシーケンスである4C 6F A7 94 93も探します。

一般的に、エンコーディング宣言を含むファイルフォーマットがある場合、エンコーディングを推測しようとするのではなく、その宣言を探します。

上記のどれでもない

他にも何百ものエンコーディングがあり、検出にはより多くの労力を必要とします。 私がお勧めするのは Mozilla の文字セット検出器 または それの .NET 移植版 .

合理的なデフォルト

UTF エンコーディングを除外し、別のエンコーディングを指すエンコーディング宣言や統計的な検出がない場合、次のように仮定します。 ISO-8859-1 または密接に関連する Windows-1252 . (なお、最新の HTML 規格では が必要です。 の宣言は Windows-1252 として解釈されることに注意してください)。 Windows の英語 (およびスペイン語、ポルトガル語、ドイツ語、フランス語などの一般的な言語) のデフォルト コード ページであり、UTF-8 以外のエンコーディングでは最もよく遭遇するものです。