Domanda

Sto leggendo file in vari formati e lingue e attualmente sto usando una piccola libreria di codifica per tentare di rilevare la codifica corretta ( http://www.codeproject.com/KB/recipes/DetectEncoding.aspx ).

È abbastanza buono, ma a volte manca ancora. (File multilingue)

La maggior parte dei miei potenziali utenti ha una comprensione molto ridotta della codifica (la cosa migliore che posso sperare è " ha qualcosa a che fare con i caratteri ") e molto probabilmente non sarà in grado di scegliere il codifica corretta in un elenco, quindi vorrei lasciarli scorrere tra diverse codifiche fino a trovare quella giusta semplicemente facendo clic su un pulsante.

Problemi di visualizzazione? Fai clic qui per provare una codifica diversa! (Beh, questo è comunque il concetto)

Quale sarebbe il modo migliore per implementare qualcosa del genere?


Modifica: sembra che non mi sia espresso abbastanza chiaramente. Per & Quot; scorrendo ciclicamente la codifica & Quot ;, non intendo & Quot; come eseguire il loop delle codifiche? & Quot;

Ciò che intendevo era " come consentire all'utente di provare diverse codifiche in sequenza senza ricaricare il file? "

L'idea è più simile a questa: supponiamo che il file sia caricato con una codifica errata. Vengono visualizzati alcuni strani personaggi. L'utente farebbe clic su un pulsante & Quot; Prossima codifica & Quot; o " codifica precedente " ;, e la stringa verrebbe convertita in una codifica diversa. L'utente deve solo continuare a fare clic finché non viene trovata la codifica corretta. (qualunque codifica sembri valida per l'utente andrà bene). Finché l'utente può fare clic su & Quot; successivo & Quot ;, ha una ragionevole possibilità di risolvere il suo problema.

Quello che ho trovato finora comporta la conversione della stringa in byte utilizzando la codifica corrente, quindi la conversione dei byte nella codifica successiva, la conversione di quei byte in caratteri, quindi la conversione del carattere in una stringa ... fattibile, ma mi chiedo se non esiste un modo più semplice per farlo.

Ad esempio, se esistesse un metodo per leggere una stringa e restituirla usando una codifica diversa, qualcosa come " render (stringa, codifica) " ;.


Grazie mille per le risposte!

È stato utile?

Soluzione

Leggi il file come byte e usa quindi il metodo Encoding.GetString.

        byte[] data = System.IO.File.ReadAllBytes(path);

        Console.WriteLine(Encoding.UTF8.GetString(data));
        Console.WriteLine(Encoding.UTF7.GetString(data));
        Console.WriteLine(Encoding.ASCII.GetString(data));

Quindi devi caricare il file solo una volta. È possibile utilizzare ogni codifica in base ai byte originali del file. L'utente può selezionare quello corretto e puoi usare il risultato di Encoding.GetEncoding (...). GetString (dati) per ulteriori elaborazioni.

Altri suggerimenti

(rimossa la risposta originale dopo l'aggiornamento della domanda)

  

Ad esempio, se esistesse un metodo   che legge una stringa e la restituisce   usando una codifica diversa, qualcosa   come " render (stringa, codifica) " ;.

Non credo che tu possa riutilizzare i dati della stringa. Il fatto è: se la codifica era errata, questa stringa può essere considerata corrotta. Può contenere facilmente parole incomprensibili tra i personaggi che sembrano probabili. In particolare, molte codifiche possono perdonare la presenza / assenza di una distinta base / preambolo, ma ricodificheresti con essa? senza di essa?

Se sei felice di rischiare (non lo sarei), potresti semplicemente ricodificare la tua stringa locale con l'ultima codifica:

// I DON'T RECOMMEND THIS!!!!
byte[] preamble = lastEncoding.GetPreamble(),
    content = lastEncoding.GetBytes(text);
byte[] raw = new byte[preamble.Length + content.Length];
Buffer.BlockCopy(preamble, 0, raw, 0, preamble.Length);
Buffer.BlockCopy(content, 0, raw, preamble.Length, content.Length);
text = nextEncoding.GetString(raw);

In realtà, credo che il meglio che puoi fare sia mantenere l'originale byte[] - continua a offrire rendering diversi (tramite codifiche diverse) fino a quando non ne hanno gradito uno. Qualcosa del tipo:

using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
class MyForm : Form {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new MyForm());
    }
    ComboBox encodings;
    TextBox view;
    Button load, next;
    byte[] data = null;

    void ShowData() {
        if (data != null && encodings.SelectedIndex >= 0) {
            try {
                Encoding enc = Encoding.GetEncoding(
                    (string)encodings.SelectedValue);
                view.Text = enc.GetString(data);
            } catch (Exception ex) {
                view.Text = ex.ToString();
            }
        }
    }
    public MyForm() {
        load = new Button();
        load.Text = "Open...";
        load.Dock = DockStyle.Bottom;
        Controls.Add(load);

        next = new Button();
        next.Text = "Next...";
        next.Dock = DockStyle.Bottom;
        Controls.Add(next);

        view = new TextBox();
        view.ReadOnly = true;
        view.Dock = DockStyle.Fill;
        view.Multiline = true;
        Controls.Add(view);

        encodings = new ComboBox();
        encodings.Dock = DockStyle.Bottom;
        encodings.DropDownStyle = ComboBoxStyle.DropDown;
        encodings.DataSource = Encoding.GetEncodings();
        encodings.DisplayMember = "DisplayName";
        encodings.ValueMember = "Name";
        Controls.Add(encodings);

        next.Click += delegate { encodings.SelectedIndex++; };

        encodings.SelectedValueChanged += delegate { ShowData(); };

        load.Click += delegate {
            using (OpenFileDialog dlg = new OpenFileDialog()) {
                if (dlg.ShowDialog(this)==DialogResult.OK) {
                    data = File.ReadAllBytes(dlg.FileName);
                    Text = dlg.FileName;
                    ShowData();
                }
            }
        };
    }
}

Potresti consentire all'utente di inserire alcune parole (con " caratteri speciali ") che dovrebbero apparire nel file?

Puoi cercare tu stesso tutte le codifiche per vedere se queste parole sono presenti.

Attenzione al famigerato ' Bug del blocco note '. Ti morderà qualunque cosa tu provi, però ... Puoi trovare alcuni buone discussioni sulle codifiche e le loro sfide su MSDN (e in altri luoghi).

Devi mantenere i dati originali come array di byte o MemoryStream, quindi puoi tradurli nella nuova codifica, una volta che hai già convertito i tuoi dati in una stringa non puoi tornare in modo affidabile alla rappresentazione originale.

Che ne dici di qualcosa del genere:

public string LoadFile(string path)
{
    stream = GetMemoryStream(path);     
    string output = TryEncoding(Encoding.UTF8);
}

public string TryEncoding(Encoding e)
{
    stream.Seek(0, SeekOrigin.Begin) 
    StreamReader reader = new StreamReader(stream, e);
    return reader.ReadToEnd();
}

private MemoryStream stream = null;

private MemorySteam GetMemoryStream(string path)
{
    byte[] buffer = System.IO.File.ReadAllBytes(path);
    return new MemoryStream(buffer);
}

Usa Carica file al primo tentativo; quindi utilizzare Prova codifica successivamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top