Вопрос

Я читаю файлы в различных форматах и языках, и в настоящее время я использую небольшую библиотеку кодирования, чтобы попытаться определить правильную кодировку (http://www.codeproject.com/KB/recipes/DetectEncoding.aspx).

Это довольно хорошо, но все равно иногда промахивается.(Многоязычные файлы)

Большинство моих потенциальных пользователей очень слабо разбираются в кодировке (лучшее, на что я могу надеяться, это "это как-то связано с символами") и вряд ли смогут выбрать правильную кодировку в списке, поэтому я хотел бы позволить им перебирать разные кодировки, пока не будет найдена нужная, просто нажав на кнопку.

Проблемы с дисплеем?Нажмите здесь, чтобы попробовать другую кодировку!(Ну, в любом случае, такова концепция)

Каков был бы наилучший способ реализовать что-то подобное?


Редактировать:Похоже, я недостаточно ясно выразился.Под "циклическим перебором кодировок" я не имею в виду "как перебирать кодировки?".

Я имел в виду "как позволить пользователю последовательно пробовать разные кодировки без перезагрузки файла?"

Идея больше похожа на эту:Допустим, файл загружен с неправильной кодировкой.Отображаются какие-то странные символы.Пользователь нажимал бы кнопку "Следующая кодировка" или "предыдущая кодировка", и строка была бы преобразована в другую кодировку.Пользователю просто нужно продолжать нажимать до тех пор, пока не будет найдена нужная кодировка.(какая бы кодировка ни выглядела хорошо для пользователя, она будет работать нормально).Пока пользователь может нажать "далее", у него есть разумные шансы решить свою проблему.

То, что я нашел до сих пор, включает преобразование строки в байты с использованием текущей кодировки, затем преобразование байтов в следующую кодировку, преобразование этих байтов в символы, затем преобразование символа в строку...Выполнимо, но мне интересно, нет ли более простого способа сделать это.

Например, если бы существовал метод, который считывал бы строку и возвращал ее, используя другую кодировку, что-то вроде "render (строка, кодировка)".


Большое спасибо за ответы!

Это было полезно?

Решение

Считайте файл в виде байтов и затем используйте кодировку.Метод 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));

Таким образом, вам нужно загрузить файл только один раз.Вы можете использовать любую кодировку, основанную на исходных байтах файла.Пользователь может выбрать правильный вариант, а вы можете использовать результат кодирования.GetEncoding(...).getString(данные) для дальнейшей обработки.

Другие советы

(удален оригинальный ответ после обновления вопроса)

Например, если бы существовал метод который считывал бы строку и возвращал ее используя другую кодировку, что-то вроде "render(строка, кодировка)".

Я не думаю, что вы можете повторно использовать строковые данные.Дело в том, что:если кодировка была неправильной, эту строку можно считать поврежденной.Он очень легко может содержать тарабарщину среди вероятных символов.В частности, многие кодировки могут допускать наличие / отсутствие спецификации / преамбулы, но не могли бы вы перекодировать их заново?без этого?

Если вы готовы рискнуть этим (я бы не стал), вы могли бы просто перекодировать свою локальную строку с последней кодировкой:

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

На самом деле, я считаю, что лучшее, что вы можете сделать, это сохранить оригинал byte[] - продолжайте предлагать разные рендеринги (в разных кодировках), пока им что-то не понравится.Что - то вроде:

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

Не могли бы вы разрешить пользователю вводить некоторые слова (со "специальными" символами), которые должны встречаться в файле?

Вы можете самостоятельно выполнить поиск по всем кодировкам, чтобы узнать, присутствуют ли эти слова.

Остерегайтесь печально известных 'Ошибка в блокноте'.Однако он будет кусать тебя, что бы ты ни пытался...Вы можете найти некоторые хорошие дискуссии о кодировках и их проблемах в MSDN (и других местах).

Вы должны сохранить исходные данные в виде массива байтов или потока памяти, который затем вы можете преобразовать в новую кодировку, поскольку после того, как вы уже преобразовали свои данные в строку, вы не сможете надежно вернуться к исходному представлению.

Как насчет чего-то вроде этого:

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

Используйте LoadFile с первой попытки;затем используйте TryEncoding впоследствии.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top