Domanda

Nella nostra applicazione, abbiamo visualizzato i file di testo (.txt, .csv, etc.) da fonti diverse.Durante la lettura di questi file contengono talvolta spazzatura, perché i file sono stati creati in un altro/sconosciuto codepage.

C'è un modo per (automaticamente) rilevare i codici di un file di testo?

Il detectEncodingFromByteOrderMarks, sulla StreamReader costruttore di opere per UTF8 e altri unicode file selezionati, ma sto cercando un modo per rilevare le pagine di codice, come ibm850, windows1252.


Grazie per le vostre risposte, questo è quello che ho fatto.

I file che riceviamo dagli utenti finali, non hanno un indizio su tabelle di codici.I ricevitori sono anche gli utenti finali, per ora questo è quello che sanno sulle tabelle codici:Tabelle codici esistono, e sono fastidiosi.

Soluzione:

  • Aprire il file ricevuto in blocco note, guardare un incomprensibile pezzo di testo.Se qualcuno è chiamato François o qualcosa del genere, con la tua intelligenza umana si può intuire questo.
  • Ho creato una piccola applicazione che l'utente può utilizzare per aprire il file e immettere un testo che l'utente sa che appaiono nel file, quando il codepage corretta è utilizzato.
  • Loop attraverso tutte le tabelle di codici e visualizzare quelli che danno una soluzione con l'utente ha fornito il testo.
  • Se più come una tabella codici pop up, chiedere all'utente di specificare il testo più.
È stato utile?

Soluzione

Non è possibile rilevare il codepage, hai bisogno di essere raccontato.È possibile analizzare i byte e l'indovino, ma che può dare qualche bizzarro (a volte divertente) risultati.Io non riesco a trovarlo ora, ma sono sicuro che il blocco note può essere ingannato la visualizzazione di testo in inglese e in Cinese.

Comunque, questo è ciò che è necessario per la lettura:Il Minimo Assoluto di Ogni Sviluppatore di Software Assolutamente, Positivamente Deve Sapere Su Unicode e Set di Caratteri (Scuse!).

In particolare Joel dice:

L'Unico Fatto Importante Circa Le Codifiche

Se si dimentica completamente tutto ciò che ho appena spiegato, si prega di ricordare un fatto estremamente importante.Non ha senso avere una stringa senza sapere che cosa la codifica utilizzata.Non è più possibile attaccare la testa sotto la sabbia e far finta che la "normale" testo ASCII.Ci non è Alcuna Cosa Come Testo Normale.

Se si dispone di una stringa in memoria, in un file o in un messaggio di posta elettronica, è necessario sapere che cosa la codifica è o non è possibile interpretare o visualizzare per gli utenti correttamente.

Altri suggerimenti

Se stai cercando di rilevare la mancanza di codifiche UTF (es.no BOM), in pratica sei giù a euristica e l'analisi statistica del testo.Si potrebbe desiderare di dare un'occhiata al Mozilla carta universale charset rilevamento (stesso link, con una migliore formattazione via Wayback Machine).

Hai provato C# porta per Mozilla Universale Charset Rivelatore

Esempio 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.");
        }
    }
}    

Non è possibile rilevare la tabella codici

Questo è chiaramente falsa.Ogni browser ha un certo tipo di universale charset rilevatore di trattare con le pagine che sono alcuna indicazione di una codifica.Firefox è uno.È possibile scaricare il codice e vedere come si fa.Vedere un po ' di documentazione qui.Fondamentalmente, si tratta di un metodo euristico, ma uno che funziona davvero bene.

Dato una ragionevole quantità di testo, è anche possibile rilevare la lingua.

Ecco un altro Ho appena trovato con Google:

So che è molto tardi per questa domanda e questa soluzione non piacerà ad alcuni, a causa del suo inglese-centric pregiudizi e la mancanza di statistiche e di verifica empirica), ma ha funzionato molto bene per me, soprattutto per l'elaborazione caricati i dati CSV:

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

Vantaggi:

  • BOM rilevamento integrato
  • Default/fallback codifica personalizzabile
  • abbastanza affidabili (nella mia esperienza) per l'europa occidentale basato su file contenente alcuni esotici dati (ad esempio i nomi francesi) con una miscela di UTF-8 e Latin-1-file di stile, in pratica il grosso di NOI europei occidentali e ambienti.

Nota:Io sono una di quelle che ha scritto questa classe, così, ovviamente, prendere con un grano di sale!:)

Notepad++ questa funzionalità out-of-the-box.Supporta anche la modifica.

Cercando una soluzione diversa, ho trovato che

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

questa soluzione è un pò pesante.

Ho bisogno di un po di codifica di base di rilevamento, sulla base di 4 primo byte e, probabilmente, xml charset rilevamento - così ho preso alcuni esempi di codice sorgente da internet e aggiunta versione leggermente modificata di

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

scritto per 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
    }

È sufficiente leggere probabilmente per la prima volta 1024 byte dal file, ma io sono carico intero file.

Se qualcuno è alla ricerca di un 93.9% soluzione.Questo funziona per me:

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();
        }
    }
}

Ho fatto qualcosa di simile in Python.Fondamentalmente, avete bisogno di un sacco di dati di esempio da varie codifiche, che sono suddivisi da una scorrevole a due byte finestra e memorizzati in un dizionario (hash), codice dei byte di coppie di fornire i valori degli elenchi di codifiche.

Dato che il dizionario (hash), prendete il vostro testo di input e:

  • se si inizia con qualsiasi carattere BOM ('\xfe\xff' UTF-16, '\xff\xfe' UTF-16-LE, '\xef\xbb\xbf' UTF-8 ecc), io lo trattano come suggerito
  • se non è così, quindi prendere una abbastanza grande campione di testo, prendere tutti i byte coppie del campione e scegliere la codifica che è il minimo comune suggerito dal dizionario.

Se hai anche provato con codifica UTF testi non iniziare con qualsiasi DISTINTA base, il secondo step sarà coprire quelle che scivolato dal primo passo.

Finora, a me funziona (il campione di dati e la successiva immissione dei dati sono i sottotitoli in varie lingue), una riduzione dei tassi di errore.

La classe StreamReader costruttore di un 'rilevare la codifica' parametro.

Lo strumento "uchardet" fa bene questo personaggio distribuzione di frequenza di modelli per ogni set di caratteri.File di dimensioni maggiori e di più "tipico" file hanno più fiducia (ovviamente).

Su ubuntu, basta apt-get install uchardet.

Su altri sistemi, ottenere la fonte, l'uso e documentazione qui: https://github.com/BYVoid/uchardet

Se è possibile linkare una libreria in C, è possibile utilizzare libenca.Vedere http://cihar.com/software/enca/.Dalla pagina man:

Enca legge dato un file di testo, o di input standard quando nessuno è dato, e utilizza la conoscenza della loro lingua (che deve essere supportata da voi) e una miscela di analisi, analisi statistica, indovinare e magia nera per determinare la loro codifica.

E ' GPL v2.

Avuto lo stesso problema, ma non ha trovato una buona soluzione di sicurezza per rilevare automaticamente .Ora im utilizzando PsPad (www.pspad.com per quella ;) Funziona bene

Dal momento che si riduce praticamente a euristica, è possibile utilizzare il sistema di codifica che in precedenza i file ricevuti dalla stessa fonte, come primo suggerimento.

La maggior parte delle persone (o applicazioni) di fare cose più o meno nello stesso ordine ogni volta, spesso sulla stessa macchina, quindi è molto probabile che quando Bob crea un .file csv e lo invia a Maria sarà sempre tramite Windows-1252 o qualunque sia la sua macchina di default.

Dove possibile, un po ' di formazione per i clienti non fa mai male:- o)

Mi è stato effettivamente in cerca di un generico, non di programmazione che permettono di rilevare la codifica del file, ma non ho trovato ancora.Quello che ho trovato facendo il test con codifiche diverse, era che il mio testo è stato UTF-7.

Così, da dove ho stava facendo:StreamReader file = file.OpenText(fullfilename);

L'ho dovuto cambiare per:StreamReader file = new StreamReader(fullfilename, Sistema.Di testo.La codifica.UTF7);

OpenText assume è UTF-8.

è inoltre possibile creare StreamReader come questo new StreamReader(fullfilename, true), il secondo parametro nel senso che dovrebbe rilevare la codifica da byteordermark del file, ma che non ha funzionato nel mio caso.

Apri il file in AkelPad(o copia/incolla di un testo incomprensibile), andare in Modifica -> Selezione -> Recode...-> spunta "Autodetect".

Come addon per ITmeze post, ho usato questa funzione per convertire l'output di C# porta per Mozilla Universale Charset Rivelatore

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

MSDN

Grazie @Erik Aronesty per la menzione di uchardet.

Nel frattempo (lo stesso?) strumento esiste per linux: chardet.
O, su cygwin è possibile che si desidera utilizzare: chardetect.

Vedere: chardet uomo pagina: https://www.commandlinux.com/man-page/man1/chardetect.1.html

Questo euristicamente rilevare (credo) la codifica dei caratteri per ogni tipo di file e riporterà il nome e il livello di confidenza per ogni file rilevato la codifica dei caratteri.

10Y (!) era passato dal momento che questo è stato chiesto, e ancora non vedo alcuna menzione di MS bene, camere non-GPL soluzione: IMultiLanguage2 API.

La maggior parte delle librerie già detto sono basati su Mozilla UDE - e mi sembra ragionevole che i browser hanno già affrontato problemi simili.Non so che cosa è chrome soluzione, ma dal momento che IE 5.0 MS hanno rilasciato la loro, ed è:

  1. Libero di GPL-e-il-come problemi di licenza,
  2. Sostenuto e mantenuto, e probabilmente per sempre,
  3. Dà ricco di uscita - tutti validi candidati per la codifica/tabelle codici lungo con fiducia punteggi,
  4. Sorprendentemente facile da usare (si tratta di una singola chiamata di funzione).

Si tratta di un nativo COM chiamata, ma ecco qualche lavoro molto bello Carsten Zeumer, che gestisce l'interoperabilità pasticcio .l'uso della rete.Ce ne sono altri in giro, ma gran parte di questa libreria non ottiene l'attenzione che merita.

Io uso questo codice per rilevare Unicode e predefinita di windows tabella codici ansi durante la lettura di un file.Per altre codifiche un controllo del contenuto è necessario, manualmente o tramite la programmazione.Questo può essere utilizzato per salvare il testo con la stessa codifica quando è stato aperto.(Io uso 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()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top