Kodierung einer Textdatei bestimmen?

flashray

Erfahrenes Mitglied
Hallo Javagemeinde,

wie bestimmt man die Kodierung einer Textdatei in Java. Lesen und Schreiben mit Angabe einer Kodierung ist kein Thema. Ich habe jedoch keine Methode gefunden, die von einer gegebenen Datei die Kodierung feststellt.

Vg Erdal
 
Hallihallo,

ich interpretiere hier das mal so.

Keine Antwort = Mit Java alleine nicht lösbar!

Da aber der Microsoft Editor verschieden kodierte Textdateien richtig erkennt und öffnet, muss es doch ein Erkennungsmerkmal geben. Ich werd mal im C/C++ Forum fragen.

Vg Erdal
 
Hi,

wie man die Kodierung von XML Dateien feststellen kann:

Man schaut sich die ersten beiden Bytes an:

- 0x3C 0x3F = "<?" => auslesen des encoding="<...>"
- 0x00 0x3C = "<" => UTF-16 BigEndian
- 0x3C 0x00 = "<" => UTF-16 LowEndian

Wenn keiner dieser Fälle zutreffen sollte wird UTF-8 als default encoding angenommen.

Für Textdateien muss ich passen.

Gruß

Romsl
 
Hallo Romsl,

heißt das der Wert in den ersten beiden bytes bezieht sich auf das encoding="..." in der XML Deklaration?

Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
...
</root>

So wäre dann die Kodierung explizit im Text angegeben. Was bei gewöhnlichen Textdateien nicht der Fall ist. Besitzt denn eine Textdatei überhaupt einen Beschreibungs- und einen Inhalteil? Oder ist die gesamte Textdatei von Byte eins bis letztes Byte ausschließlich für den Textinhalt gewidmet?

Vg Erdal
 
Hi,

die ersten beiden Bytes werden herangezogen um das Encoding festzustellen. Dies geschieht wenn das Encoding nicht direkt angegeben ist.

Gruß

Romsl
 
Hallo,

hab den genannten Code ausprobiert. Nach ein paar Test, scheint es ordentlich zu funktionieren.

Hier nochmal der Code, falls sich der genannte Link irgendwann ändern sollte.

Code:
/**
 Original pseudocode   : Thomas Weidenfeller
 Implementation tweaked: Aki Nieminen

 http://www.unicode.org/unicode/faq/utf_bom.html
 BOMs:
 00 00 FE FF    = UTF-32, big-endian
 FF FE 00 00    = UTF-32, little-endian
 FE FF          = UTF-16, big-endian
 FF FE          = UTF-16, little-endian
 EF BB BF       = UTF-8

 Win2k Notepad:
 Unicode format = UTF-16LE
 ***/

import java.io.*;

/**
 * Generic unicode textreader, which will use BOM mark
 * to identify the encoding to be used. If BOM is not found
 * then use a given default encoding.
 * System default is used if:
 *    BOM mark is not found and defaultEnc is NULL
 *
 * Usage pattern:
 String defaultEnc = "ISO-8859-1"; // or NULL to use system default
 FileInputStream fis = new FileInputStream(file);
 Reader in = new UnicodeReader(fis, defaultEnc);
 */
public class UnicodeReader extends Reader {
	PushbackInputStream internalIn;

	InputStreamReader internalIn2 = null;

	String defaultEnc;

	private static final int BOM_SIZE = 4;

	UnicodeReader(InputStream in, String defaultEnc) {
		internalIn = new PushbackInputStream(in, BOM_SIZE);
		this.defaultEnc = defaultEnc;
	}

	public String getDefaultEncoding() {
		return defaultEnc;
	}

	public String getEncoding() {
		if (internalIn2 == null)
			return null;
		return internalIn2.getEncoding();
	}

	/**
	 * Read-ahead four bytes and check for BOM marks. Extra bytes are
	 * unread back to the stream, only BOM bytes are skipped.
	 */
	protected void init() throws IOException {
		if (internalIn2 != null)
			return;

		String encoding;
		byte bom[] = new byte[BOM_SIZE];
		int n, unread;
		n = internalIn.read(bom, 0, bom.length);

		if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB)
				&& (bom[2] == (byte) 0xBF)) {
			encoding = "UTF-8";
			unread = n - 3;
		} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
			encoding = "UTF-16BE";
			unread = n - 2;
		} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
			encoding = "UTF-16LE";
			unread = n - 2;
		} else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00)
				&& (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
			encoding = "UTF-32BE";
			unread = n - 4;
		} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
				&& (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
			encoding = "UTF-32LE";
			unread = n - 4;
		} else {
			// Unicode BOM mark not found, unread all bytes
			encoding = defaultEnc;
			unread = n;
		}
		//      System.out.println("read=" + n + ", unread=" + unread);

		if (unread > 0)
			internalIn.unread(bom, (n - unread), unread);

		// Use given encoding
		if (encoding == null) {
			internalIn2 = new InputStreamReader(internalIn);
		} else {
			internalIn2 = new InputStreamReader(internalIn, encoding);
		}
	}

	public void close() throws IOException {
		init();
		internalIn2.close();
	}

	public int read(char[] cbuf, int off, int len) throws IOException {
		init();
		return internalIn2.read(cbuf, off, len);
	}

}

Vg Erdal
 
Hallo Erdal,

ich habe diesen alten Thread ausgegraben. Mein Problem ist, dass ich Testdateien darauf prüfen muss, ob sie in UTF-8 kodiert ist. Habe dazui deinen Beispielcode genutzt und mir zwei Textdateien mit identischem Inhalt, eine in UTF-8, die andere in ISO-8859-1 erstellt. Beim Lesen mit deiner Beispielklasse werden in der UTF-8-Datei die ersten drei Bytes übersprungen, so dass in bom[] immer das gleiche steht.
Hast du (oder sonst jemand) eine Idee, woran das liegt?

Danke, Henning
 
Zurück