# Encoding



## roli_07 (1. Feb 2008)

Hallo allerseits!

Ich muss Daten aus einer alten Datenbank auslesen und danach filtrieren usw. Das Problem ist, dass Umlaute nciht korrekt dargestelt werden können, oder besser gesagt, werden sie nicht erkannt. Meine Anfrage hat ergben, dass die Datenbank das Encoding *IBM00858* nutzt und wenn ich dieses Encoding einsetzen würde, sollt ich die Umlaute erkennen können. 

Mein Problem ist, dass ich bis heute mit Encoding nicht zu tun hatte. Wie macht man das? Muss ich irgendetwas mit Locale-Klasse machen, oder was? Oder, findet man irgendwo im Internet etwas brauchbares darüber?

Bin auch für den kleinsten Hinweis dankbar. 

mfg


----------



## roli_01 (1. Feb 2008)

Ist damit gemeint, dass ich beim Lesen mit _InputStreamReader _oder beim Schreiben mit _OutputStreamWriter_ noch das Encoding als Parameter angebe?


----------



## Murray (2. Feb 2008)

Das Encoding wird gebraucht, wenn eine in ASCII-Form gespeicherte Zeichenkette in einen Unicode-String umgesetzt wird (und umgekehrt); dazu muss definiert sein, welche Variante der Abbildung von Unicode auf den (kleineren) Wertebereich  der ASCII-Zeichen verwendet werden soll; letztendlich geht es also darum, welche ASCII-Variante ( "Codepage") benutzt werden soll.

Wenn man nichts angibt, verwendet Java bei der Umwandung von Byte-Arrays (ASCII-Texte sind letztendlich nichts anderes) in Unicode-Strings einen von der Lokalisierung des Betriebssystems abhängigen Default-Wert, (der in Deinem Fall eben nicht passt).

Wenn Du also irgendwo einen String hast, dann ist er vermutlich mit genau diesem Default-Encoding interpretiert worden; insofern bekommst Du mit getBytes()  (was wieder das gleiche (Standard-)Encoding verwendet) wieder die originale Byte-Repräsentation.

Lt. java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html
wird das von Dir genannte Encoding für java.io und java.lang als "Cp858" bezeichnet.

Versuch doch mal

```
public String convertStringCp858( String defaultEncodedString) {
  byte[] ba = defaultEncodedString.getBytes();
  String strCp858 = new String( ba, "Cp858");
  return strCp858;
}
```


----------



## roli_07 (3. Feb 2008)

Vielen Dank für deine Antwort. 

Ich habe probiert dies umzusetzen, komme leider weiterhin nicht zum Ziel. 

Ich bin der Meinung, dass Daten ins Programm mit Cp858 eingelesen werden. Das Einlesen wird mit Hilfe von Bibliotheken realisiert, die nicht von mir kommen. Ich nehme jetz einmal an, dass während dem Einlesen das Original-Encoding nicht verloren geht (bin allerdings nicht sicher). So habe ich mit Debugger versucht, die eingelesenen Daten zu analysieren. Wenn ich beispielsweise den Begriff "Schlüssel" habe, wird 'ü' immer mit einem Rechteck dargestellt. Da dies auch ein Problem der Darstellung sein könnte, habe ich den eingelesenen String als byte-Array angeschaut und gesehen, dass das Zeichen 'ü' den Wert 63 hat!!! 

Schlüssel sieht im byte-Array wie folgt aus: 83 99 104 63 115 115 101

Und der Wert 63 ist (meines Wissens) überal gleich und steht für das Fragezeichen! Wenn ich Daten danach in eine Textdatei (XML) schreibe, steht in der Datei das Fragezeichen. Also, die Schlussfolgerung wäre, dass das Original-Encoding "verloren gegangen ist". Oder, ich verstehe etwas immer noch nicht. 

Um zu sehen, ob ich es verstehe oder nicht, habe ich probiert, ein Cp858-String zu erzeugen, in dem nur die drei Umlaute äöü enthalten sind. Laut der Dokumentation zu IBM00858 haben diese Zeichen folgende Werte: 

ä --> 84 (\u00e4) oder -28 als byte-Wert
ö --> 94 (\u00f6) oder -10  als byte-Wert 
ü --> 81 (\u00fc) oder -4 als byte-Wert

Also sieht der obige String als byte-Array wie folgt aus: [-28 -10 -4]

So weit klar. Jetzt probiere ich den obigen String 

-	direkt so auszugeben, 
-	mit einem PrintWriter auszugeben, der Cp850 unterstützt und 
-	mit einem PrintWriter auszugeben, der Cp858 unterstützt. 

Die Asugabe wird im Dos-Schell getätigt. Die erste Ausgabe fehlt etwas kriptisch aus, während sowohl die zweite als auch die dritte Ausgabe korrekt funktionieren. Das ist auch das, was ich erwartet habe. 

Hier noch der Code: 


```
String str="\u00e4\u00f6\u00fc";

byte [] buffer = str.getBytes();

// Ausgabe direkt
System.out.println(str);

// PrintWriter für Cp850
PrintWriter outCp850 = new PrintWriter(new OutputStreamWriter(System.out, "Cp850"));

// PrintWriter für Cp850
PrintWriter outCp858 = new PrintWriter(new OutputStreamWriter(System.out, "Cp858"));

outCp850.println(str);
outCp850.flush();

outCp858.println(str);
outCp858.flush();
```

Habe ich dies einigermassen richtig verstanden, oder bin ich „auf dem Holzweg“? Denn, ich kann es mir gar nicht vorstellen, dass die Originalstrings beim Einlesen „verloren gehen“ können und vermute, dass ich irgendwo noch einen Fehler in meiner Überlegung mache. 

Danke für jeden Tipp.


----------



## roli_07 (3. Feb 2008)

Ich fürchte, da verstehe ich etwas nicht. 

Ich habe jetzt einen String nach Cp858 erzeugt, indem ich zuerst das byte-Array geschrieben habe und danach daraus String erzeugt und ausgegeben. Obwohl ich gehofft habe, irgendeinmal den String *äöü* zu sehen, wurden immer ein anderer String ausgegeben. Hier mein Codebeispiel: 

```
import java.io.*;

public class EncodingTest
{
	public static void main(String[] args) throws Exception
	{
		// 84 -> ä, 94 -> ö, 81 -> ü im Cp858
		byte[] bufCp858 = {84, 94, 81}; 
		
		// String aus dem bufCp858 erzeugen
		String str = new String(bufCp858); 
		
		// String ausgeben
		System.out.println(str); 
		
		System.out.println("------------------------------"); 
		
		// PrintWriter für Cp858 erzeugen
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out, "Cp858")); 
		
		// String Cp858-mässig ausgeben
		out.println(str); 
		out.flush(); 
		
		System.out.println("------------------------------"); 
		
		// aus dem bufCp859 einen Cp858-String erzeugen
		String strCp858 = new String(bufCp858, "Cp858"); 
		
		// String ausgeben mit System.out
		System.out.println("strCp858 mit System.out: " + strCp858); 
		
		System.out.println("------------------------------"); 
		
		// String ausgeben mit out
		out.println("strCp858 mit Cp858-fähigem PrintWriter: " + strCp858);
		out.flush(); 
	}
}
```

Was mache ich falsch?

Danke.


----------



## HoaX (4. Feb 2008)

dir macht java die ausgabe in utf8 aber deine ausgabekonsole zeigt in latin1 an?

als schnellschuss könntest du die ausgabe z.B. mit JOptionPane#showMessage machen


----------



## roli_07 (4. Feb 2008)

Vielen Dank. 

Habe probiert, und zwar wie folgt: 


```
public static void main(String[] args) throws Exception
    {
        // PrintWriter für Cp858 erzeugen
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out,
                "Cp858"));

        // 84 -> ä, 94 -> ö, 81 -> ü im Cp858
        byte[] bufCp858 = { 84, 94, 81 };

        // Strings aus dem bufCp858 erzeugen
        String strSimple = new String(bufCp858);
        String strCp858 = new String(bufCp858, "Cp858");

        JOptionPane.showMessageDialog(null, "strSimple: " + strSimple
                + ", strCp858: " + strCp858);

        System.out.println("----------------------------------------");
        System.out.println("Ausgabe mit System.out:");
        System.out.println("----------------------------------------");
        // Strings ausgeben mit System.out
        System.out.println(strSimple);
        System.out.println(strCp858);

        System.out.println("----------------------------------------");
        System.out.println("Ausgabe mit Cp858-faechigem PrintWriter:");
        System.out.println("----------------------------------------");
        // String Cp858-mässig ausgeben
        out.println(strSimple);
        out.flush();
        out.println(strCp858);
        out.flush();
    }
```

Habe leider keinen Unterschied feststellen können. Ich bekomme immer *T^Q*. 

Oder, hast du was anderes gemeint?

Danke.


----------



## marcel99 (5. Feb 2008)

aus welcher DB liest du daten aus? und, was sind das für bibliotheken, die du benutztst?


----------



## roli_07 (5. Feb 2008)

Daten komen aus UniVerse und werden mit _Uni Objects for Java_.


----------



## roli_07 (5. Feb 2008)

... ausgelesen.


----------



## roli_07 (8. Feb 2008)

Ich *glaube*, ich habe den Fehler im Code gefunden:  :bahnhof: 

```
public static void main(String[] args) throws Exception
    {
        // PrintWriter für Cp858 erzeugen
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out,
                "Cp858"));

        // 84 -> ä, 94 -> ö, 81 -> ü im Cp858
        byte[] bufCp858 = { -124, -108, -127 };

        // Strings aus dem bufCp858 erzeugen
        String strSimple = new String(bufCp858);
        String strCp858 = new String(bufCp858, "Cp858");

        JOptionPane.showMessageDialog(null, "strSimple: " + strSimple
                + ", strCp858: " + strCp858);
    }
```

Das byte-Array wurde mit falschen byte-Werten initialisiert!


----------

