Проблема с кодировкой Java FileReader

Я попытался использовать java.io.FileReader для чтения некоторых текстовых файлов и преобразования их в строку, но я обнаружил, что результат неверен и не читается вообще.

Здесь моя среда:

  • Windows 2003, кодировка ОС: CP1252

  • Java 5.0

Мои файлы кодируются в кодировке UTF-8 или CP1252, а некоторые из них (кодированные файлы UTF-8) могут содержать китайские (нелатинские) символы.

Я использую следующий код для выполнения своей работы:

   private static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        FileReader reader = new FileReader(filePath);
        //System.out.println(reader.getEncoding());
        BufferedReader reader = new BufferedReader(reader);
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }

Приведенный выше код не работает. Я обнаружил, что кодировка FileReader - это CP1252, даже если текст кодируется UTF-8. Но JavaDoc java.io.FileReader говорит, что:

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

Означает ли это, что мне не требуется устанавливать кодировку символов самостоятельно, если я использую FileReader? Но в последнее время я получил неверные кодированные данные, какой правильный способ справиться с моей ситуацией? Спасибо.

Ответ 1

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

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

Нет, нет общего способа угадать кодировку любого данного файла "обычного текста".

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

Вместо FileReader вам нужно использовать new InputStreamReader( new FileInputStream(pathToFile) , <encoding>).

Ответ 2

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

Если это "лучшее предположение" неверно, вам нужно явно указать кодировку. К сожалению, FileReader не позволяет этого (большой надзор в API). Вместо этого вы должны использовать new InputStreamReader(new FileInputStream(filePath), encoding) и в идеале получить кодировку из метаданных о файле.

Ответ 3

Начиная с Java 11 вы можете использовать это:

public FileReader(String fileName, Charset charset) throws IOException;

Ответ 4

Для Java 7+ doc вы можете использовать это:

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

Вот все документы Charsets

Например, если ваш файл в CP1252, используйте этот метод

Charset.forName("windows-1252");

Вот другие канонические имена для кодировок Java и для IO и для документа NIO

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

Ответ 5

Для других латинских языков, например, кириллицы, вы можете использовать что-то вроде этого:

FileReader fr = new FileReader("src/text.txt", StandardCharsets.UTF_8);

и убедитесь, что ваш файл .txt сохранен в формате UTF-8 (но не по умолчанию ANSI). Ура!

Ответ 6

FileInputStream с InputStreamReader лучше, чем напрямую использовать FileReader, поскольку последний не позволяет указывать кодировку charset.

Вот пример использования BufferedReader, FileInputStream и InputStreamReader вместе, чтобы вы могли читать строки из файла.

List<String> words = new ArrayList<>();
List<String> meanings = new ArrayList<>();
public void readAll( ) throws IOException{
    String fileName = "College_Grade4.txt";
    String charset = "UTF-8";
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream(fileName), charset)); 

    String line; 
    while ((line = reader.readLine()) != null) { 
        line = line.trim();
        if( line.length() == 0 ) continue;
        int idx = line.indexOf("\t");
        words.add( line.substring(0, idx ));
        meanings.add( line.substring(idx+1));
    } 
    reader.close();
}