it-swarm-tr.com

Bir metin dosyasının kodlamasını/kod sayfasını nasıl tespit edebilirim

Uygulamamızda çeşitli kaynaklardan metin dosyaları (.txt, .csv, vb.) Alıyoruz. Okurken, bu dosyalar bazen çöp içerir, çünkü dosyalar farklı/bilinmeyen bir kod sayfasında yaratılır.

Bir metin dosyasının kod sayfasını (otomatik olarak) tespit etmenin bir yolu var mı? 

detectEncodingFromByteOrderMarks yapıcısı üzerindeki StreamReader, UTF8 ve diğer unicode işaretli dosyalar için çalışır, ancak ibm850, windows1252 gibi kod sayfalarını tespit etmenin bir yolunu arıyorum. 


Cevaplarınız için teşekkürler, yaptığım şey bu.

Aldığımız dosyalar son kullanıcılardan geliyor, kod sayfaları hakkında hiçbir ipucu yok. Alıcıları da son kullanıcılar, şimdiye dek kod sayfaları hakkında bildikleri şey: Kod sayfaları var ve can sıkıcı.

Çözüm:  

  • Alınan dosyayı Not Defteri'nde açın, bozuk bir metne bakın. Birine François veya başka bir şey deniyorsa, insan zekanızla bunu tahmin edebilirsiniz.
  • Kullanıcının dosyayı açmak için kullanabileceği küçük bir uygulama oluşturdum ve doğru kod sayfası kullanıldığında, kullanıcının dosyada görüneceğini bildiği bir metni girin. 
  • Tüm kod sayfalarında dolaşın ve kullanıcı tarafından sağlanan metinle birlikte çözüm olanları görüntüleyin. 
  • Birden fazla kod sayfası açılırsa, kullanıcıdan daha fazla metin belirtmesini isteyin.
283
GvS

Kod sayfasını tespit edemezsiniz, size söylenmesi gerekir. Baytları analiz edebilir ve tahmin edebilirsiniz, ancak bu bazı tuhaf (bazen eğlenceli) sonuçlar verebilir. Şimdi bulamıyorum, ancak Not Defteri'nin Çince İngilizce metin görüntülemek için kandırılabileceğinden eminim. 

Her neyse, okumanız gereken bu: Mutlak, Her Yazılım Geliştiricisinin Mutlak En Az, Kesinlikle Unicode ve Karakter Kümeleri Hakkında Bilmeniz Gerekenler (Mazeret Yok!) .

Özellikle Joel diyor ki:

Kodlamalar Hakkında En Önemli Tek Şey

Az önce açıkladığım her şeyi tamamen unutursanız, lütfen son derece önemli bir gerçeği unutmayın. Hangi kodlamayı kullandığını bilmeden bir dizgeye sahip olmak mantıklı gelmiyor. Artık başınızı kuma sokamaz ve "düz" metnin ASCII ..__ olduğunu iddia edemezsiniz. Düz Metin Gibi Bir Şey Yok.

Bir dizginiz varsa, bellekte, bir dosyada veya bir e-posta iletisinde, hangi kodlamanın içinde olduğunu bilmeniz gerekir, onu yorumlayamaz veya kullanıcılara doğru gösteremezsiniz.

255
JV.

UTF olmayan kodlamaları tespit etmek istiyorsanız (yani, ürün reçetesi yok), temel olarak metnin sezgisel ve istatistiksel analizine düşersiniz. Mozilla makalesine evrensel karakter kümesi algılama ( aynı bağlantıya, Wayback Machine ) üzerinden daha iyi biçimlendirme ile bakmak isteyebilirsiniz.

30
Tomer Gabel

Denediniz mi Mozilla Universal Charset Detector için C # portu

http://code.google.com/p/ude/ adresinden örnek

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

Kod sayfasını algılayamıyorsunuz

Bu açıkça yanlıştır. Her web tarayıcısının, herhangi bir kodlama belirtisi olmayan sayfalarla uğraşması için bir tür evrensel karakter dedektörü vardır. Firefox'ta bir tane var. Kodu indirebilir ve nasıl yaptığını görebilirsiniz. Bazı belgelere bakın here . Temel olarak, bir sezgisel, ama gerçekten iyi çalışıyor.

Makul miktarda metin verildiğinde, dili tespit etmek bile mümkündür.

İşte bir tane daha Google’ı kullanırken yeni buldum:

15
shoosh

Bu soru için çok geç olduğunu biliyorum ve bu çözüm bazılarına hitap etmeyecek (İngilizce merkezli önyargıları ve istatistiksel/ampirik testlerin olmayışı nedeniyle), ama özellikle yüklenen CSV verilerini işlemek için benim için çok iyi çalıştı:

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

Avantajları:

  • BOM algılama yerleşik
  • Özelleştirilebilir varsayılan/geri dönüş kodlaması
  • aBD ve Batı Avrupa ortamlarının büyük bir kısmı olan UTF-8 ve Latin-1 tarzı dosyaların bir karışımını içeren bazı egzotik veriler (örneğin, fransız isimleri) içeren batı-avrupa tabanlı dosyalar için oldukça güvenilir (benim tecrübeme göre).

Not: Bu dersi yazan benim, bu yüzden belli ki onu tuzla al! :)

8
Tao

Farklı bir çözüm arıyorum, buldum 

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

bu çözüm çok ağır.

4 ilk bayt ve muhtemelen xml karakter kümesi saptamasını temel alan bazı temel kodlama tespitlerine ihtiyacım vardı - bu yüzden internetten bazı örnek kaynak kodları aldım ve biraz değiştirilmiş versiyonu ekledim.

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

java için yazılmış.

    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
    }

Muhtemelen ilk 1024 byte'ı dosyadan okumak yeterlidir, ancak bütün dosyayı yüklüyorum.

7
TarmoPikaro

Notepad ++ , kutusundan çıkma özelliği vardır. Ayrıca değiştirmeyi de destekler.

7
hegearon

Birisi% 93.9 çözüm arıyorsa. Bu benim için çalışıyor:

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

Python'da da benzer bir şey yaptım. Temel olarak, kayan iki baytlık bir pencere tarafından parçalanan ve kodlama listelerinin değerlerini sağlayan bayt çiftleri ile anahtarlanmış bir sözlükte (karma) saklanan çeşitli kodlamalardan çok sayıda örnek verilere ihtiyacınız vardır.

Bu sözlüğe bakıldığında (karma), giriş metninizi alırsınız ve:

  • herhangi bir BOM karakteriyle başlasa (UTF-16-BE için '\ xfe\xff', UTF-16-LE için '\ xff\xfe', UTF-8-LE için '\ xef\xbb\xbf' vb.) önerildiği gibi davran
  • eğer değilse, o zaman metnin yeterince büyük bir örneğini alın, örneğin tüm bayt çiftlerini alın ve sözlükten önerilen en az kullanılan kodlamayı seçin.

Ayrıca herhangi bir malzeme listesi ile başlayan değil ile başlayan UTF kodlu metinleri de örneklediyseniz, ikinci adım, ilk adımdan kaybolanları kapsayacaktır.

Şimdiye kadar, azalan hata oranlarıyla benim için çalışıyor (örnek veriler ve sonraki girdi verileri çeşitli dillerde altyazılardır).

4
tzot

"Uchardet" aracı her karakter grubu için karakter frekansı dağıtım modellerini kullanarak bunu iyi yapar. Daha büyük dosyalar ve daha "tipik" dosyalar daha belirgindir (açıkçası).

Ubuntu'da, sadece apt-get install uchardet

Diğer sistemlerde kaynağı, kullanımı ve belgeleri buradan alın: https://github.com/BYVoid/uchardet

3
Erik Aronesty

StreamReader sınıfının yapıcısı bir 'kodlama tespit' parametresi alır.

3
leppie

Bir C kütüphanesine bağlanabiliyorsanız, libenca öğesini kullanabilirsiniz. Bkz. http://cihar.com/software/enca/ . Man sayfasından:

Enca verilen metin dosyalarını okur veya hiçbiri verilmediğinde standart girişi yapar, ve dilleri hakkındaki bilgileri kullanır (sizin tarafınızdan desteklenmelidir) ve. ayrıştırma, istatistiksel analiz, tahmin ve kara büyü karışımı. kodlamalarını belirlemek için.

GPL v2.

1
Kundor

Aynı problemi çözdüm fakat henüz otomatik olarak tespit etmek için iyi bir çözüm bulamadım ..

0
DeeCee

Teşekkürler @ Erik Aronestyuchardet'dan bahsettiğin için.

Bu arada (aynı?) Aracı linux için de var: chardet.
Veya, cygwin'de kullanmak isteyebilirsiniz: chardetect.

Bakınız: chardet man sayfası:https://www.commandlinux.com/man-page/man1/chardetect.1.html

Bu, verilen her dosya için karakter kodlamasını sezgisel olarak algılar (tahmin eder) ve her dosyanın algılanan karakter kodlaması için ad ve güven düzeyini bildirir.

0
Schlacki

Aslında dosya kodlamasını tespit etmenin genel, programlama yolunu aramıyordum, ama henüz bunu bulamadım . Farklı kodlamalarla test ederek buldum, metnimin UTF-7 olmasıydı.

Peki ilk yaptığım yer: StreamReader file = File.OpenText (fullfilename);

Bunu değiştirmek zorunda kaldım: StreamReader file = new StreamReader (tam dosyaadı, System.Text.Encoding.UTF7);

OpenText bunun UTF-8 olduğunu varsayar.

ayrıca StreamReader'ı bu şekilde oluşturabilirsiniznew StreamReader (fullfilename, true), ikinci parametre, dosyanın byteordermark'ından gelen kodlamayı denemeyi ve algılamayı denemesi gerektiği anlamına gelir;.

0
Intraday Tips

ITmeze postuna ek olarak, bu işlevi Mozilla Universal Charset Detector için C # portunun çıkışını dönüştürmek için kullandım.

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

MSDN

0
PrivatePyle

Dosyayı AkelPad'de açın (veya bozuk bir metni kopyalayın/yapıştırın), Düzenle -> Seçim -> Recode ... -> "Autodetect" işaretine gidin.

0
plavozont

Temel olarak buluşsal bulguyla ilgili olduğu için, daha önce alınan dosyaların kodlamasını ilk ipucuyla aynı kaynaktan kullanmak yardımcı olabilir.

Çoğu kişi (veya uygulama), genellikle aynı makinede her seferinde hemen hemen aynı sırada işlem yapar, bu yüzden Bob bir .csv dosyası oluşturup Mary'ye gönderdiğinde her zaman Windows-1252 veya onun makinesi ne olursa olsun varsayılan.

Mümkün olduğunda, biraz müşteri eğitimi hiçbir zaman zarar görmez :-)

0
devstuff

Bu sorulduğundan bu yana 10Y (!) Geçildi ve hala MS'in GPL olmayan iyi çözümünden bahsetmiyorum: IMultiLanguage2 API.

Bahsedilen çoğu kütüphane Mozilla'nın UDE'sine dayanmaktadır - ve tarayıcıların zaten benzer problemleri çözmüş olması makul görünmektedir. Kromun çözümünün ne olduğunu bilmiyorum, ancak IE 5.0 MS bu yana serbest bırakıldı ve bu:

  1. GPL ve benzeri lisanslama sorunlarından muaf,
  2. Sonsuza dek desteklenmiş ve korunmuş,
  3. Zengin çıktı verir - kodlama/kod sayfaları için geçerli olan tüm adayları güven puanlarıyla birlikte verir,
  4. Şaşırtıcı derecede kullanımı kolay (tek bir işlev çağrısıdır).

Yerel bir COM çağrısıdır, ancak .net kullanımı için birlikte çalışma karmaşasını işleyen Carsten Zeumer tarafından işte bazı çok güzel işler . Etrafta bazıları var ama bu kütüphanenin büyük kısmı hak ettiği ilgiyi görmüyor.

0
Ofek Shilon