Pregunta

Estoy leyendo archivos en varios formatos e idiomas y actualmente estoy usando una pequeña biblioteca de codificación para intentar detectar la codificación adecuada ( http://www.codeproject.com/KB/recipes/DetectEncoding.aspx ).

Es bastante bueno, pero todavía se pierde ocasionalmente. (Archivos multilingües)

La mayoría de mis usuarios potenciales tienen muy poca comprensión de la codificación (lo mejor que puedo esperar es " tiene algo que ver con los caracteres ") y es muy poco probable que puedan elegir el codificación correcta en una lista, por lo que me gustaría dejar que recorran diferentes codificaciones hasta encontrar la correcta con solo hacer clic en un botón.

¿Problemas de visualización? Haga clic aquí para probar una codificación diferente. (Bueno, ese es el concepto de todos modos)

¿Cuál sería la mejor manera de implementar algo así?


Editar: Parece que no me expresé con suficiente claridad. Por & "; Recorrer la codificación &"; No me refiero a & "; ¿Cómo recorrer las codificaciones? &";

Lo que quise decir fue & "; ¿cómo permitir que el usuario pruebe diferentes codificaciones en secuencia sin volver a cargar el archivo? &";

La idea es más como esta: Digamos que el archivo está cargado con la codificación incorrecta. Se muestran algunos personajes extraños. El usuario haría clic en un botón & Quot; Siguiente codificación & Quot; o " codificación anterior " ;, y la cadena se convertiría en una codificación diferente. El usuario solo necesita seguir haciendo clic hasta encontrar la codificación correcta. (cualquier codificación que se vea bien para el usuario funcionará bien). Siempre que el usuario pueda hacer clic en & Quot; next & Quot ;, tiene una posibilidad razonable de resolver su problema.

Lo que he encontrado hasta ahora implica convertir la cadena a bytes usando la codificación actual, luego convertir los bytes a la siguiente codificación, convertir esos bytes en caracteres, luego convertir el carácter en una cadena ... factible, pero me pregunto si no hay una manera más fácil de hacer eso.

Por ejemplo, si hubiera un método que leería una cadena y la devolvería usando una codificación diferente, algo como " render (cadena, codificación) " ;.


¡Muchas gracias por las respuestas!

¿Fue útil?

Solución

Lea el archivo como bytes y luego use el Método 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));

Por lo tanto, debe cargar el archivo solo una vez. Puede usar cada codificación basada en los bytes originales del archivo. El usuario puede seleccionar el correcto y usted puede usar el resultado de Encoding.GetEncoding (...). GetString (datos) para su posterior procesamiento.

Otros consejos

(se eliminó la respuesta original después de la actualización de la pregunta)

  

Por ejemplo, si hubiera un método   eso leería una cadena y la devolvería   usando una codificación diferente, algo   como " render (cadena, codificación) " ;.

No creo que pueda reutilizar los datos de la cadena. El hecho es: si la codificación fue incorrecta, esta cadena puede considerarse corrupta. Muy fácilmente puede contener galimatías entre los personajes de aspecto probable. En particular, muchas codificaciones pueden perdonar la presencia / ausencia de una lista de materiales / preámbulo, pero ¿volvería a codificar con ella? sin ella?

Si está feliz de arriesgarse (no lo estaría), podría volver a codificar su cadena local con la última codificación:

// 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);

En realidad, creo que lo mejor que puede hacer es mantener el byte[] original: seguir ofreciendo diferentes representaciones (a través de diferentes codificaciones) hasta que les guste una. Algo así como:

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

¿Podría permitir que el usuario ingrese algunas palabras (con " caracteres " especiales) que se supone que deben aparecer en el archivo?

Puede buscar todas las codificaciones usted mismo para ver si estas palabras están presentes.

Cuidado con el infame ' Error del bloc de notas '. Sin embargo, te morderá lo que intentes ... Puedes encontrar algunos buenas discusiones sobre codificaciones y sus desafíos en MSDN (y otros lugares).

Debe mantener los datos originales como una matriz de bytes o MemoryStream que luego puede traducir a la nueva codificación, una vez que ya ha convertido sus datos en una cadena no puede volver a la representación original de manera confiable.

¿Qué tal algo como esto?

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

Use Load File en su primer intento; luego use Try Encoding posteriormente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top