Конвертировать ANSI (Windows 1252) в UTF8 в C # - PullRequest
4 голосов
/ 08 декабря 2010

Я спрашивал об этом раньше в обходном порядке, прежде чем здесь, на Stack Overflow, и хочу сделать это правильно на этот раз. Как преобразовать ANSI (кодовая страница 1252) в UTF-8, сохранив при этом специальные символы? (Я знаю, что UTF-8 поддерживает больший набор символов, чем ANSI, но ничего, если я смогу сохранить все символы UTF-8, которые поддерживаются ANSI, и заменить остальные на ? или чем-то еще)

Почему я хочу конвертировать ANSI & rarr; UTF-8

Я в основном пишу программу, которая разбивает файлы vCard (VCF) на отдельные файлы, каждый из которых содержит один контакт. Я заметил, что телефоны Nokia и Sony Ericsson сохраняют резервный файл VCF в формате UTF-8 (без спецификации), но Android сохраняет его в формате ANSI (1252). И Бог знает, в каких форматах их сохраняют другие телефоны!

Так что мои вопросы

  1. Нет ли промышленного стандарта для кодировки символов в файлах vCard?
  2. Что проще для решения моей проблемы? Преобразование ANSI в UTF8 (и / или наоборот) или попытка определить кодировку входного файла и уведомление пользователя об этом?

ТЛ; др Необходимо знать, как преобразовать кодировку символов из (ANSI / UTF8) в (UTF8 / ANSI) при сохранении всех специальных символов.

Ответы [ 6 ]

13 голосов
/ 08 декабря 2010

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

Как только вы прочитаете файл, используя правильную кодировку, у вас будет содержимое в виде строки Unicode, оттуда вы сможете сохранитьон использует любую понравившуюся вам кодировку.

Если вам нужно определить кодировку, вы можете прочитать файл в байтах, а затем искать коды символов, специфичные для любой кодировки.Если файл не содержит специальных символов, любая кодировка будет работать, так как символы 32..127 одинаковы для обеих кодировок.

8 голосов
/ 08 декабря 2010

VCF кодируется в utf-8, как того требует спецификация в главе 3.4. Вы должны принять это всерьез, формат был бы совершенно бесполезным, если бы он не был отлит в камне. Если вы видите, что какое-то приложение Android манипулирует акцентированными символами, тогда исходите из предположения, что это ошибка в этом приложении. Или, более вероятно, что он получил плохую информацию откуда-то еще. Ваша попытка исправить кодировку может вызвать проблемы more , потому что ваша версия карты никогда не будет соответствовать оригиналу.

Вы конвертируете из 1252 в utf-8 с Encoding.GetEncoding (1252) .GetString (), передавая байт [] . Никогда не пытайтесь писать код, который читает строку и помещает ее в байт [], чтобы вы могли использовать метод преобразования, который только усугубляет проблемы кодирования много . Другими словами, вам нужно прочитать файл с помощью FileStream, а не StreamReader. Но опять же, избегайте решения проблем других людей.

7 голосов
/ 18 августа 2011

Это то, что я использую в C # (я использовал его для преобразования из Windows-1252 в UTF8)

    public static String readFileAsUtf8(string fileName)
    {
        Encoding encoding = Encoding.Default;
        String original = String.Empty;

        using (StreamReader sr = new StreamReader(fileName, Encoding.Default))
        {
            original = sr.ReadToEnd();
            encoding = sr.CurrentEncoding;
            sr.Close();
        }

        if (encoding == Encoding.UTF8)
            return original;

        byte[] encBytes = encoding.GetBytes(original);
        byte[] utf8Bytes = Encoding.Convert(encoding, Encoding.UTF8, encBytes);
        return Encoding.UTF8.GetString(utf8Bytes);
    }
5 голосов
/ 07 октября 2015

Я делаю это так:

    private static void ConvertAnsiToUTF8(string inputFilePath, string outputFilePath)
    {
        string fileContent = File.ReadAllText(inputFilePath, Encoding.Default);
        File.WriteAllText(outputFilePath, fileContent, Encoding.UTF8);
    }
1 голос
/ 22 февраля 2019

Я нашел этот вопрос, работая над обработкой большой коллекции древних текстовых файлов в хорошо отформатированных PDF-файлах.Ни один из файлов не имеет спецификации, а самые старые из них содержат кодовые точки кодовой страницы 1252, которые вызывают неправильное декодирование в UTF8.Это происходит только в некоторых случаях, UTF8 работает большую часть времени.Кроме того, последние текстовые данные содержат кодовые точки UTF8, поэтому это смешанный пакет.

Итак, я также поставил ", чтобы определить, какая кодировка входного файла имеет" и послечтение Как определить кодировку символов текстового файла? и Как определить кодировку текста? пришли к выводу, что в лучшем случае это будет трудно.

НО, я нашел Абсолютный минимум, который каждый разработчик программного обеспечения абсолютно, положительно должен знать о Unicode и наборах символов в комментариях, прочитал его и нашел этот драгоценный камень:

UTF-У 8 есть приятный побочный эффект: английский текст в UTF-8 выглядит точно так же, как и в ASCII, поэтому американцы даже не замечают ничего плохого.Только остальной мир должен прыгать через обручи.В частности, Hello, который был U + 0048 U + 0065 U + 006C U + 006C U + 006F, будет сохранен как 48 65 6C 6C 6F, что, вот!это то же самое, что и в ASCII, и в ANSI, и в каждом OEM-наборе символов на планете.

Вся статья короткая и заслуживает прочтения.

Итак,Я решил свою проблему с помощью следующего кода.Поскольку только небольшой объем моих текстовых данных содержит сложные кодовые точки символов, я не возражаю против снижения производительности при обработке исключений, тем более что это нужно было выполнить только один раз.Возможно, есть более умные способы избежать try/catch, но я не стал его разрабатывать.

    public static string ReadAllTextFromFile(string file)
    {
        const int WindowsCodepage1252 = 1252;

        string text;

        try
        {
            var utf8Encoding = Encoding.UTF8;
            utf8Encoding.DecoderFallback = DecoderFallback.ExceptionFallback;

            text = File.ReadAllText(file, utf8Encoding);
        }
        catch (DecoderFallbackException dfe)//then text is not entirely valid UTF8, contains Codepage 1252 characters that can't be correctly decoded to UTF8
        {
            var codepage1252Encoding = Encoding.GetEncoding(WindowsCodepage1252, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
            text = File.ReadAllText(file, codepage1252Encoding);
        }

        return text;
    }

Стоит также отметить, что класс StreamReader имеет конструкторы, которые принимают определенныйКодирование объекта, и, как я показал, вы можете настроить поведение EncoderFallback / DecoderFallback в соответствии с вашими потребностями.Так что если вам нужен StreamReader или StreamWriter для более тонкой работы, этот подход все еще можно использовать.

0 голосов
/ 06 января 2014
  1. Нет ли промышленного стандарта для кодировки символов в файлах vCard?
  2. Что проще для решения моей проблемы?Преобразование ANSI в UTF8 (и / или наоборот) или попытка определить, какая кодировка имеет входной файл, и уведомить об этом пользователя?

Как я решил это: у меня есть файл vCard (*.vcf) - 200 контактов в одном файле на русском языке ... Я открыл его с помощью программы vCardOrganizer 2.1, затем сделал Split, чтобы разделить его на 200 .... и что я вижу - контакты с грязными символами, единственное, что я могу прочитатьцифры :-) ...

Шаги: (когда вы делаете эти шаги, наберитесь терпения, иногда это требует времени) Откройте файл vCard (мой размер файла был 3mb) с помощью «блокнота», затем перейдите из Меню - Файл-Сохранить как ... в открывшемся окне выберите имя файла, не забудьте указать .vcf и кодировку - ANSI или UTF-8 ... и, наконец, нажмите "Сохранить". Я преобразовал имя файла .vcf (UTF-8) в имя файла.) - ничего не потеряно и отлично читаемый русский язык ... если у вас есть квест напишите: yoshidakatana@gmail.com

Удачи !!!

...