JavaRush /Курсы /JAVA 25 SELF /Задание кодировки при чтении/записи файлов

Задание кодировки при чтении/записи файлов

JAVA 25 SELF
37 уровень , 2 лекция
Открыта

1. Введение

Давайте сразу честно: если вы хотя бы раз видели вместо русского текста что-то вроде Привет, вы уже жертва неправильной кодировки. Это случается, когда файл был записан в одной кодировке, а читается в другой. Например, файл был сохранён как UTF-8, а читается как Windows-1251, или наоборот.

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

System.out.println(System.getProperty("file.encoding"));

На одном компьютере это может быть UTF-8, на другом — Windows-1251, а где-то ещё — ISO-8859-1. Именно поэтому всегда лучше указывать кодировку явно. Это особенно важно, если приходится работать с многоязычными данными, если файлы будут использоваться на разных компьютерах или открываться в других программах, или если нужно, чтобы ваш код вёл себя одинаково в любой среде, а не только на вашей машине.

Класс Charset: ваш друг в мире кодировок

В Java для работы с кодировками используется класс java.nio.charset.Charset. Он позволяет задавать кодировку как именем (например, "UTF-8"), так и использовать стандартные константы (StandardCharsets.UTF_8).

Примеры стандартных кодировок:

Кодировка Константа Java
UTF-8
StandardCharsets.UTF_8
UTF-16
StandardCharsets.UTF_16
ISO-8859-1
StandardCharsets.ISO_8859_1
Windows-1251
Charset.forName("Windows-1251")

Использование констант предпочтительнее: меньше шансов ошибиться в названии и не возникнет UnsupportedCharsetException.

2. Чтение файлов с указанием кодировки

Старый способ:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Явно указываем кодировку
    )
);

Современный способ:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedReader;

BufferedReader reader = Files.newBufferedReader(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Явно указываем кодировку
);

Рекомендуется использовать второй способ — он короче, безопаснее и удобно сочетается с try-with-resources.

Пример: читаем строку из файла

try (BufferedReader reader = Files.newBufferedReader(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    String line = reader.readLine();
    System.out.println("Прочитали: " + line);
}

Почему это важно: Если файл был сохранён в UTF-8, а вы читаете его как Windows-1251, кириллические символы исказятся. Если указать правильную кодировку, текст будет читаться корректно на любой ОС.

3. Запись файлов с указанием кодировки

Старый способ:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Явно указываем кодировку
    )
);

Современный способ:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedWriter;

BufferedWriter writer = Files.newBufferedWriter(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Явно указываем кодировку
);

Пример: пишем строку в файл

try (BufferedWriter writer = Files.newBufferedWriter(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    writer.write("Привет, мир!");
}

Результат: Файл будет сохранён в UTF-8, и его можно будет корректно открыть в любом редакторе, поддерживающем UTF-8.

4. Полезные нюансы

Как узнать поддерживаемые кодировки

import java.nio.charset.Charset;

public class ListCharsets {
    public static void main(String[] args) {
        System.out.println("Доступные кодировки:");
        Charset.availableCharsets().forEach((name, charset) -> System.out.println(name));
    }
}

Совет: Если вы используете экзотическую кодировку (например, для древнекитайских иероглифов или марсианских смайликов), проверьте, поддерживается ли она вашей JVM.

Использование try-with-resources: не забываем закрывать потоки

Работая с файлами, важно закрывать потоки, чтобы не было утечек ресурсов. Современный Java-код использует конструкцию try-with-resources:

try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
    // Работаем с файлом
}

Поток закроется автоматически, даже если произойдёт ошибка.

Рекомендации

  • Лучше всегда явно указывать кодировку при чтении и записи файлов, даже если вы уверены, что «по умолчанию всё работает».
  • Используйте UTF-8 для новых файлов — это де-факто стандарт, особенно если вы работаете с web, JSON, XML, или хотите, чтобы ваши файлы были читаемы везде.
  • Для старых файлов (например, выгрузка из 1С, старых баз данных, CSV с Windows) используйте ту кодировку, в которой они были сохранены (например, Windows-1251, ISO-8859-1).
  • Не используйте устаревшие классы, где кодировка не задаётся явно: FileReader/FileWriter. Вместо них применяйте InputStreamReader/OutputStreamWriter с явной кодировкой или методы из Files.
  • Для больших файлов используйте буферизацию (BufferedReader/BufferedWriter), чтобы не съесть всю память.

5. Типичные ошибки при работе с кодировками

Ошибка №1: Не указана кодировка при чтении/записи файла.
Если не указать кодировку, Java использует системную по умолчанию ("file.encoding"). На вашей машине всё работает, а у коллеги — «кракозябры».

Ошибка №2: Несовпадение кодировок при чтении и записи.
Файл был записан в одной кодировке, а читается в другой. Например, файл записан в UTF-8, а читается как Windows-1251 — кириллица искажается.

Ошибка №3: Использование устаревших классов FileReader/FileWriter.
Эти классы не позволяют явно указать кодировку — использовать их не рекомендуется. Вместо них используйте InputStreamReader/OutputStreamWriter с указанием кодировки или методы из Files.

Ошибка №4: Ошибка в названии кодировки.
Например, написали "utf8" вместо "UTF-8" или "win1251" вместо "Windows-1251". Java бросит UnsupportedCharsetException.

Ошибка №5: Не закрыт поток — файл не записался.
Если не использовать try-with-resources или явно не закрыть поток, часть данных может не попасть на диск.

1
Задача
JAVA 25 SELF, 37 уровень, 2 лекция
Недоступна
Аудит системных настроек Java-машины 🖥️
Аудит системных настроек Java-машины 🖥️
1
Задача
JAVA 25 SELF, 37 уровень, 2 лекция
Недоступна
Атлас цифровых языков: Обзор поддерживаемых кодировок 🗺️
Атлас цифровых языков: Обзор поддерживаемых кодировок 🗺️
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ