Как прочитать файл в Java с определенной кодировкой символов?

Я пытаюсь прочитать файл в формате UTF-8 или Windows-1252 в зависимости от вывода этого метода:

public Charset getCorrectCharsetToApply() {
    // Returns a Charset for either UTF-8 or Windows-1252.
}

Пока что у меня есть:

String fileName = getFileNameToReadFromUserInput();
InputStream is = new ByteArrayInputStream(fileName.getBytes());
InputStreamReader isr = new InputStreamReader(is, getCorrectCharsetToApply());
BufferedReader buffReader = new BufferedReader(isr);

У меня проблема заключается в преобразовании BufferedReader экземпляр для FileReader,

Более того:

  • Название самого файла (fileName) нельзя доверять, чтобы быть конкретным Charset; иногда имя файла будет содержать символы UTF-8, а иногда и Windows-1252. То же самое касается содержимого файла (однако, если имя файла и содержимое файла всегда будут иметь совпадающие кодировки).
  • Только логика внутри getCorrectCharsetToApply() Я могу выбрать набор символов для применения, поэтому попытка чтения файла по его имени до вызова этого метода может привести к тому, что Java попытается прочитать имя файла с неправильной кодировкой... что приведет к его смерти!

Заранее спасибо!

4 ответа

Решение

Итак, во-первых, как голову, осознайте, что fileName.getBytes() поскольку у вас есть получает байты имени файла, а не сам файл.

Во-вторых, чтение внутри документов FileReader:

Конструкторы этого класса предполагают, что кодировка символов по умолчанию и размер байтового буфера по умолчанию являются подходящими. Чтобы указать эти значения самостоятельно, создайте InputStreamReader для FileInputStream.

Итак, звучит так, будто FileReader на самом деле не тот путь. Если мы воспользуемся советом в документации, то вам просто нужно изменить код так, чтобы он имел:

String fileName = getFileNameToReadFromUserInput();
FileInputStream is = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(is, getCorrectCharsetToApply());
BufferedReader buffReader = new BufferedReader(isr);

и не пытайтесь сделать FileReader вообще.

С Java 7+ вы можете создать Reader в одну строку:

BufferedReader buffReader = Files.newBufferedReader(Paths.get(fileName), getCorrectCharsetToApply());

Обратите внимание, что если вы используете Google Guava, вы можете использовать Files.newReader:

final BufferedReader reader =
        Files.newReader(new File(filename), getCorrectCharsetToApply());

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

      String fileName = getFileNameToReadFromUserInput();
InputStream is = new ByteArrayInputStream(fileName.getBytes());
InputStreamReader isr = new InputStreamReader(is, getCorrectCharsetToApply());
BufferedReader buffReader = new BufferedReader(isr);

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

      void processFile(String fileName, Charset charset) {
    try (
        InputStream is = new FileInputStream(fileName);
        InputStreamReader isr = new InputStreamReader(is, charset);
        BufferedReader buffReader = new BufferedReader(isr);
    ) {
        ... (do whatever you have to do here by reading buffReader)
    }
}

void main(String[]) {
    String fileName = getFileNameToReadFromUserInput();

    // try all the known charsets
    for (Charset charset: Charset.availableCharsets().values()) {
        try {
            processFile(fileName, charset);
            // still here? then it was successful
            return;
        } catch (Exception e) {
            System.out.println("Reading " + fileName + " with " + charset + " resulted in");
            e.printStackTrace();
            System.out.println("Trying next...");
        }
    }
}

Блок try-with-resources внутри ProcessFile гарантирует закрытие всех файлов/потоков/буферов, когда они больше не нужны. Блок try/catch в основном методе гарантирует, что программа не умрет, если мы выберем неправильную кодировку.

Другие вопросы по тегам