(C#)文字コードを判別して、テキストファイルを読み込む方法
作ったもの
日本語テキストファイルのエンコード方式には、以下のようなものがあります。
①UTF-16(LE, BE)
②UTF-8
③Shift-JIS
④EUC-JP
これを自動的に判定して読み込む関数を作りました。
前提
using System.IO;
using System.Text;
コード
/// <summary> /// 自動的にエンコード方式を判定してテキストファイルを読み込みます。 /// </summary> /// <param name="path">ファイルパス</param> /// <returns>読み込んだ文字列</returns> static string ReadTextFile(string path) { Encoding encoding; return ReadTextFile(path, out encoding); } /// <summary> /// 自動的にエンコード方式を判定してテキストファイルを読み込みます。 /// </summary> /// <param name="path">ファイルパス</param> /// <param name="enc">エンコード方式</param> /// <returns>読み込んだ文字列</returns> static string ReadTextFile(string path, out Encoding enc) { var replacement = new DecoderReplacementFallback("�[FALLBACK]"); Func<int, Encoding> CodePageをEncodingに = (cp) => { var encoding = (Encoding)Encoding.GetEncoding(cp).Clone(); encoding.DecoderFallback = replacement; return encoding; }; int[] aryCP = { 65001, 932, 1200, 1201, 51932 }; int minLength = int.MaxValue; string result = null; enc = null; byte[] bytes = File.ReadAllBytes(path); foreach (var codepage in aryCP) { var encoding = CodePageをEncodingに(codepage); string s = encoding.GetString(bytes); int length = Encoding.UTF8.GetByteCount(s); if (length < minLength) { minLength = length; result = s; enc = encoding; } } return result; }
使い方
Encoding enc; string content = ReadTextFile(@"C:\Windows\Inst.log", out enc);
解説
何かが書かれたテキストファイルを様々な文字コードで開くと次のようになったとしましょう。
人間が見れば、UTF-8が正しいのは明らかですが、どのように判別すればいいのでしょうか。
3つを比べてみましょう。文字化けを起こすと、滅多に使わない文字が頻出したり、長い文字列になってしまうことが分かります。そこで実際に、これらの文字をUTF-8で符号化してみると、
となり、「C#の使い手」のサイズが最小で、正しそうだということが判定できます。
正しく復号できなかった時の代替文字は標準では「�」ですが、たったの3bytesなので、ひらがなと同じサイズです。そのため、「�[FALLBACK]」を代替文字列に設定して、復号エラーに対して13bytesのペナルティを与えています。