it-swarm-id.com

Bagaimana saya dapat mengkonversi encoding/codepage dari file teks

Dalam aplikasi kami, kami menerima file teks (.txt, .csv, dll.) Dari berbagai sumber. Saat membaca, file-file ini kadang-kadang mengandung sampah, karena file-file di mana dibuat dalam codepage yang berbeda/tidak dikenal.

Apakah ada cara untuk (secara otomatis) mendeteksi codepage dari file teks? 

detectEncodingFromByteOrderMarks, pada konstruktor StreamReader, berfungsi untuk UTF8 dan file bertanda unicode lainnya, tetapi saya sedang mencari cara untuk mendeteksi halaman kode, seperti ibm850, windows1252


Terima kasih atas jawaban Anda, inilah yang saya lakukan.

File yang kami terima berasal dari pengguna akhir, mereka tidak memiliki petunjuk tentang codepage. Penerima juga adalah pengguna akhir, sekarang ini yang mereka ketahui tentang codepage: Codepage ada, dan menjengkelkan.

Solusi:  

  • Buka file yang diterima di Notepad, lihat sepotong teks yang kacau. Jika seseorang disebut François atau sesuatu, dengan kecerdasan manusia Anda, Anda dapat menebaknya.
  • Saya telah membuat aplikasi kecil yang dapat digunakan pengguna untuk membuka file, dan memasukkan teks yang pengguna tahu akan muncul di file, ketika codepage yang benar digunakan. 
  • Ulangi semua kode halaman, dan tampilkan yang memberikan solusi dengan teks yang disediakan pengguna. 
  • Jika lebih dari satu codepage muncul, minta pengguna untuk menentukan lebih banyak teks.
283
GvS

Anda tidak dapat mendeteksi codepage, Anda harus diberi tahu. Anda dapat menganalisis byte dan menebaknya, tetapi itu bisa memberikan hasil yang aneh (terkadang lucu). Saya tidak dapat menemukannya sekarang, tetapi saya yakin Notepad dapat diperdaya untuk menampilkan teks bahasa Inggris dalam bahasa Mandarin. 

Bagaimanapun, ini adalah apa yang perlu Anda baca: Minimum Mutlak Setiap Pengembang Perangkat Lunak Sepenuhnya, Pasti Harus Tahu Tentang Unicode dan Karakter Set (Tanpa Alasan!) .

Secara khusus Joel mengatakan:

Satu Fakta Paling Penting Tentang Penyandian

Jika Anda benar-benar melupakan semua yang baru saja saya jelaskan, harap ingat satu fakta yang sangat penting. Tidak masuk akal memiliki string tanpa mengetahui pengkodean apa yang digunakannya. Anda tidak dapat lagi menjulurkan kepala ke pasir dan berpura-pura bahwa teks "biasa" adalah ASCII . Tidak Ada Hal Seperti Teks Biasa.

Jika Anda memiliki string, dalam memori, dalam file, atau dalam pesan email, Anda harus tahu apa itu pengkodean atau Anda tidak dapat menafsirkannya atau menampilkannya kepada pengguna dengan benar.

255
JV.

Jika Anda ingin mendeteksi penyandian non-UTF (mis. Tidak ada BOM), Anda pada dasarnya turun ke heuristik dan analisis statistik teks. Anda mungkin ingin melihat kertas Mozilla pada deteksi charset universal ( tautan yang sama, dengan pemformatan yang lebih baik melalui Wayback Machine ).

30
Tomer Gabel

Sudahkah Anda mencoba port C # untuk Mozilla Universal Charset Detector

Contoh dari 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.");
        }
    }
}    
21
ITmeze

Anda tidak dapat mendeteksi codepage

Ini jelas salah. Setiap browser web memiliki semacam detektor charset universal untuk menangani halaman yang tidak memiliki indikasi penyandian apa pun. Firefox punya satu. Anda dapat mengunduh kode dan melihat bagaimana melakukannya. Lihat beberapa dokumentasi di sini . Pada dasarnya, ini heuristik, tetapi bekerja dengan sangat baik.

Mengingat jumlah teks yang masuk akal, bahkan dimungkinkan untuk mendeteksi bahasa.

Ini satu lagi Saya baru saja menemukan menggunakan Google:

15
shoosh

Saya tahu ini sudah sangat terlambat untuk pertanyaan ini dan solusi ini tidak akan menarik bagi beberapa orang (karena bias bahasa Inggris-sentris dan kurangnya statistik/pengujian empiris), tetapi ini bekerja sangat baik bagi saya, terutama untuk memproses data CSV yang diunggah:

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

Keuntungan:

  • Deteksi BOM bawaan
  • Pengkodean default/cadangan dapat disesuaikan
  • cukup dapat diandalkan (dalam pengalaman saya) untuk file berbasis Eropa-Eropa yang berisi beberapa data eksotis (misalnya nama Perancis) dengan campuran file gaya UTF-8 dan Latin-1 - pada dasarnya sebagian besar lingkungan AS dan Eropa barat.

Catatan: Akulah yang menulis kelas ini, jadi jelas bawa dengan sebutir garam! :)

8
Tao

Mencari solusi yang berbeda, saya menemukan itu 

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

solusi ini agak berat.

Saya memerlukan deteksi dasar pengkodean, berdasarkan 4 byte pertama dan mungkin deteksi charset xml - jadi saya telah mengambil beberapa kode sumber sampel dari internet dan menambahkan versi modifikasi

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

ditulis untuk 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
    }

Cukup membaca mungkin 1024 byte pertama dari file, tapi saya memuat seluruh file.

7
TarmoPikaro

Notepad ++ memiliki fitur ini di luar kotak. Ini juga mendukung mengubahnya.

7
hegearon

Jika seseorang mencari solusi 93,9%. Ini bekerja untuk saya:

public static class StreamExtension
{
    /// <summary>
    /// Convert the content to a string.
    /// </summary>
    /// <param name="stream">The stream.</param>
    /// <returns></returns>
    public static string ReadAsString(this Stream stream)
    {
        var startPosition = stream.Position;
        try
        {
            // 1. Check for a BOM
            // 2. or try with UTF-8. The most (86.3%) used encoding. Visit: http://w3techs.com/technologies/overview/character_encoding/all/
            var streamReader = new StreamReader(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true);
            return streamReader.ReadToEnd();
        }
        catch (DecoderFallbackException ex)
        {
            stream.Position = startPosition;

            // 3. The second most (6.7%) used encoding is ISO-8859-1. So use Windows-1252 (0.9%, also know as ANSI), which is a superset of ISO-8859-1.
            var streamReader = new StreamReader(stream, Encoding.GetEncoding(1252));
            return streamReader.ReadToEnd();
        }
    }
}
5
Magu

Saya telah melakukan sesuatu yang serupa dengan Python. Pada dasarnya, Anda memerlukan banyak data sampel dari berbagai pengkodean, yang dipecah oleh jendela dua byte geser dan disimpan dalam kamus (hash), dikunci pada byte-pasangan memberikan nilai daftar pengkodean.

Dengan kamus (hash) itu, Anda mengambil teks input dan:

  • jika dimulai dengan karakter BOM ('\ xfe\xff' untuk UTF-16-BE, '\ xff\xfe' untuk UTF-16-LE, '\ xef\xbb\xbf' untuk UTF-8 dll), saya perlakukan seperti yang disarankan
  • jika tidak, maka ambil sampel teks yang cukup besar, ambil semua byte-pasang sampel dan pilih pengkodean yang paling jarang disarankan dari kamus.

Jika Anda juga mengambil sampel teks yang disandikan UTF yang tidak tidak dimulai dengan BOM apa pun, langkah kedua akan mencakup teks-teks yang tergelincir dari langkah pertama.

Sejauh ini, ini berfungsi untuk saya (data sampel dan data input berikutnya adalah subtitle dalam berbagai bahasa) dengan tingkat kesalahan yang semakin berkurang.

4
tzot

Alat "uchardet" melakukan ini dengan baik menggunakan model distribusi frekuensi karakter untuk setiap rangkaian karakter. File yang lebih besar dan lebih banyak "tipikal" file memiliki lebih banyak kepercayaan diri (jelas).

Di ubuntu, Anda hanya apt-get install uchardet

Di sistem lain, dapatkan sumber, penggunaan & dokumen di sini: https://github.com/BYVoid/uchardet

3
Erik Aronesty

Konstruktor kelas StreamReader mengambil parameter 'deteksi penyandian'.

3
leppie

Jika Anda dapat menautkan ke pustaka C, Anda dapat menggunakan libenca. Lihat http://cihar.com/software/enca/ . Dari halaman manual:

Enca membaca file teks yang diberikan, atau input standar ketika tidak ada yang diberikan, dan menggunakan pengetahuan tentang bahasa mereka (harus didukung oleh Anda) dan campuran penguraian, analisis statistik, menebak dan ilmu hitam untuk menentukan penyandiannya.

Ini GPL v2.

1
Kundor

Mendapat masalah yang sama tetapi belum menemukan solusi yang baik untuk mendeteksi secara otomatis . Sekarang saya menggunakan PsPad (www.pspad.com) untuk itu;) Bekerja dengan baik

0
DeeCee

Terima kasih @ Erik Aronesty untuk menyebutkan uchardet.

Sementara itu alat (sama?) Ada untuk linux: chardet.
Atau, pada cygwin Anda mungkin ingin menggunakan: chardetect.

Lihat: halaman manual chardet:https://www.commandlinux.com/man-page/man1/chardetect.1.html

Ini akan secara heuristik mendeteksi (menebak) pengkodean karakter untuk setiap file yang diberikan dan akan melaporkan nama dan tingkat kepercayaan untuk setiap pengkodean karakter yang terdeteksi dari setiap file.

0
Schlacki

Saya sebenarnya mencari cara pemrograman generik, bukan untuk mendeteksi pengkodean file, tetapi saya belum menemukannya . Apa yang saya temukan dengan pengujian dengan pengkodean yang berbeda adalah bahwa teks saya adalah UTF-7.

Jadi di mana saya pertama kali lakukan: StreamReader file = File.OpenText (fullfilename);

Saya harus mengubahnya ke: StreamReader file = new StreamReader (fullfilename, System.Text.Encoding.UTF7);

OpenText menganggap itu UTF-8.

anda juga dapat membuat StreamReader seperti ininew StreamReader (fullfilename, true), parameter kedua yang berarti harus mencoba dan mendeteksi pengkodean dari byteordermark file, tetapi itu tidak berfungsi dalam kasus saya.

0
Intraday Tips

Sebagai tambahan pada posting ITmeze, saya telah menggunakan fungsi ini untuk mengubah output port C # untuk Mozilla Universal Charset Detector

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

MSDN

0
PrivatePyle

Buka file di AkelPad (atau cukup salin/tempel teks yang kacau), buka Edit -> Selection -> Recode ... -> centang "Autodetect".

0
plavozont

Karena pada dasarnya turun ke heuristik, mungkin membantu menggunakan pengkodean file yang sebelumnya diterima dari sumber yang sama sebagai petunjuk pertama.

Kebanyakan orang (atau aplikasi) melakukan hal-hal dalam urutan yang hampir sama setiap kali, sering pada mesin yang sama, sehingga sangat mungkin bahwa ketika Bob membuat file .csv dan mengirimkannya ke Mary, ia akan selalu menggunakan Windows-1252 atau apa pun default mesinnya.

Jika memungkinkan, sedikit pelatihan pelanggan tidak ada salahnya juga :-)

0
devstuff

10Y (!) Telah berlalu sejak ini ditanyakan, dan saya masih melihat tidak menyebutkan solusi MS yang baik, non-GPL: IMultiLanguage2 API.

Sebagian besar perpustakaan yang telah disebutkan didasarkan pada UDE Mozilla - dan tampaknya masuk akal bahwa browser telah mengatasi masalah yang sama. Saya tidak tahu apa solusi chrome, tetapi karena IE 5.0 MS telah merilis solusi mereka, dan itu adalah:

  1. Bebas dari masalah lisensi GPL dan sejenisnya,
  2. Didukung dan dipelihara mungkin selamanya,
  3. Memberikan hasil yang kaya - semua kandidat yang valid untuk encoding/codepages bersama dengan skor kepercayaan,
  4. Sangat mudah digunakan (ini adalah panggilan fungsi tunggal).

Ini adalah panggilan COM asli, tetapi inilah beberapa pekerjaan yang sangat bagus oleh Carsten Zeumer, yang menangani kekacauan interop untuk penggunaan .net. Ada beberapa yang lain di sekitar, tetapi pada umumnya perpustakaan ini tidak mendapatkan perhatian yang layak.

0
Ofek Shilon