CodeGym /Kurse /JAVA 25 SELF /Probleme durch nicht übereinstimmende Zeichencodierungen,...

Probleme durch nicht übereinstimmende Zeichencodierungen, typische Fehler

JAVA 25 SELF
Level 37 , Lektion 3
Verfügbar

1. Fehlersymptome

In einer idealen Welt wissen Entwickler immer, in welcher Codierung eine Datei gespeichert ist, und geben sie beim Lesen korrekt an. In der Realität jedoch wandern Dateien zwischen Windows, Linux, Servern und Editoren, und jede Umgebung interpretiert Bytes auf ihre eigene Weise. Das führt zu Symptomen wie:

  • „Mojibake“ – statt des erwarteten Textes erscheinen seltsame Zeichen, Fragezeichen, Kästchen oder ein Buchstabensalat, der zu keiner Sprache passt.
  • Zeichenverlust – Teile des Textes verschwinden oder werden durch ? ersetzt.
  • Ausnahmen – zum Beispiel MalformedInputException, wenn Java die Bytes in der gewählten Codierung nicht „verdauen“ kann.
  • Parsing-Fehler – das Programm kann die Datei nicht korrekt verarbeiten, weil Schlüsselwörter oder Strukturen durch Textverfälschung beschädigt wurden.

Ein klassisches Beispiel für „Mojibake“ beim Lesen einer Datei mit kyrillischem Text in der falschen Codierung:

Erwartet:  Privet, mir!
Bekommen: Привет, мир

Das ist keine neue Sprache, sondern das Ergebnis davon, dass die Bytes mit dem falschen „Wörterbuch“ interpretiert wurden.

2. Warum Fehler entstehen: die Wurzel des Übels

Datei in einer Codierung gespeichert, in einer anderen gelesen

Angenommen, jemand hat die Datei in Windows-1251 gespeichert, Sie öffnen sie aber in UTF-8. Java versucht ehrlich, die Bytes nach den Regeln von UTF-8 zu dekodieren, doch entsteht Unsinn, weil die Bytewerte nicht den Erwartungen entsprechen.

Verwendung der systemweiten Standardcodierung

Wenn Sie die Codierung nicht explizit angeben, verwendet Java die Systemcodierung – diejenige, die auf Ihrem Rechner eingestellt ist. Unter Windows mit russischer Ländereinstellung kann das Windows-1251 sein, unter Linux UTF-8, auf dem Mac ebenfalls UTF-8. Eine Datei, die bei Ihnen problemlos geöffnet wird, kann bei einer Kollegin auf einem anderen OS unlesbar sein.

Verwendung veralteter Konstruktoren

In älteren Java-Versionen (und in manchen Lehrbüchern) findet man oft Konstrukte mit FileReader/FileWriter, die die Systemcodierung nutzen und Ihnen keine Kontrolle geben – das ist eine Falle und eine Quelle für „Mojibake“.

FileReader reader = new FileReader("file.txt");
FileWriter writer = new FileWriter("file.txt");

Vorhandensein oder Fehlen eines BOM (Byte Order Mark)

Einige Codierungen (z. B. UTF-8 mit BOM oder UTF-16) fügen am Anfang der Datei spezielle Bytes hinzu, um auf ihre Natur hinzuweisen. Erwartet ein Programm ein BOM nicht oder umgekehrt – erwartet es eines, findet aber keines –, können Probleme auftreten: entweder werden die ersten Zeichen der Datei verfälscht oder die Datei wird gar nicht erkannt.

3. Wie sich Fehler äußern: in der Praxis

Beispiel 1: Datei mit kyrillischem Text, in Windows-1251 gespeichert, als UTF-8 gelesen

import java.nio.file.*;
import java.nio.charset.*;

public class EncodingDemo {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("russian.txt");
        // Datei ist in Windows-1251 gespeichert, wir lesen sie als UTF-8 – es gibt Mojibake!
        try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
            System.out.println(reader.readLine());
        }
    }
}

Als Ergebnis sehen Sie statt des erwarteten Textes eine Folge seltsamer Zeichen.

Beispiel 2: Datei ist in UTF-8 gespeichert, wird aber als ISO-8859-1 gelesen

try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1)) {
    System.out.println(reader.readLine());
}

Ergebnis: Alle Nicht-ASCII-Zeichen werden zu Müll oder durch ? ersetzt.

Beispiel 3: Ausnahme beim Lesen einer Datei

Wenn Bytes nicht den Regeln der gewählten Codierung entsprechen, kann Java eine Ausnahme auslösen:

Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
    at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    ...

Das bedeutet, dass Java auf ein Byte gestoßen ist, das in der gewählten Codierung nicht korrekt interpretiert werden kann.

4. Diagnose: wie man Codierungsprobleme erkennt

Codierung der Datei prüfen

  • In Editoren wie Notepad++, VS Code oder Sublime Text kann man die Dateicodierung einsehen oder ändern (meist in der unteren Leiste).
  • Unter Linux liefert ein Befehl oft einen Hinweis auf die Codierung (nicht immer 100 % exakt):
file imya_faila.txt

Systemcodierung von Java prüfen

Geben Sie den Wert der Eigenschaft file.encoding auf die Konsole aus:

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

Verwenden Sie Testdaten

Erstellen Sie eine kleine Datei mit unterschiedlichen Zeichen (kyrillische, lateinische, Sonderzeichen, Emojis), lesen Sie sie mit verschiedenen Codierungen und prüfen Sie, wann das Ergebnis den Erwartungen entspricht.

Geben Sie die Codierung immer explizit an

Sobald Sie im Code Datei-Ein-/Ausgabe ohne Angabe der Codierung sehen – Vorsicht. Verwenden Sie zum Beispiel Files.newBufferedReader(..., StandardCharsets.UTF_8) statt „Defaults“.

5. Best Practices: wie man nicht in die Falle tappt

Regel Nr. 1:
IMMER die Codierung explizit angeben, insbesondere wenn die Datei auf verschiedenen Rechnern, in unterschiedlichen Betriebssystemen oder über das Netzwerk genutzt wird.

Regel Nr. 2:
Verwenden Sie moderne, weit verbreitete Codierungen – in erster Linie UTF-8 (StandardCharsets.UTF_8). Nur wenn es besondere Anforderungen gibt (z. B. Integration mit einem Altsystem), nutzen Sie andere Codierungen.

Regel Nr. 3:
Vermeiden Sie die Klassen FileReader und FileWriter (sie erlauben keine explizite Codierung). Verwenden Sie stattdessen InputStreamReader, OutputStreamWriter oder Methoden aus Files mit explizitem Charset.

Regel Nr. 4:
Prüfen Sie das Ergebnis! Öffnen Sie geschriebene Dateien in Editoren mit Unterstützung für verschiedene Codierungen, um sicherzustellen, dass der Text korrekt aussieht.

6. Besonderheiten und Feinheiten: BOM, XML, JSON und andere „tückische“ Fälle

BOM (Byte Order Mark): Manchmal beginnt eine UTF-8-Datei mit „unsichtbaren“ Bytes (EF BB BF). Die meisten modernen Programme ignorieren sie, einige zeigen jedoch zu Beginn der Zeile „Mojibake“ an oder akzeptieren die Datei nicht (z. B. ältere Parser für XML/JSON).

XML/HTML: Am Anfang der Datei steht manchmal eine Zeile wie <?xml version="1.0" encoding="UTF-8"?>. Sie teilt dem Programm mit, welche Codierung zu erwarten ist. Stimmt die tatsächliche Codierung nicht mit der deklarierten überein – gibt es wieder „Mojibake“.

JSON: Laut Standard sollte es in UTF-8 vorliegen. Wird die Datei jedoch in Windows-1251 erstellt, gibt der Parser einen Fehler aus oder liefert verfälschte Daten.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION