CodeGym /Kursy /JAVA 25 SELF /Przekodowywanie plików: odczyt w jednym kodowaniu, zapis ...

Przekodowywanie plików: odczyt w jednym kodowaniu, zapis w innym

JAVA 25 SELF
Poziom 37 , Lekcja 4
Dostępny

1. Wprowadzenie

Wyobraź sobie, że otrzymałeś od księgowego plik z raportem, który zapisano w "Windows-1251" (stare kodowanie dla cyrylicy). Twoja aplikacja Java oczekuje wszystkich danych wejściowych w "UTF-8", w przeciwnym razie zaczyna „marudzić” i wyświetlać krzaczki zamiast liter. Albo, na przykład, integrujesz się z systemem, który akceptuje tylko "ISO-8859-1". Co robić? Oczywiście — przekodować plik!

Przekodowywanie — to proces, w którym odczytujesz tekst z pliku w jednym kodowaniu i zapisujesz go w innym. To tak, jakbyś przepisywał list z jednego języka na drugi, aby odbiorca na pewno zrozumiał Twoją wiadomość.

Jak działa przekodowywanie w Javie: podejście ogólne

W Javie łańcuchy (String) wewnątrz programu są zawsze przechowywane w Unicode (UTF‑16). Oznacza to, że kiedy odczytasz tekst z pliku, jest on już „uniwersalny” i może zostać zapisany w dowolnym obsługiwanym kodowaniu. Dlatego przekodowywanie to po prostu:

  • Odczytać plik jako wiersze, podając poprawne kodowanie źródłowe.
  • Zapisać te wiersze do nowego pliku, jawnie wskazując wymagane kodowanie docelowe.

Schemat:

[Plik w kodowaniu A] --(odczyt z Charset A)--> [String w pamięci] --(zapis z Charset B)--> [Plik w kodowaniu B]

2. Algorytm przekodowywania krok po kroku

Krok 1. Określ kodowanie źródłowe i docelowe
Kodowanie źródłowe — to, w którym zapisano plik wejściowy (np. "Windows-1251"). Kodowanie docelowe — to, w którym chcesz otrzymać wynik (np. "UTF-8").

Krok 2. Otwórz strumień do odczytu z właściwym kodowaniem
Użyj Files.newBufferedReader(Path, Charset) lub klasycznego InputStreamReader.

Krok 3. Otwórz strumień do zapisu z właściwym kodowaniem
Użyj Files.newBufferedWriter(Path, Charset) lub klasycznego OutputStreamWriter.

Krok 4. Czytaj wiersze i zapisuj je do nowego pliku
Czytaj wiersz po wierszu (albo całość — jeśli plik jest mały) i każdy wiersz zapisuj do nowego pliku.

Krok 5. Zamknij strumienie (najlepiej użyć try-with-resources)
Dzięki temu zapewnisz poprawne zwalnianie zasobów. Stosuj konstrukcję try-with-resources.

3. Przykład kodu: przekodowywanie Windows-1251 → UTF-8

Zaimplementujmy prosty program, który przekoduje plik z Windows‑1251 do UTF‑8. Taki przykład często spotyka się w praktyce, zwłaszcza gdy pracujesz z danymi rosyjskojęzycznymi.

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 {
        // Ścieżki do plików
        Path inputPath = Paths.get("input-1251.txt");
        Path outputPath = Paths.get("output-utf8.txt");

        // Otwieramy reader z kodowaniem źródłowym 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(); // nie zapominamy o znaku nowej linii!
            }
        }

        System.out.println("Plik został pomyślnie przekodowany z Windows-1251 do UTF-8!");
    }
}

Tutaj jawnie wskazujemy kodowanie dla odczytu (Charset.forName("Windows-1251")) i dla zapisu (StandardCharsets.UTF_8). Następnie używamy try-with-resources, aby strumienie zamknęły się automatycznie nawet w przypadku błędów. writer.newLine() — przejście do nowej linii, aby zachować strukturę pliku.

4. Ważne niuanse i wskazówki

Jak ustalić kodowanie źródłowe pliku?

  • Sam plik nie zawiera „etykiety” z informacją o kodowaniu (wyjątek — BOM, ale nie zawsze występuje).
  • Jeśli plik tworzyłeś Ty — użyj tego samego kodowania, co przy zapisie.
  • Jeśli plik przyszedł „skądinąd” — spróbuj otworzyć go w edytorze, który pokazuje kodowanie (np. Notepad++, Visual Studio Code).
  • W Linuksie możesz użyć polecenia file -i nazwa_pliku, ale nie zawsze poprawnie rozpoznaje ono kodowanie.

Co się stanie, jeśli podasz błędne kodowanie źródłowe?

Dostaniesz „krzaczki” albo utratę znaków. Na przykład, jeśli odczytasz plik zapisany w Windows‑1251 jako UTF‑8, cyrylica zamieni się w "Привет".

Obsługa wyjątków

Podczas pracy z plikami zawsze mogą wystąpić błędy: plik nie znaleziony, brak uprawnień, błędne kodowanie. Używaj obsługi wyjątków (try-catch) lub wyrzucaj je wyżej (throws), aby aplikacja nie kończyła się nieoczekiwanie „bez podania przyczyny”.

Praca z dużymi plikami

Jeśli plik jest ogromny (wielkości gigabajtów!), używaj odczytu i zapisu wiersz po wierszu, jak w podanych przykładach. Nie wczytuj całego pliku do pamięci — w przeciwnym razie otrzymasz OutOfMemoryError.

Przekodowywanie „w locie” (streaming)

Jeśli plik jest bardzo duży, możesz nawet nie tworzyć pliku pośredniego, tylko czytać i pisać „w locie” — na przykład podczas strumieniowego przetwarzania danych z sieci.

5. Typowe błędy przy przekodowywaniu plików

Błąd №1: Nieprawidłowe kodowanie źródłowe. Jeśli pomylisz się w kodowaniu źródłowym, wynik będzie opłakany: „Privet” zamieni się w "Привет". Zawsze ustalaj, w jakim kodowaniu został utworzony plik.

Błąd №2: Niejawne użycie kodowania systemowego. Jeśli nie wskazać kodowania jawnie, Java użyje systemowego domyślnego (System.getProperty("file.encoding")). To może prowadzić do różnych rezultatów na różnych komputerach (np. na Windows — cp1251, na Linuksie — UTF‑8).

Błąd №3: Odczyt i zapis całego pliku do pamięci. Dla dużych plików takie podejście doprowadzi do przepełnienia pamięci. Używaj odczytu i zapisu wiersz po wierszu.

Błąd №4: Nieobsłużone wyjątki. Pliki mogą nie istnieć, być zajęte przez inne procesy albo zawierać uszkodzone znaki. Zawsze obsługuj wyjątki lub używaj try-with-resources.

Błąd №5: Przekodowywanie plików binarnych. Nie próbuj przekodowywać obrazów, PDF, archiwów i innych plików binarnych! To doprowadzi do ich uszkodzenia. Przekodowywanie ma sens tylko dla plików tekstowych.

1
Ankieta/quiz
Praca z kodowaniami, poziom 37, lekcja 4
Niedostępny
Praca z kodowaniami
Praca z kodowaniami
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION