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
Опитування
Робота з кодуваннями, рівень 37, лекція 4
Недоступний
Робота з кодуваннями
Робота з кодуваннями
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ