Как я могу определить кодировку / кодовую страницу текстового файла

В нашем приложении мы получаем текстовые файлы ( .txt , .csv и т. Д.) Из разных источников. При чтении эти файлы иногда содержат мусор, потому что файлы, созданные в другой / неизвестной кодовой странице.

Есть ли способ (автоматически) определить кодовую страницу текстового файла?

Функция detectEncodingFromByteOrderMarks в конструкторе StreamReader работает для UTF8 и других отмеченных в Unicode файлов, но я ищу способ обнаружения кодовых страниц, таких как ibm850 , ibm850 .


Спасибо за ваши ответы, вот что я сделал.

Файлы, которые мы получаем, от конечных пользователей, они не имеют понятия о кодовых страницах. Приемники также являются конечными пользователями, и теперь это то, что они знают о кодовых страницах: Codepages существуют и раздражают.

Решение:

  • Откройте полученный файл в «Блокноте», посмотрите на искаженный fragment текста. Если кого-то зовут Франсуа или что-то, с вашим человеческим интеллектом, вы можете это догадаться.
  • Я создал небольшое приложение, которое пользователь может использовать для открытия файла, и введите текст, который пользователь знает, что он появится в файле, когда используется правильная кодовая страница.
  • Прокрутите все кодовые страницы и отобразите те, которые дают решение с предоставленным пользователем текстом.
  • Если по мере появления одной кодовой страницы попросите пользователя указать больше текста.

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

В любом случае, это то, что вам нужно прочитать: Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Unicode и наборах символов (никаких оправданий!) .

В частности, Джоэл говорит:

Самый важный факт о кодировании

Если вы полностью забудете все, что я только что объяснил, помните один чрезвычайно важный факт. Не имеет смысла иметь строку, не зная, какую кодировку она использует. Вы больше не можете засунуть голову в песок и притвориться, что «простой» текст – ASCII. Нет такой вещи, как обычный текст.

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

Если вы хотите обнаружить кодировки, отличные от UTF (т. Е. Без спецификации), вы в основном используете эвристику и статистический анализ текста. Возможно, вы захотите взглянуть на документ Mozilla на универсальное обнаружение кодировки ( та же ссылка, с лучшим форматированием через Wayback Machine ).

Вы пробовали порт C # для детектора универсальной кодировки Mozilla

Пример из 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."); } } } 

Вы не можете определить кодовую страницу

Это явно неверно. Каждый веб-браузер имеет какой-то универсальный детектор штриховок для обработки страниц, которые не имеют никаких указаний на кодировку. У Firefox есть одно. Вы можете загрузить код и посмотреть, как он это делает. См. Некоторые документы здесь . В принципе, это эвристический, но тот, который работает очень хорошо.

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

Вот еще один, который я нашел с помощью Google:

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

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

Преимущества:

  • Встроенное обнаружение спецификации
  • Настройка по умолчанию / резервное кодирование
  • довольно надежный (по моему опыту) для западно-европейских файлов, содержащих некоторые экзотические данные (например, французские имена) со смесью файлов UTF-8 и Latin-1 – в основном основная часть американской и западной европейской сред.

Примечание: Я тот, кто написал этот class, поэтому, очевидно, возьмите его с солью! 🙂

Notepad ++ имеет эту функцию из коробки. Он также поддерживает его изменение.

В поисках другого решения я обнаружил, что

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

это решение довольно тяжелое.

Мне понадобилось некоторое базовое кодирование, основанное на 4 первых байтах и, возможно, обнаружении charset xml, поэтому я взял некоторый образец исходного кода из Интернета и добавил немного модифицированную версию

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

написанный для 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 } 

Достаточно прочитать, вероятно, первые 1024 байта из файла, но я загружаю весь файл.

Если кто-то ищет решение на 93,9%. Это работает для меня:

 public static class StreamExtension { ///  /// Convert the content to a string. ///  /// The stream. ///  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(); } } } 

Я сделал что-то подобное в Python. В принципе, вам нужно много выборочных данных из разных кодировок, которые разбиваются на скользящее двухбайтовое окно и хранятся в словаре (hash), на основе байтовых пар, предоставляющих значения списков кодировок.

Учитывая этот словарь (hash), вы берете текст ввода и:

  • если он начинается с любого символа спецификации (‘\ xfe \ xff’ для UTF-16-BE, ‘\ xff \ xfe’ для UTF-16-LE, ‘\ xef \ xbb \ xbf’ для UTF-8 и т. д.), I относиться к нему как к предложению
  • если нет, то возьмите достаточно большой образец текста, возьмите все байтовые пары образца и выберите кодировку, которая является наименее распространенной из словаря.

Если вы также выбрали UTF-кодированные тексты, которые не запускаются с какой-либо спецификацией, второй шаг будет охватывать те, которые проскальзывали с первого шага.

Пока это работает для меня (образцы данных и последующие входные данные являются субтитрами на разных языках) с уменьшением частоты ошибок.

Конструктор classа StreamReader принимает параметр «обнаружить кодирование».

Инструмент «uchardet» делает это хорошо, используя модели распределения частоты символов для каждой кодировки. Большие файлы и более «типичные» файлы имеют большую уверенность (очевидно).

На ubuntu вы просто apt-get install uchardet .

В других системах получите источник, использование и документы здесь: https://github.com/BYVoid/uchardet

Если вы можете ссылаться на библиотеку C, вы можете использовать libenca . См. http://cihar.com/software/enca/ . На странице руководства:

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

Это GPL v2.

Получил ту же проблему, но не нашел хорошего решения, но обнаружил его автоматически. Теперь я использую PsPad (www.pspad.com) для этого;) Хорошо работает

Поскольку это в основном сводится к эвристике, это может помочь использовать кодировку ранее полученных файлов из того же источника, что и первый намек.

Большинство людей (или приложений) делают вещи практически в одном и том же порядке каждый раз, часто на одной машине, поэтому вполне вероятно, что, когда Боб создает CSV-файл и отправляет его в Mary, он всегда будет использовать Windows-1252 или независимо от того, на что его машина по умолчанию.

По возможности немного тренировок клиентов никогда не повредит 🙂

Я действительно искал общий, а не программный способ обнаружения кодировки файлов, но пока этого не нашел. То, что я обнаружил при тестировании с разными кодировками, заключалось в том, что мой текст был UTF-7.

Итак, где я впервые делал: StreamReader file = File.OpenText (fullfilename);

Мне пришлось изменить его на: StreamReader file = new StreamReader (fullfilename, System.Text.Encoding.UTF7);

OpenText предполагает, что это UTF-8.

вы также можете создать StreamReader, как этот новый StreamReader (fullfilename, true), второй параметр означает, что он должен попытаться обнаружить кодировку из byteordermark файла, но это не сработало в моем случае.

Откройте файл в AkelPad (или просто скопируйте / вставьте искаженный текст), перейдите в Edit -> Selection -> Recode … -> отметьте «Autodetect».

Как аддон к сообщению ITmeze, я использовал эту функцию для преобразования вывода порта C # для универсального детектора Mozilla Universal Charset Detector

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

MSDN

Спасибо @ Erik Aronesty за упоминание uchardet .

Тем временем (такой же?) Инструмент существует для linux: chardet .
Или, на cygwin, вы можете использовать: chardetect .

См. Страницу man : chardet man: https://www.commandlinux.com/man-page/man1/chardetect.1.html

Это будет эвристически определять (догадываться) кодировку символов для каждого заданного файла и сообщать имя и уровень достоверности для кодировки символов каждого файла.

10Y (!) Прошло с тех пор, как это было задано, и все же я не вижу упоминания о хорошем, отличном от GPL решении MS : IMultiLanguage2 API.

Большинство упомянутых библиотек основаны на UDE Mozilla – и кажется разумным, что браузеры уже справились с подобными проблемами. Я не знаю, что такое хром-решение, но поскольку IE 5.0 MS выпустили их, и это:

  1. Без GPL-и-подобных проблем лицензирования,
  2. Поддерживаемые и поддерживаемые, вероятно, навсегда,
  3. Дает богатый результат – все действующие кандидаты на кодирование / кодовые страницы вместе с оценками доверия,
  4. Удивительно проста в использовании (это вызов одной функции).

Это родной COM-вызов, но здесь есть очень хорошая работа Карстена Зеймера, которая обрабатывает беспорядок обмена для использования .net. Есть и другие, но в целом эта библиотека не получает внимания, которого она заслуживает.

Я использую этот код для обнаружения кодировки Unicode и windows по умолчанию ansi при чтении файла. Для других кодировок необходима проверка содержимого, вручную или путем программирования. Это может использоваться для сохранения текста с той же кодировкой, что и при его открытии. (Я использую 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() 
  • Обосновать последнюю строку div?
  • Как читать и анализировать CSV-файлы на C ++?
  • Хороший цвет текста переднего плана для заданного цвета фона
  • Подпиксельный сглаженный текст в элементе canvasа HTML5
  • Форматирование текста в ярлыке WinForm
  • Извлечение текста OpenCV
  • Усечение длинных строк с помощью CSS: возможно?
  • Вертикальная (повернутая) метка в Android
  • Как печатать цвет в консоли с помощью System.out.println?
  • Можно ли изменить цвет текста в строке на несколько цветов в Java?
  • Как эффективно анализировать CSV-файл в Perl?
  • Давайте будем гением компьютера.