Как узнать кодировку текстового файла java

Обновлено: 04.07.2024

Изучите кодировку символов в Java и узнайте о распространенных подводных камнях.

1. Обзор

В этом уроке мы обсудим основы кодирования символов и то, как мы справляемся с этим в Java.

2. Важность кодирования символов

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

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

Чтобы лучше понять это, давайте определим метод декодирования текста на Java:

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

Ну, не совсем то, что мы ожидали.

3. Основы

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

3.1. Кодирование

Компьютеры могут понимать только двоичные представления, такие как 1 и 0 . Обработка всего остального требует некоторого сопоставления текста реального мира с его двоичным представлением. Это отображение-то, что мы знаем как кодировка символов или просто как кодировка .

3.2. Кодировки

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

3.3. Кодовый пункт

Мы можем представить само целое число в простых десятичных или альтернативных основаниях, таких как шестнадцатеричное или восьмеричное. Мы используем альтернативные базы для удобства ссылки на большие числа.

4. Понимание Схем Кодирования

Кодировка символов может принимать различные формы в зависимости от количества символов, которые она кодирует.

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

Давайте рассмотрим некоторые из популярных схем кодирования на практике сегодня.

4.1. Однобайтовое кодирование

Одна из самых ранних схем кодирования, называемая ASCII (Американский стандартный код для обмена информацией), использует однобайтовую схему кодирования. По сути, это означает, что каждый символ в ASCII представлен семибитными двоичными числами. Это все еще оставляет один бит свободным в каждом байте!

Давайте определим простой метод в Java для отображения двоичного представления символа в определенной схеме кодирования:

И если мы используем наш метод утилиты, мы можем увидеть его двоичное представление:

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

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

Было предложено и принято несколько вариантов схемы кодирования ASCII.

Многие расширения ASCII имели разные уровни успеха, но, очевидно, это

4.2. Многобайтовое кодирование

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

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

BIG 5 и SHIFT-JIS являются примерами многобайтовых схем кодирования символов, которые начали использовать как один, так и два байта для представления более широких наборов символов . Большинство из них были созданы для того, чтобы представлять китайские и аналогичные сценарии, которые имеют значительно большее количество символов.

полный список кодировок символов, наряду с их псевдонимами, ведется Международным органом по номерам.

5. Юникод

Нетрудно понять, что, хотя кодирование важно, декодирование в равной степени жизненно важно для понимания представлений. Это возможно на практике только в том случае, если широко используется согласованная или совместимая схема кодирования.

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

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

Ну, для этого должно потребоваться несколько байтов для хранения каждого символа? Честно говоря, да, но у Unicode есть гениальное решение.

Мы используем шестнадцатеричную систему в качестве основы для кодовых точек в Юникоде, поскольку существует 1 114 112 точек, что является довольно большим числом для удобной передачи в десятичном формате!

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

5.1. UTF-32

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

5.2. UTF-8

Вывод в точности аналогичен ASCII, использующему только один байт. На самом деле UTF-8 полностью обратно совместим с ASCII.

UTF-8, благодаря своей экономичности пространства, является наиболее распространенной кодировкой, используемой в Интернете.

6. Поддержка кодирования в Java

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

Это включает в себя US-ASCII, ISO-8859-1, UTF-8 и UTF-16, чтобы назвать некоторые из них. Конкретная реализация Java может дополнительно поддерживать дополнительные кодировки .

Есть некоторые тонкости в том, как Java подбирает кодировку для работы. Давайте рассмотрим их более подробно.

6.1. Кодировка по умолчанию

Платформа Java сильно зависит от свойства, называемого кодировкой по умолчанию . Виртуальная машина Java (JVM) определяет кодировку по умолчанию во время запуска .

Это зависит от локали и кодировки базовой операционной системы, на которой работает JVM. Например, в macOS кодировка по умолчанию-UTF-8.

Давайте посмотрим, как мы можем определить кодировку по умолчанию:

Если мы запустим этот фрагмент кода на компьютере с Windows, то получим результат:

6.2. Кто использует Кодировку по умолчанию?

Многие API Java используют кодировку по умолчанию, определенную JVM. Чтобы назвать несколько:

  • InputStreamReader и Средство чтения файлов
  • OutputStreamWriter и Файловая машина
  • Форматер и Сканер
  • URLEncoder и URLDecoder

Итак, это означает, что если бы мы запустили наш пример без указания кодировки:

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

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

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

6.3. Проблемы С Набором Символов По Умолчанию

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

Например, если мы запустим

в macOS он будет использовать UTF-8.

Если мы попробуем тот же фрагмент кода в Windows, он будет использовать Windows-1252 для декодирования того же текста.

Или представьте, что вы пишете файл в mac OS, а затем читаете тот же файл в Windows.

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

6.4. Можем ли мы переопределить кодировку по умолчанию?

Определение кодировки по умолчанию в Java приводит к двум системным свойствам:

  • file.encoding : Значение этого системного свойства является именем набора символов по умолчанию
  • sun.jnu.encoding : Значением этого системного свойства является имя набора символов, используемого при кодировании/декодировании путей к файлам

Теперь интуитивно понятно переопределять эти системные свойства с помощью аргументов командной строки:

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

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

6.5. Почему Java Не Решает Эту Проблему?

Этот ДЖИП находится в состоянии проекта на данный момент и когда он (надеюсь!) пройдя через него, мы решим большинство вопросов, которые мы обсуждали ранее.

Обратите внимание, что более новые API, такие как в файле java.nio.file.Файлы не используют кодировку по умолчанию. Методы в этих API-интерфейсах читают или записывают символьные потоки с кодировкой UTF-8, а не с кодировкой по умолчанию.

6.6. Решение Этой Проблемы в Наших Программах

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

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

Бинго! Мы можем увидеть результат, который мы надеялись увидеть.

Здесь мы установили кодировку, которая, по нашему мнению, лучше всего соответствует нашим потребностям в конструкторе InputStreamReader . Обычно это самый безопасный метод работы с символами и преобразованиями байтов в Java.

Аналогично, OutputStreamWriter и многие другие API поддерживают настройку схемы кодирования через свой конструктор.

6.7. Исключение MalformedInputException

Когда мы декодируем последовательность байтов, существуют случаи , когда она не является законной для данной кодировки , или же это не является законным шестнадцатибитным Юникодом. Другими словами, данная последовательность байтов не имеет отображения в указанной кодировке .

Существует три предопределенные стратегии (или CodingErrorAction ), когда входная последовательность имеет искаженные входные данные:

  • ИГНОРИРОВАТЬ будет игнорировать искаженные символы и возобновит операцию кодирования
  • REPLACE заменит искаженные символы в выходном буфере и возобновит операцию кодирования
  • ОТЧЕТ вызовет исключение MalformedInputException

По умолчанию malformedInputAction для кодера CharsetDecoder является REPORT, и по умолчанию malformedInputAction декодера по умолчанию в InputStreamReader is REPLACE.

Давайте определим функцию декодирования , которая получает заданную кодировку , тип CodingErrorAction и строку, подлежащую декодированию:

Для второго теста мы используем CodingErrorAction.ЗАМЕНИТЕ , который помещает � вместо запрещенных символов:

Для третьего теста мы используем CodingErrorAction.ОТЧЕТ который приводит к выбрасыванию MalformedInputException:

7. Другие Места, Где Кодирование Важно

Нам не просто нужно учитывать кодировку символов при программировании. Тексты могут окончательно испортиться во многих других местах.

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

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

7.1. Текстовые Редакторы

В большинстве случаев текстовый редактор-это место, откуда исходят тексты. Существует множество текстовых редакторов в популярном выборе, включая vi, Блокнот и MS Word. Большинство из этих текстовых редакторов позволяют нам выбрать схему кодирования. Следовательно, мы всегда должны быть уверены, что они подходят для текста, с которым мы работаем.

7.2. Файловая система

После того, как мы создадим тексты в редакторе, нам нужно сохранить их в какой-то файловой системе. Файловая система зависит от операционной системы, на которой она работает. Большинство операционных систем имеют встроенную поддержку нескольких схем кодирования. Однако все еще могут быть случаи, когда преобразование кодировки приводит к потере данных.

7.3. Сеть

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

7.4. Базы данных

Большинство популярных баз данных, таких как Oracle и MySQL, поддерживают выбор схемы кодирования символов при установке или создании баз данных. Мы должны выбрать это в соответствии с текстами, которые мы ожидаем сохранить в базе данных. Это одно из наиболее частых мест, где повреждение текстовых данных происходит из-за преобразования кодировки.

7.5. Браузеры

Наконец, в большинстве веб-приложений мы создаем тексты и пропускаем их через различные слои с намерением просмотреть их в пользовательском интерфейсе, например в браузере. Здесь также важно, чтобы мы выбрали правильную кодировку символов, которая может правильно отображать символы. Большинство популярных браузеров, таких как Chrome, Edge, позволяют выбирать кодировку символов в своих настройках.

8. Заключение

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

Далее мы обсудили основные принципы, включая кодировку и кодировки. Более того, мы прошли через различные схемы кодирования и их использование.

Мы также подобрали пример неправильного использования кодировки символов в Java и увидели, как это сделать правильно. Наконец, мы обсудили некоторые другие распространенные сценарии ошибок, связанные с кодировкой символов.

Как получить кодировку символов текстового файла в Java [версия UTF-8, улучшенная версия]

1. Распознать кодировку символов:

1. Кодировка String в Java по умолчанию - UTF-8, которую можно получить с помощью следующего оператора: Charset.defaultCharset();

2. По умолчанию в Windows используется кодировка текстовых файлов ANSI, для китайских операционных систем - GBK. Например, если мы используем программу «Блокнот» для создания нового текстового документа, кодировка символов по умолчанию - ANSI.

3. Для текстовых текстовых документов предусмотрены четыре варианта кодирования: ANSI, Unicode (включая Unicode Big Endian и Unicode Little Endian), UTF-8, UTF-16.

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

  • ANSI: нет определения формата, GBK или GB2312 для китайских операционных систем
  • UTF-8: первые три байта: 0xE59B9E (UTF-8), 0xEFBBBF (UTF-8 с спецификацией)
  • UTF-16: первые два байта: 0xFEFF
  • Unicode: первые два байта: 0xFFFE

Например, если документ Unicode начинается с 0xFFFE, используйте программу, чтобы вынуть первые несколько байтов и оценить.

5. Соответствие между кодировкой Java и кодировкой текста:

UTF-8 содержит две спецификации:

Нужно судить о первых трех байтах:

Первые три байта: 0xE59B9E

Первые три байта: 0xEFBBBF

Юникод содержит две спецификации:

1、UCS2 Little Endian

2、UCS2 Big Endian

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

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

80.2k 7 7 золотых знаков 66 66 серебряных знаков 146 146 бронзовых знаков


85 1 1 золотой знак 2 2 серебряных знака 3 3 бронзовых знака Берем ваш вопрос, переводим на английский, вбиваем в гугл, открываем первую ссылку, копируем код, вставляем в свой проект. @metalurgus ну если бы я мог так сделать разве я бы спрашивал? есть конкретные примеры? за ссылку буду признателен. Что из вышеизложенного алгоритма вызывает у вас проблемы? @metalurgus уровень английского не позволит правильно поставить вопрос а тем более разобраться в найденном материале

Вообще это непростая задача и я думаю не всегда возможно это сделать. Обычно кодировку определяют заранее. Но действительно (как и сказал @metalurgus) довольно много информации в сети. Хотя, нужно понимать, что для решения такой задачи понадобится использовать какую-нибудь стороннюю библиотеку думаю вот это рассуждение подходит: определение кодировки

1,935 10 10 серебряных знаков 11 11 бронзовых знаков это все очень геморно выглядит, может я не стой стороны зашол. ситуация такая, программа открывает и обрабатывает текстовый файл, но файл может попасть в любой кодировку, нужно или проверять кодировку чтобы не было крякозябр или как то запретить обработку если файл не подходит под конкретную кодировку. @TСPakko и это просто так не запретишь (на файле не написано в какой кодировке там символы), только если читать и выкидывать ошибку разбора фала, если у него есть какой-то определённый формат (xml, css и т.д.).

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

1) Получаем список поддерживаемых данной платформой кодировок Charset.availableCharset()

2) Берем первую по списку charset и читаем строчку из файла:

3) Берем Yandex Словарь и оформляем JSon запрос lookup, запоминаем статистику переводов

4) После прогона всех доступных кодировок выбираем ту, которая получила наилучшую статистику - это и будет наша искомая кодировка.

каков наилучший способ программно определить правильную кодировку кодировки inputstream/файла ?

Я попытался использовать следующее:

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

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

на getEncoding () метод вернет кодировку, которая была настроена (прочитайте JavaDoc) для потока. Он не угадает кодировку для вас.

некоторые потоки сообщают вам, какая кодировка использовалась для их создания: XML, HTML. Но не произвольный поток байтов.

в любом случае, вы можете попытаться угадать кодировку самостоятельно, если вам нужно. Каждый язык имеет общую частоту для каждого символа. В английском языке char e появляется очень часто, но ê будет появляться очень редко. В потоке ISO-8859-1 обычно нет символов 0x00. Но в потоке UTF-16 Их много.

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

вот мои любимые:

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

Я не тестировал его широко, но, похоже, он работает.

Не забудьте поставить все попытки поймать нужно это.

Я надеюсь, что это работает для вас.

какую библиотеку использовать?

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

Я не включаю Apache Any23 потому что он использует ICU4j 3.4 под капотом.

Как сказать, какой из них обнаружил право charset (или так близко, как возможно)?

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

Как забить возвращенный ответ?

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

есть ли пример кода?

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

улучшения: The guessEncoding метод полностью считывает inputstream. Для больших inputstreams это может быть проблемой. Все эти библиотеки будут читать весь inputstream. Это потребует больших затрат времени на обнаружение кодировки.

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

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

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

Я написал инструмент meta java для обнаружения кодировки кодировок HTML веб-страниц, используя IBM ICU4j и Mozilla JCharDet в качестве встроенные компоненты. здесь вы можете найти мой инструмент, пожалуйста, прочитайте раздел README, прежде чем что-либо еще. Также, вы можете найти некоторые основные понятия этой проблемы в моем статьи и в его ссылках.

ниже я предоставил некоторые полезные комментарии, которые я испытал в своей работе:

  • обнаружение кодировки не является надежным процессом, потому что он по существу основан на статистических данных, и то, что на самом деле происходит, гадание не определения
  • icu4j является основным инструментом в этом контексте IBM, imho
  • оба TikaEncodingDetector и Lucene-ICU4j используют icu4j, и их точность не имела значимого отличия от того, что icu4j в моих тестах (не более %1, Как я помню)
  • icu4j гораздо более общий, чем jchardet, icu4j просто немного смещен к кодировкам семейства IBM, в то время как jchardet сильно смещен к utf-8
  • из-за широкое использование UTF-8 в HTML-мире; jchardet-лучший выбор, чем icu4j в целом, но не лучший выбор!
  • icu4j отлично подходит для восточноазиатских кодировок, таких как EUC-KR, EUC-JP, SHIFT_JIS, BIG5 и семейные кодировки GB
  • как icu4j, так и jchardet-Это фиаско в работе с HTML-страницами с кодировками Windows-1251 и Windows-1256. Windows-1251 aka cp1251 широко используется для кириллических языков, таких как русский и Windows-1256 aka cp1256 is широко используется для арабского
  • почти все инструменты обнаружения кодирования используют статистические методы, поэтому точность вывода сильно зависит от размера и содержимого ввода
  • некоторые кодировки по существу одинаковы только с частичными различиями, поэтому в некоторых случаях угаданная или обнаруженная кодировка может быть ложной, но в то же время истинной! Что касается Windows-1252 и ISO-8859-1. (см. последний абзац в разделе 5.2 бумага)

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

UTF-8 и UTF-16 файлы включают в себя Метка Порядка Байтов (BOM) в самом начале файла. BOM-это пространство с нулевой шириной.

к сожалению, по историческим причинам, Java не обнаруживает это автоматически. Такие программы, как Notepad, проверят спецификацию и используйте соответствующую кодировку. Используя unix или Cygwin, вы можете проверить спецификацию с помощью команды file. Например:

для Java я предлагаю вам проверить этот код, который обнаружит общие форматы файлов и выберет правильную кодировку: Как прочитать файл и автоматически указать правильную кодировку

Каков наилучший способ программного определения правильной кодировки кодировки входного потока / файла?

Я пробовал использовать следующее:

Но для файла, который, как я знаю, закодирован с помощью ISO8859_1, приведенный выше код дает ASCII, что неверно и не позволяет мне правильно отобразить содержимое файла обратно на консоль.

Эдуард прав: «Вы не можете определить кодировку произвольного байтового потока». Все другие предложения дают вам способы (и библиотеки) для наилучшего предположения. Но в конце концов это все еще догадки. Reader.getEncoding возвращает кодировку, для использования которой был настроен читатель, которая в вашем случае является кодировкой по умолчанию. Этот juniversalchardet не работает. Он предоставляет UTF-8 большую часть времени, даже если файл на 100% закодирован в Windows-1212.

Вы не можете определить кодировку произвольного байтового потока. Такова природа кодировок. Кодирование означает отображение между байтовым значением и его представлением. Так что каждая кодировка «могла быть» правильной.

Метод getEncoding () вернет кодировку, которая была настроена (прочтите JavaDoc ) для потока. Он не угадает за вас кодировку.

Некоторые потоки сообщают вам, какая кодировка использовалась для их создания: XML, HTML. Но не произвольный поток байтов.

В любом случае, вы можете попытаться угадать кодировку самостоятельно, если вам нужно. Каждый язык имеет общую частоту для каждого символа. В английском языке символ e встречается очень часто, а ê - очень редко. В потоке ISO-8859-1 обычно нет символов 0x00. Но в потоке UTF-16 их много.

Или: вы можете спросить пользователя. Я уже видел приложения, которые представляют вам фрагмент файла в разных кодировках и просят выбрать «правильную».

Итак, как мой редактор, блокнот ++, знает, как открыть файл и показать мне правильные символы? @Hamidam удачно показывает вам правильных персонажей. Когда он угадывает ошибочно (а это часто бывает), есть опция (Меню >> Кодировка), которая позволяет вам изменить кодировку. @Eduard: «Значит, каждая кодировка может быть правильной». не совсем так. Многие кодировки текста имеют несколько недействительных шаблонов, которые являются признаком того, что текст, вероятно, не в этой кодировке. Фактически, учитывая первые два байта файла, только 38% комбинаций являются допустимыми UTF8. Вероятность того, что первые 5 кодовых точек окажутся действительными UTF8 случайно, составляет менее 0,77%. Точно так же UTF16BE и LE обычно легко идентифицируются по большому количеству нулевых байтов и их местонахождению. Было бы неплохо получить хотя бы такой же точный метод, как Notepad ++ или просто Notepad. Никто не может сказать нам, что это такое? Я попытался, но это очень не удалось: я сделал 2 текстовых файла в eclipse, оба содержащие "öäüß". Один установлен на кодировку iso, а другой - на utf8 - оба распознаются как utf8! Итак, я попробовал файл, сохраненный где-то на моем жестком диске (Windows) - он был обнаружен правильно ("windows-1252"). Затем я создал два новых файла на жестком диске, один из которых отредактировал редактором, а другой - с помощью блокнота ++. в обоих случаях был обнаружен "Big5" (китайский)! РЕДАКТИРОВАТЬ: Хорошо, я должен проверить cm.getConfidence () - с моим коротким "äöüß" уверенность равна 10. Итак, я должен решить, какая уверенность достаточно хороша - но это абсолютно нормально для этого усилия (определение кодировки)

Вот мои любимые:

Замечание : TikaEncodingDetector 1.1 на самом деле представляет собой тонкую оболочку для CharsetDectector класса ICU4J 3.4 . К сожалению, обе библиотеки не работают. В одном случае он идентифицирует файл UTF-8 с немецким Umlaute как ISO-8859-1 и US-ASCII. @BennyNeugebauer - это файл в формате UTF-8 без спецификации. Я проверил это с помощью Notepad ++, также изменив кодировку и заявив, что "Umlaute" все еще видны.

Вы, безусловно, можете проверить файл для конкретной кодировки, декодируя его с помощью a CharsetDecoder и отслеживая ошибки "неправильного ввода" или "несопоставимого символа". Конечно, это только говорит вам, если кодировка неверна; он не говорит вам, правильно ли это. Для этого вам нужна основа сравнения для оценки декодированных результатов, например, знаете ли вы заранее, ограничены ли символы некоторым подмножеством или придерживается ли текст какого-то строгого формата? Суть в том, что определение кодировки - это догадки без каких-либо гарантий.

Какую библиотеку использовать?

На момент написания этой статьи появилось три библиотеки:

Я не включаю Apache Any23, потому что он использует ICU4j 3.4 под капотом.

Как определить, какая из них обнаружила правильную кодировку (или как можно более близкую)?

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

Как оценить полученный ответ?

Каждому ответу можно присвоить один балл. Чем больше очков в ответе, тем больше уверенности в обнаруженной кодировке. Это простой метод подсчета очков. Вы можете уточнить другие.

Есть ли образец кода?

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

Улучшения: guessEncoding метод считывает InputStream полностью. Для больших входных потоков это может быть проблемой. Все эти библиотеки будут читать весь поток ввода. Это потребовало бы больших затрат времени на определение кодировки.

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

только на кончике, но на этом сайте нет «выше» - подумайте о том, чтобы указать библиотеки, о которых вы говорите.

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

Я написал мета-инструмент Java для определения кодировки кодировки веб-страниц HTML, используя IBM ICU4j и Mozilla JCharDet в качестве встроенных компонентов. Здесь вы можете найти мой инструмент, прежде всего прочтите раздел README. Кроме того, вы можете найти некоторые основные концепции этой проблемы в моей статье и в ссылках на нее.

Ниже я предоставил несколько полезных комментариев, которые я испытал в своей работе:

Читайте также: