Gerade noch etwas unerfahrene Java Programmierer haben teilweise Probleme mit unterschiedlichen Zeichensätzen. Läuft bei der Entwicklung und dem Test auf der lokalen Maschine noch alles glatt - wieso sich auch Gedanken machen, wenn alles funktioniert - ist die Überraschung teilweise groß, wenn über Schnittstellen fremde Rechner ins Spiel kommen und beispielsweise die Umlaute nicht mehr richtig dargestellt werden.
Generell gilt:
UNICODE
Zeichensatz.
UNICODE
.
Wird eine Textdatei geschrieben, übersetzt Java von UNICODE
in den Default-Zeichensatz des Rechners.
Der von Java verwendete Default-Zeichensatz kann übrigens wie folgt festgestellt werden:
public class DefaultEncoding { public static void main(String[] args) throws Exception { System.out.println("Default Encoding = " + System.getProperty("file.encoding")); } }
und liefert dann beispielsweise in einer Windows-Umgebung:
C:\temp>java DefaultEncoding Default Encoding = Cp1252
Links: Java Supported Encodings / Wikipedia Zeichenkodierungen
Aber: woher weiß denn Java eigentlich, ob es sich bei einer Datei um eine Textdatei oder eine Binärdatei (.jpg, .zip, etc.) handelt? Weiß es nicht! Der Entwickler muss wissen was er liest oder schreibt und mit entsprechenden Klassen und Methoden dafür sorgen, dass eine Textdatei entsprechend umcodiert wird und eine Binärdatei belassen bleibt, wie sie ist.
Und hier wartet auch schon der nächste Stolperstein:
Verwenden Sie:
Reader
und
Writer
Klassen um Textdateien
zu lesen und zu schreiben.
InputStream
und
OutputStream
Klassen um Binärdateien
zu lesen und zu schreiben.
InputStreamReader
und
OutputStreamWriter
zählen zu den
Reader
und
Writer
Klassen und sind deshalb
nicht zum lesen / schreiben von Binärdateien geeignet!
Wenn Sie unsicher sind, welche Klassen Sie verwenden sollen, sehen Sie nach, ob die Klasse
oder deren Elternklasse einen Constructor anbietet, der einen Charset
oder einen anderen Reader
/ Writer
als Parameter erwartet. Wenn ja, handelt
es sich mit Sicherheit um eine Klasse die nur für das lesen / schreiben von Textdateien geeignet ist.
Weiterhin werden Sie es bei der Verarbeitung von Binärdateien immer mit einer Form von ByteArrays und bei der Verarbeitung von Textdateien immer mit einer Form von Strings, SringBuffern oder CharacterArrays zu tun haben.
Lesen einer Binärdatei:
import java.io.*; ... byte[] getBinaryFileContent(String fileName) throws IOException { BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName)); ByteArrayOutputStream bs = new ByteArrayOutputStream(); BufferedOutputStream out = new BufferedOutputStream(bs); byte[] ioBuf = new byte[4096]; int bytesRead; while ((bytesRead = in.read(ioBuf)) != -1) out.write(ioBuf, 0, bytesRead); out.close(); in.close(); return bs.toByteArray(); }
Schreiben einer Binärdatei:
import java.io.*; ... void writeBinaryFileContent(String fileName, byte[] content) throws IOException { BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(content)); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName)); byte[] ioBuf = new byte[4096]; int bytesRead; while ((bytesRead = in.read(ioBuf)) != -1) out.write(ioBuf, 0, bytesRead); out.close(); in.close(); }
Kopieren einer (Binär- oder Text-) Datei:
import java.io.*; ... void copyFile(String srcName, String dstName) throws IOException { InputStream in = new FileInputStream(srcName); OutputStream out = new FileOutputStream(dstName); byte[] ioBuf = new byte[4096]; int bytesRead; while ((bytesRead = in.read(ioBuf)) != -1) out.write(ioBuf, 0, bytesRead); out.close(); in.close(); }
Lesen einer Textdatei mit Default Zeichensatz-Codierung:
import java.io.*; ... String getTextFileContent(String textFileName) throws IOException { StringBuffer content = new StringBuffer(); String line, lineFeed = System.getProperty("line.separator"); BufferedReader in = new BufferedReader(new FileReader(textFileName)); while((line = in.readLine()) != null) content.append(line).append(lineFeed); in.close(); return content.toString(); }
Lesen einer UTF8 codierten Textdatei:
z.B. eine unter Unix erzeugte Textdatei in einem Windows-System verarbeiten
import java.io.*;
...
String getUTF8TextFileContent(String textFileName) throws IOException
{ StringBuffer content = new StringBuffer();
String line, lineFeed = System.getProperty("line.separator");
Reader r = new InputStreamReader(new FileInputStream(textFileName), "UTF8");
BufferedReader in = new BufferedReader(r);
while((line = in.readLine()) != null) content.append(line).append(lineFeed);
in.close();
return content.toString();
}
Schreiben einer UTF8 codierten Textdatei:
z.B. auf einem Windows-System eine Textdatei für Unix erstellen
import java.io.*; ... void writeUTF8TextFileContent(String textFileName, String content) throws IOException { String line, lineFeed = new String("\n"); // Unix LineFeed BufferedReader in = new BufferedReader(new StringReader(content)); Writer w = new OutputStreamWriter(new FileOutputStream(textFileName), "UTF8"); BufferedWriter out = new BufferedWriter(w); while((line = in.readLine()) != null) { out.write(line); out.write(lineFeed); } out.close(); in.close(); }
Wie bereits oben erwähnt, hält Java alle Buchstaben und Zeichenketten intern im
UNICODE
Zeichensatz vor. Wird eine Java Quelldatei übersetzt, wird vom
Compiler angenommen, dass diese Quelldatei im Default-Zeichensatz des Rechners vorliegt,
auf dem der Übersetzungsprozess läuft und alle konstanten Strings werden deshalb vom
Default-Zeichensatz nach UNICODE
transformiert und so in die .class Datei
abgespeichert. Das hat zur Folge, dass eine Java Quelldatei, die zum Beispiel auf einem
Unix System verfasst wurde, nicht so ohne weiteres auf einem Windows System übersetzt
werden kann, wenn sie beispielsweise in UTF8 codiert ist. Deshalb muss in diesem Fall der
Compiler mit einer zusätzlichen Option -encoding UTF8
gestartet werden:
C:\temp>javac -encoding UTF8 MyUTF8CodedProgram.java
Falls Sie Ihre Java Programme innerhalb einer Windows-Umgebung entwickeln, ist Ihnen sicher
schon einmal aufgefallen, dass Umlaute auf der System-Console (System.out
)
falsch dargestellt werden. Das liegt daran, dass Java davon ausgeht, dass alle Zeichen auf
einem Windows-System in der Default-Codierung (z.B.: CP1252
) ausgegeben werden müssen.
Leider geht die Windows System-Console aber davon aus, dass eingehende Zeichen im alten
DOS-Format CP850
codiert sind, weshalb die Ausgaben von Java Programmen
nicht richtig dargestellt werden.
Abhilfe schafft ein Trick, bei dem die System.out
als Basis für einen
Filter herangezogen wird, mit dem die Zeichensatz-Konvertierung vorgenommen wird:
import java.io.*;
public class ConsoleOutput
{ public static void main(String[] args) throws Exception
{ System.out.println("schönes München");
System.setOut(new PrintStream(
new FileOutputStream(FileDescriptor.out),true,"CP850"));
System.out.println("schönes München");
}
}
C:\temp>java ConsoleOutput sch÷nes M³nchen schönes München
Copyright © 2003 Wöhrmann Softwareentwicklung - Höhenkirchen-Siegertsbrunn - Landkreis München