テキストファイルの文字エンコードを検出する方法は?
-
12-10-2019 - |
質問
ファイルで使用される文字エンコードを検出しようとします。
標準のエンコードを取得するためにこのコードで試してみてください
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つの最初のバイトは、60、118、56、46、49です。
これらの5つの最初のバイトと一致するエンコードを示すチャートはありますか?
解決
BOMを持っているファイルに依存することはできません。 UTF-8はそれを必要としません。そして、非ユニコードエンコーディングにはBOMさえありません。ただし、エンコードを検出する他の方法があります。
UTF-32
BOMは00 00 Fe ff(be)またはff fe 00 00(leの場合)です。
しかし、UTF-32はBOMがなくても簡単に検出できます。これは、ユニコードコードポイント範囲がu+10ffffに制限されているため、UTF-32ユニットには常にパターン00 {00-10} xx xx(be)またはxx xx {00-10} 00(leの場合)があるためです。 。データの長さは4の倍数で、これらのパターンの1つに従う場合、UTF-32であると安全に想定できます。バイト指向のエンコーディングの00バイトの希少性により、誤検知はほとんど不可能です。
us-ascii
ボムはありませんが、必要はありません。 ASCIIは、80-ff範囲のバイトの不足によって簡単に識別できます。
UTF-8
bomはef bb bfです。しかし、あなたはこれに頼ることはできません。 UTF-8ファイルの多くは、特に非窓システムで発生した場合、BOMを持っていません。
しかし、ファイルがUTF-8として検証された場合、それは安全に想定することができます は UTF-8。誤検知はまれです。
具体的には、データがASCIIではないことを考えると、2バイトシーケンスの偽陽性率はわずか3.9%(1920/49152)です。 7バイトのシーケンスの場合、1%未満です。 12バイトシーケンスの場合、0.1%未満です。 24バイトのシーケンスの場合、100万人に1人未満です。
UTF-16
bomはFe ff(for be)またはff fe(for le)です。 UTF-16LE BOMはUTF-32LE BOMの開始時に見つかっているため、最初にUTF-32を確認してください。
主にISO-8859-1文字で構成されるファイルがある場合、ファイルのバイトの半分が00であることも、UTF-16の強力な指標です。
それ以外の場合は、BOMなしでUTF-16を認識する唯一の信頼できる方法は、代理ペア(D [8-B] XX D [CF] XX)を探すことですが、非BMP文字はあまりにも使用されず、このアプローチを実用化することはめったにありません。
XML
ファイルがバイト3c 3f 78 6d 6cで始まる場合(つまり、ASCII文字」 encoding=
宣言。存在する場合は、そのエンコードを使用します。不在の場合は、デフォルトのXMLエンコードであるUTF-8を想定します。
EBCDICをサポートする必要がある場合は、同等のシーケンス4C 6F A7 94 93も探してください。
一般に、エンコーディング宣言を含むファイル形式がある場合は、エンコードを推測しようとするのではなく、その宣言を探します。
上記のどれでもない
他にも何百ものエンコーディングがあり、より多くの努力を検出する必要があります。試してみることをお勧めします MozillaのCharset Detector また それの.NETポート.
妥当なデフォルト
UTFエンコーディングを除外し、別のエンコードを指すエンコーディング宣言や統計的検出がない場合は、想定してください ISO-8859-1 または密接に関連する Windows-1252. 。 (最新のHTML標準に注意してください 必要 「ISO-8859-1」宣言はWindows-1252として解釈される宣言です。)英語(およびスペイン語、ポルトガル語、ドイツ語、フランス語などの他の人気言語)のWindowsのデフォルトコードページであるため、それは以外で最も一般的に遭遇するエンコードです。 UTF-8。
他のヒント
「シンプルな」ソリューションを追求したい場合は、このクラスを組み立てて役立つと思われる場合があります。
http://www.architectshack.com/textfileencodingdetector.ashx
最初にBOM検出が自動的に検出され、次にBOMなしでユニコードエンコーディングを区別しようとします。それと、他のデフォルトエンコード(通常、Windows-1252は、.NETのEncoding.asciiとして誤ってラベル付けされています)。
上記のように、NCHARDETまたはMLANGを含む「より重い」ソリューションがより適切かもしれません。このクラスの概要ページで注意するように、最良のことは、可能であれば、可能であれば、ユーザーと何らかの形の互換性を提供することです。 100%の検出率は不可能です!
使用する StreamReader
そして、あなたのためのエンコーディングを検出するように指示してください:
using (var reader = new System.IO.StreamReader(path, true))
{
var currentEncoding = reader.CurrentEncoding;
}
そして使用します コードページ識別子 https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspxロジックに応じて切り替えるため。
ここにはいくつかの答えがありますが、誰も有用なコードを投稿していません。
MicrosoftがStreamReaderクラスのフレームワーク4で検出するすべてのエンコーディングを検出する私のコードです。
BOMはストリーム内の最初のバイトであるため、ストリームから他のものを読む前に、ストリームを開いた直後にこの関数を呼び出す必要があります。
この関数には、(たとえば、FileStream)を探すことができるストリームが必要です。あなたがあなたを探すことができないストリームがある場合、あなたがすでに読まれているが生まれていないバイトでバイトバッファーを返すより複雑なコードを書く必要があります。
/// <summary>
/// UTF8 : EF BB BF
/// UTF16 BE: FE FF
/// UTF16 LE: FF FE
/// UTF32 BE: 00 00 FE FF
/// UTF32 LE: FF FE 00 00
/// </summary>
public static Encoding DetectEncoding(Stream i_Stream)
{
if (!i_Stream.CanSeek || !i_Stream.CanRead)
throw new Exception("DetectEncoding() requires a seekable and readable Stream");
// Try to read 4 bytes. If the stream is shorter, less bytes will be read.
Byte[] u8_Buf = new Byte[4];
int s32_Count = i_Stream.Read(u8_Buf, 0, 4);
if (s32_Count >= 2)
{
if (u8_Buf[0] == 0xFE && u8_Buf[1] == 0xFF)
{
i_Stream.Position = 2;
return new UnicodeEncoding(true, true);
}
if (u8_Buf[0] == 0xFF && u8_Buf[1] == 0xFE)
{
if (s32_Count >= 4 && u8_Buf[2] == 0 && u8_Buf[3] == 0)
{
i_Stream.Position = 4;
return new UTF32Encoding(false, true);
}
else
{
i_Stream.Position = 2;
return new UnicodeEncoding(false, true);
}
}
if (s32_Count >= 3 && u8_Buf[0] == 0xEF && u8_Buf[1] == 0xBB && u8_Buf[2] == 0xBF)
{
i_Stream.Position = 3;
return Encoding.UTF8;
}
if (s32_Count >= 4 && u8_Buf[0] == 0 && u8_Buf[1] == 0 && u8_Buf[2] == 0xFE && u8_Buf[3] == 0xFF)
{
i_Stream.Position = 4;
return new UTF32Encoding(true, true);
}
}
i_Stream.Position = 0;
return Encoding.Default;
}
あなたはこれを読むべきです: テキストファイルのエンコーディング/コードページを検出するにはどうすればよいですか
ファイルがバイト60、118、56、46、49から始まる場合、あいまいなケースがあります。 UTF-8(BOMなし)またはASCII、ANSI、ISO-8859-1などの単一バイトエンコーディングのいずれかである可能性があります。
私が使う ude これは、Mozilla Universal Charset DetectorのC#ポートです。使いやすく、本当に良い結果が得られます。