305

このアプリケーションでは、さまざまなソースからテキストファイル(、など)を受け取り.txtます.csv。読み取るときに、これらのファイルにはガベージが含まれることがあります。これは、ファイルが別の/不明なコードページで作成されたためです。

テキストファイルのコードページを(自動的に)検出する方法はありますか?

コンストラクターdetectEncodingFromByteOrderMarks上の、は、およびその他のUnicodeでマークされたファイルに対して機能しますが、、などの コードページを検出する方法を探しています。StreamReaderUTF8ibm850windows1252


あなたの答えをありがとう、これは私がしたことです。

私たちが受け取るファイルはエンドユーザーからのものであり、コードページについての手がかりはありません。受信者はエンドユーザーでもあります。これは、コードページについて知っていることです。コードページは存在し、煩わしいものです。

解決:

  • 受信したファイルをメモ帳で開き、文字化けしたテキストを確認します。誰かがフランソワか何かと呼ばれているなら、あなたの人間の知性であなたはこれを推測することができます。
  • ユーザーがファイルを開くために使用できる小さなアプリを作成し、正しいコードページが使用されたときにファイルに表示されることをユーザーが知っているテキストを入力します。
  • すべてのコードページをループし、ユーザーが提供したテキストで解決策を提供するコードページを表示します。
  • 複数のコードページが表示される場合は、ユーザーにさらにテキストを指定するように依頼してください。
4

21 に答える 21

267

コードページを検出できません。通知する必要があります。バイトを分析して推測することはできますが、奇妙な (場合によっては面白い) 結果が得られる可能性があります。今は見つけられませんが、メモ帳を騙して英語のテキストを中国語で表示できることは確かです。

とにかく、これはあなたが読む必要があるものです: すべてのソフトウェア開発者が絶対に、積極的にUnicodeと文字セットについて知っておくべき絶対最小値(言い訳はありません!) .

具体的には、ジョエルは次のように述べています。

エンコーディングに関する最も重要な事実

今説明したことを完全に忘れてしまった場合は、1 つの非常に重要な事実を思い出してください。使用するエンコーディングを知らずに文字列を取得しても意味がありません。砂の中に頭を突き刺して、「プレーン」テキストが ASCII であるふりをすることはできなくなりました。プレーンテキストなどというものはありません。

メモリ内、ファイル内、または電子メール メッセージ内に文字列がある場合、それがどのエンコーディングに含まれているかを知る必要があります。そうしないと、文字列を解釈したり、ユーザーに正しく表示したりできません。

于 2008-09-18T08:30:29.777 に答える
34

非 UTF エンコーディング (つまり、BOM なし) を検出しようとしている場合、基本的にテキストのヒューリスティックと統計分析にかかっています。ユニバーサル文字セット検出に関する Mozilla の論文(同じリンク、Wayback Machine を介したフォーマットの改善) をご覧になることをお勧めします。

于 2008-09-18T08:23:13.617 に答える
30

Mozilla Universal Charset Detector の C# ポートを試しましたか

http://code.google.com/p/ude/の例

public static void Main(String[] args)
{
    string filename = args[0];
    using (FileStream fs = File.OpenRead(filename)) {
        Ude.CharsetDetector cdet = new Ude.CharsetDetector();
        cdet.Feed(fs);
        cdet.DataEnd();
        if (cdet.Charset != null) {
            Console.WriteLine("Charset: {0}, confidence: {1}", 
                 cdet.Charset, cdet.Confidence);
        } else {
            Console.WriteLine("Detection failed.");
        }
    }
}    
于 2012-07-23T10:47:38.277 に答える
16

コードページを検出できません

これは明らかに誤りです。すべての Web ブラウザには、エンコーディングがまったく示されていないページを処理するための何らかの汎用文字セット検出器があります。Firefoxには1つあります。コードをダウンロードして、それがどのように機能するかを確認できます。こちらのドキュメントを参照してください。基本的に、これはヒューリスティックですが、非常にうまく機能します。

妥当な量のテキストがあれば、言語を検出することさえ可能です。

Googleを使用して見つけた別のものを次に示します。

于 2008-09-18T09:04:51.567 に答える
10

この質問には非常に遅れており、このソリューションは一部の人には魅力的ではないことを知っています(英語中心のバイアスと統計的/経験的テストの欠如のため)が、特にアップロードされたCSVデータの処理には非常にうまく機能しました:

http://www.architectshack.com/TextFileEncodingDetector.ashx

利点:

  • BOM検出内蔵
  • カスタマイズ可能なデフォルト/フォールバックエンコーディング
  • (私の経験では)UTF-8とLatin-1スタイルのファイルが混在するいくつかのエキゾチックなデータ(フランス語の名前など)を含む西ヨーロッパベースのファイル(基本的には米国と西ヨーロッパの環境の大部分)に対してかなり信頼できます。

注:このクラスを書いたのは私ですので、明らかに塩を一粒入れてください!:)

于 2011-04-29T09:20:17.950 に答える
7

別の解決策を探していると、

https://code.google.com/p/ude/

このソリューションはちょっと重いです。

最初の4バイトとおそらくxml文字セット検出に基づいた基本的なエンコーディング検出が必要だったので、インターネットからサンプルソースコードをいくつか取得し、わずかに変更されたバージョンの

http://lists.w3.org/Archives/Public/www-validator/2002Aug/0084.html

Java用に書かれています。

    public static Encoding DetectEncoding(byte[] fileContent)
    {
        if (fileContent == null)
            throw new ArgumentNullException();

        if (fileContent.Length < 2)
            return Encoding.ASCII;      // Default fallback

        if (fileContent[0] == 0xff
            && fileContent[1] == 0xfe
            && (fileContent.Length < 4
                || fileContent[2] != 0
                || fileContent[3] != 0
                )
            )
            return Encoding.Unicode;

        if (fileContent[0] == 0xfe
            && fileContent[1] == 0xff
            )
            return Encoding.BigEndianUnicode;

        if (fileContent.Length < 3)
            return null;

        if (fileContent[0] == 0xef && fileContent[1] == 0xbb && fileContent[2] == 0xbf)
            return Encoding.UTF8;

        if (fileContent[0] == 0x2b && fileContent[1] == 0x2f && fileContent[2] == 0x76)
            return Encoding.UTF7;

        if (fileContent.Length < 4)
            return null;

        if (fileContent[0] == 0xff && fileContent[1] == 0xfe && fileContent[2] == 0 && fileContent[3] == 0)
            return Encoding.UTF32;

        if (fileContent[0] == 0 && fileContent[1] == 0 && fileContent[2] == 0xfe && fileContent[3] == 0xff)
            return Encoding.GetEncoding(12001);

        String probe;
        int len = fileContent.Length;

        if( fileContent.Length >= 128 ) len = 128;
        probe = Encoding.ASCII.GetString(fileContent, 0, len);

        MatchCollection mc = Regex.Matches(probe, "^<\\?xml[^<>]*encoding[ \\t\\n\\r]?=[\\t\\n\\r]?['\"]([A-Za-z]([A-Za-z0-9._]|-)*)", RegexOptions.Singleline);
        // Add '[0].Groups[1].Value' to the end to test regex

        if( mc.Count == 1 && mc[0].Groups.Count >= 2 )
        {
            // Typically picks up 'UTF-8' string
            Encoding enc = null;

            try {
                enc = Encoding.GetEncoding( mc[0].Groups[1].Value );
            }catch (Exception ) { }

            if( enc != null )
                return enc;
        }

        return Encoding.ASCII;      // Default fallback
    }

ファイルからおそらく最初の 1024 バイトを読み取るだけで十分ですが、ファイル全体をロードしています。

于 2013-10-19T09:57:22.593 に答える
7

Notepad++ には、すぐに使えるこの機能があります。変更にも対応しています。

于 2010-08-06T19:13:52.677 に答える
4

ツール「uchardet」は、各文字セットの文字頻度分布モデルを使用してこれをうまく行います。ファイルが大きく、「典型的な」ファイルほど信頼性が高くなります (明らかに)。

ubuntu では、apt-get install uchardet.

他のシステムでは、 https ://github.com/BYVoid/ucharde からソース、使用方法、およびドキュメントを入手してください。

于 2013-12-03T14:20:41.193 に答える
4

私はPythonで似たようなことをしました。基本的に、さまざまなエンコーディングからのサンプル データが多数必要です。これらのサンプル データは、2 バイトのスライド ウィンドウで分割され、エンコーディングのリストの値を提供するバイト ペアをキーにして辞書 (ハッシュ) に格納されます。

その辞書 (ハッシュ) を指定すると、入力テキストを取得して、次のようになります。

  • 任意の BOM 文字 (UTF-16-BE の場合は '\xfe\xff'、UTF-16-LE の場合は '\xff\xfe'、UTF-8 の場合は '\xef\xbb\xbf' など) で始まる場合、私は提案どおりに扱う
  • そうでない場合は、テキストの十分な大きさのサンプルを取得し、サンプルのすべてのバイトペアを取得して、辞書から提案された最も一般的でないエンコーディングを選択します。

BOM で始まらないUTF でエンコードされたテキストもサンプリングした場合、2 番目のステップは最初のステップから抜け落ちたものをカバーします。

これまでのところ、エラー率が減少しており (サンプル データとその後の入力データはさまざまな言語の字幕です)、うまく機能しています。

于 2008-09-18T09:03:38.420 に答える
3

StreamReaderクラスのコンストラクターは、「エンコードの検出」パラメーターを取ります。

于 2008-09-18T08:04:28.747 に答える
1

同じ問題が発生しましたが、自動的に検出するための適切な解決策はまだ見つかりませんでした。今はそのために PsPad (www.pspad.com) を使用しています ;) 正常に動作します

于 2008-09-18T08:25:40.180 に答える
1

C ライブラリにリンクできる場合は、libenca. http://cihar.com/software/enca/を参照してください。マニュアルページから:

Enca は、指定されたテキスト ファイル、または指定されていない場合は標準入力を読み取り、言語に関する知識 (サポートが必要です) と、解析、統計分析、推測、黒魔術を組み合わせてエンコーディングを決定します。

GPL v2 です。

于 2013-03-27T03:25:12.507 に答える
0

私は実際にファイルエンコーディングを検出するためのプログラミングではなく一般的な方法を探していましたが、まだ見つかりませんでした。さまざまなエンコーディングでテストした結果、私のテキストは UTF-7 であることがわかりました。

だから私が最初にやったところ: StreamReader file = File.OpenText(fullfilename);

次のように変更する必要がありました: StreamReader file = new StreamReader(fullfilename, System.Text.Encoding.UTF7);

OpenText はそれが UTF-8 であると想定します。

この新しい StreamReader(fullfilename, true) のように StreamReader を作成することもできます。2 番目のパラメーターは、ファイルの byteordermark からエンコーディングを検出しようとすることを意味しますが、私の場合はうまくいきませんでした。

于 2010-08-20T12:31:49.920 に答える
0

cpanm Text::Unaccent と入力して perl モジュール Text::Unaccent::PurePerl をインストールしてみてください これにより build.log ファイルが生成され、一部のアプリケーションでは中国語として表示され、他のアプリケーションでは英語として表示されます cpanm は最初のテキストです 運が良ければもっともらしい試み言語にスペースを入れるのに十分なのは、統計テストを介して単語の分布頻度を比較することです

于 2022-02-12T15:06:08.743 に答える
0

基本的にヒューリスティックに帰着するため、同じソースから以前に受信したファイルのエンコーディングを最初のヒントとして使用すると役立つ場合があります。

ほとんどの人 (またはアプリケーション) は、ほぼ同じ順序で、多くの場合同じマシン上で毎回処理を行うため、Bob が .csv ファイルを作成して Mary に送信するときは、常に Windows-1252 または彼のマシンのデフォルトは何でも。

可能な場合は、少しの顧客トレーニングも問題ありません:-)

于 2008-12-29T19:42:00.367 に答える
0

ITmeze の投稿へのアドオンとして、この関数を使用して C# ポートの出力を Mozilla Universal Charset Detector 用に変換しました。

    private Encoding GetEncodingFromString(string codePageName)
    {
        try
        {
            return Encoding.GetEncoding(codePageName);
        }
        catch
        {
            return Encoding.ASCII;
        }
    }

MSDN

于 2015-09-03T09:37:33.990 に答える
-1

このコードを使用して、ファイルの読み取り時に Unicode と Windows のデフォルトの ansi コードページを検出します。他のコーディングについては、手動またはプログラミングによるコンテンツのチェックが必要です。これを使用して、テキストを開いたときと同じエンコーディングで保存できます。(私はVB.NETを使用しています)

'Works for Default and unicode (auto detect)
Dim mystreamreader As New StreamReader(LocalFileName, Encoding.Default) 
MyEditTextBox.Text = mystreamreader.ReadToEnd()
Debug.Print(mystreamreader.CurrentEncoding.CodePage) 'Autodetected encoding
mystreamreader.Close()
于 2012-06-02T10:39:54.770 に答える