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

Перекодировка файлов: чтение в одной кодировке, запись в другой

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

1. Введение

Представьте, что вы получили от бухгалтера файл с отчётом, который был сохранён в "Windows-1251" (старая кодировка для кириллицы). Ваше Java‑приложение ожидает все входные данные в "UTF-8", иначе оно начинает «ругаться» и выдавать иероглифы вместо букв. Или, например, вы интегрируетесь с системой, которая принимает только "ISO-8859-1". Что делать? Конечно, перекодировать файл!

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

Как работает перекодировка в Java: общий подход

В Java строки (String) внутри программы всегда хранятся в Unicode (UTF‑16). Это значит, что когда вы прочитали текст из файла, он уже «универсален» и может быть записан в любую поддерживаемую кодировку. Поэтому перекодировка — это просто:

  • Прочитать файл как строки, указав правильную исходную кодировку.
  • Записать эти строки в новый файл, явно указав нужную целевую кодировку.

Схема:

[Файл в кодировке A] --(чтение с Charset A)--> [String в памяти] --(запись с Charset B)--> [Файл в кодировке B]

2. Пошаговый алгоритм перекодировки

Шаг 1. Определить исходную и целевую кодировку
Исходная кодировка — та, в которой сохранён исходный файл (например, "Windows-1251"). Целевая кодировка — та, в которой вы хотите получить результат (например, "UTF-8").

Шаг 2. Открыть поток для чтения с нужной кодировкой
Используем Files.newBufferedReader(Path, Charset) или классический InputStreamReader.

Шаг 3. Открыть поток для записи с нужной кодировкой
Используем Files.newBufferedWriter(Path, Charset) или классический OutputStreamWriter.

Шаг 4. Читать строки и писать их в новый файл
Читаем построчно (или целиком — если файл маленький), каждую строку записываем в новый файл.

Шаг 5. Закрыть потоки (лучше использовать try-with-resources)
Так мы гарантируем корректное освобождение ресурсов. Применяйте конструкцию try-with-resources.

3. Пример кода: перекодировка Windows-1251 → UTF-8

Давайте реализуем простую программу, которая перекодирует файл из Windows‑1251 в UTF‑8. Такой пример часто встречается в реальной жизни, особенно если вы работаете с русскоязычными данными.

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

public class FileReencoder {
    public static void main(String[] args) throws IOException {
        // Пути к файлам
        Path inputPath = Paths.get("input-1251.txt");
        Path outputPath = Paths.get("output-utf8.txt");

        // Открываем reader с исходной кодировкой Windows-1251
        try (
            BufferedReader reader = Files.newBufferedReader(inputPath, Charset.forName("Windows-1251"));
            BufferedWriter writer = Files.newBufferedWriter(outputPath, StandardCharsets.UTF_8)
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine(); // не забываем перенос строки!
            }
        }

        System.out.println("Файл успешно перекодирован из Windows-1251 в UTF-8!");
    }
}

Здесь мы явно указываем кодировку для чтения (Charset.forName("Windows-1251")) и для записи (StandardCharsets.UTF_8). Затем используем try-with-resources, чтобы потоки закрылись автоматически даже при ошибках. writer.newLine() — перенос строки, чтобы структура файла сохранилась.

4. Важные нюансы и лайфхаки

Как узнать исходную кодировку файла?

  • Файл сам по себе не содержит «ярлыка» с указанием кодировки (исключение — BOM, но он встречается не всегда).
  • Если файл создавали вы — используйте ту же кодировку, что и при записи.
  • Если файл пришёл «откуда-то» — попробуйте открыть его в редакторе, который показывает кодировку (например, Notepad++, Visual Studio Code).
  • В Linux можно использовать команду file -i имя_файла, но она не всегда определяет кодировку корректно.

Что будет, если указать неверную исходную кодировку?

Вы получите «кракозябры» или потерю символов. Например, если читать файл, сохранённый в Windows‑1251, как UTF‑8, кириллица превратится в "РџСЂРёР²РµС‚".

Обработка исключений

При работе с файлами всегда возможны ошибки: файл не найден, нет прав, неверная кодировка. Используйте обработку исключений (try-catch) или выбрасывайте их выше (throws), чтобы приложение не падало «без объяснения причин».

Работа с большими файлами

Если файл огромный (гигабайты!), используйте построчное чтение и запись, как в приведённых примерах. Не читайте весь файл в память целиком — иначе получите OutOfMemoryError.

Перекодировка «на лету» (стриминг)

Если файл очень большой, можно даже не создавать промежуточный файл, а читать и писать «на лету» — например, при потоковой обработке данных из сети.

5. Типичные ошибки при перекодировке файлов

Ошибка №1: Неправильная исходная кодировка. Если вы ошиблись с исходной кодировкой, результат будет печальным: «Привет» превратится в "Привет". Всегда выясняйте, в какой кодировке был создан файл.

Ошибка №2: Неявное использование системной кодировки. Если не указать кодировку явно, Java использует системную по умолчанию (System.getProperty("file.encoding")). Это может привести к разным результатам на разных компьютерах (например, на Windows — cp1251, на Linux — UTF‑8).

Ошибка №3: Чтение и запись всего файла в память. Для больших файлов такой подход приведёт к переполнению памяти. Используйте построчное чтение и запись.

Ошибка №4: Необработанные исключения. Файлы могут не существовать, быть заняты другими процессами или содержать битые символы. Всегда обрабатывайте исключения или используйте try-with-resources.

Ошибка №5: Перекодировка бинарных файлов. Не пытайтесь перекодировать картинки, PDF, архивы и другие бинарные файлы! Это приведёт к их порче. Перекодировка имеет смысл только для текстовых файлов.

1
Задача
JAVA 25 SELF, 37 уровень, 4 лекция
Недоступна
Цифровой архивариус: Миграция старых документов в новый формат 🏛️
Цифровой архивариус: Миграция старых документов в новый формат 🏛️
1
Задача
JAVA 25 SELF, 37 уровень, 4 лекция
Недоступна
Спасатель цифровых данных: Безопасная перекодировка с защитой от сбоев 🚨
Спасатель цифровых данных: Безопасная перекодировка с защитой от сбоев 🚨
1
Опрос
Работа с кодировками, 37 уровень, 4 лекция
Недоступен
Работа с кодировками
Работа с кодировками
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ