Кодирование текстового файла Java

У меня есть текстовый файл, и он может быть ANSI (с кодировкой ISO-8859-2), UTF-8, UCS-2 Big или Little Endian.

Есть ли способ обнаружить кодировку файла для его правильного чтения?

Или можно ли читать файл без указания кодировки? (и он читает файл как есть)

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

Ответ 1

UTF-8 и UCS-2/UTF-16 можно легко распознать с помощью байтового порядка в начале файла. Если это существует, то это довольно хорошая ставка, что файл находится в этой кодировке - но это не мертвая уверенность. Вы также можете обнаружить, что файл находится в одном из этих кодировок, но не имеет знака порядка байтов.

Я не очень разбираюсь в ISO-8859-2, но я не удивлюсь, если почти каждый файл является допустимым текстовым файлом в этой кодировке. Лучшее, что вы сможете сделать, это проверить его эвристически. Действительно, страница Wikipedia, говорящая об этом, предполагает, что только байт 0x7f недействителен.

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

Ответ 2

Да, существует ряд методов для обнаружения кодирования символов, особенно в Java. Взгляните на jchardet, который основан на алгоритме Mozilla. Там также cpdetector и проект IBM под названием ICU4j, Я бы посмотрел на последнего, поскольку он кажется более надежным, чем два других. Они работают на основе статистического анализа двоичного файла, ICU4j также обеспечит уровень достоверности кодировки символов, который он обнаруживает, чтобы вы могли использовать это в приведенном выше случае. Он работает очень хорошо.

Ответ 3

Вы можете использовать ICU4J (http://icu-project.org/apiref/icu4j/)

Вот мой код:

            String charset = "ISO-8859-1"; //Default chartset, put whatever you want

            byte[] fileContent = null;
            FileInputStream fin = null;

            //create FileInputStream object
            fin = new FileInputStream(file.getPath());

            /*
             * Create byte array large enough to hold the content of the file.
             * Use File.length to determine size of the file in bytes.
             */
            fileContent = new byte[(int) file.length()];

            /*
             * To read content of the file in byte array, use
             * int read(byte[] byteArray) method of java FileInputStream class.
             *
             */
            fin.read(fileContent);

            byte[] data =  fileContent;

            CharsetDetector detector = new CharsetDetector();
            detector.setText(data);

            CharsetMatch cm = detector.detect();

            if (cm != null) {
                int confidence = cm.getConfidence();
                System.out.println("Encoding: " + cm.getName() + " - Confidence: " + confidence + "%");
                //Here you have the encode name and the confidence
                //In my case if the confidence is > 50 I return the encode, else I return the default value
                if (confidence > 50) {
                    charset = cm.getName();
                }
            }

Не забудьте поставить все, чтобы попытаться поймать его.

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

Ответ 4

Если ваш текстовый файл является правильно созданным текстовым файлом в Юникоде, тогда метка байтового заказа (BOM) должна сообщить вам всю необходимую вам информацию. См. здесь для более подробной информации о спецификации

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