Hallo zusammen,
bei mir herrscht derzeit Konfusion in Sachen Java Encodings. Und zwar möchte ich das Eurosymbol in ein Byte Array umwandeln und erhalte je nachdem welche Funktion ich anwende verschiedene Resultate. Laut ASCII Tabelle (z.B.dieser hier http://www.torsten-horn.de/techdocs/ascii.htm) hat das € Zeichen auf Windows Systemen mit "Windows-1252" Encoding den Dezimalwert 128 bzw.Hexadezimalwert 80. Um zu verifizieren das diese Codierung bei mir Standard ist habe ich folgenden Java-Code benutzt:
Zur Konvertierung von Strings in Byte Arrays habe ich zunächst die übliche String-Methode "getBytes()" getestet, die einmal mit und ohne Encoding Parameter genutzt werden kann. Da "Windows-1252" als Standard definiert ist sind die beiden folgenden Aufrufe equivalent:
Die Ausgabe ist verständlich. Da ein Byte nur aus 8 bit besteht und in Java das 8te bit für Vorzeichen reserviert ist (also den Bereich -128 bis 127 abdeckt) ist -128 die 8 bit Darstellung der Zahl 128. Dementsprechen klappt auch die Rückumwandlung:
Soweit so gut. Nun habe ich noch eine andere Variante im Internet gefunden, die das selbe tut wie getBytes() jedoch performanter sein soll.
Hier lautet allerdings das Resultat [32, -84], jedoch klappt die Rückumwandlung mit folgender Methode ebenfalls.
Um den Rückgabewert der stringToBytesUTFCustom() Methode besser nachvollziehen zu können, habe ich mir mal folgende Inhalte in der for-Schleife ausgeben lassen:
Statt 8364 hätte ich hier wiederum den Wert 128 aus der ASCII Tabelle erwartet. Durch die Bit-Manipulationsoperationen in der Methode erhält man dann schließlich [32, -84], wobei es sich hier scheinbar um die Byte-Werte der Unicode-Codierung des Eurosymbols handelt, was in hexadezimaler Schreibweise dem Wert "20AC" entspricht. Danach habe ich herausgefunden, daß sich mittels folgender Schreibweise ebenfalls das €-Zeichen ausgeben läßt.
Nachdem ich anschließend mit den Encodings in Java etwas weiter herumexperimentiert habe, konnte ich feststellen, daß UTF-16 fast die gleiche Ausgabe liefert, bis auf die Tatsache das hier 2 bytes mehr zurückgegeben werden.
Eine Rücktransformation erzielt man dann mit folgendem Aufruf:
Meine Frage ist nun, warum erhalte ich beim Casten des €-Zeichen von char nach int den Integerwert 8364 und nicht 128? Benutzt Java intern UTF-16 für die Zeichencodierung? Wieso bekomme ich dann bei Verwendung dieses Encodings ein Array mit 4 Bytes und nicht 2?
P.S.: Sorry das der Post so lang geworden ist, aber ich wollte alle meine Erkenntnisse zusammentragen, damit sich mein Problem besser herauskristallisiert
bei mir herrscht derzeit Konfusion in Sachen Java Encodings. Und zwar möchte ich das Eurosymbol in ein Byte Array umwandeln und erhalte je nachdem welche Funktion ich anwende verschiedene Resultate. Laut ASCII Tabelle (z.B.dieser hier http://www.torsten-horn.de/techdocs/ascii.htm) hat das € Zeichen auf Windows Systemen mit "Windows-1252" Encoding den Dezimalwert 128 bzw.Hexadezimalwert 80. Um zu verifizieren das diese Codierung bei mir Standard ist habe ich folgenden Java-Code benutzt:
HTML:
System.out.println(Charset.defaultCharset()); /*Ausgabe: windows-1252*/
System.out.println(System.getProperty("file.encoding")); /*Ausgabe: Cp1252*/
Code:
byte[] bytes = "€".getBytes("windows-1252");
System.out.println(Arrays.toString(bytes)); /*Ausgabe: [-128]*/
bytes = "€".getBytes();
System.out.println(Arrays.toString(bytes)); /*Ausgabe: [-128]*/
Code:
System.out.println(new String(bytes)); /*Ausgabe: €*/
Code:
public static byte[] stringToBytesUTFCustom(String str) {
char[] buffer = str.toCharArray();
byte[] b = new byte[buffer.length << 1];
for(int i = 0; i < buffer.length; i++) {
int bpos = i << 1;
b[bpos] = (byte) ((buffer[i]&0xFF00)>>8);
b[bpos + 1] = (byte) (buffer[i]&0x00FF);
}
return b;
}
Code:
public static void bytesToStringUTFCustom()
{
byte[] bytes = stringToBytesUTFCustom("€");
char[] buffer = new char[bytes.length >> 1];
for (int i = 0; i < buffer.length; i++)
{
int bpos = i << 1;
char c = (char) (((bytes[bpos] & 0x00FF) << 8) + (bytes[bpos + 1] & 0x00FF));
buffer[i] = c;
}
System.out.println(new String(buffer));
}
Code:
System.out.println((int)buffer[i]); /*Ausgabe: 8364*/
System.out.println((int)buffer[i] & 0xFF00); /*Ausgabe: 8192*/
Code:
System.out.println("\u20AC");
Code:
System.out.println(Arrays.toString("€".getBytes("utf-16"))); /*Ausgabe: [-2, -1, 32, -84]*/
Code:
System.out.println(new String("€".getBytes("utf-16"),"utf-16")); /*Ausgabe: €*/
Meine Frage ist nun, warum erhalte ich beim Casten des €-Zeichen von char nach int den Integerwert 8364 und nicht 128? Benutzt Java intern UTF-16 für die Zeichencodierung? Wieso bekomme ich dann bei Verwendung dieses Encodings ein Array mit 4 Bytes und nicht 2?
P.S.: Sorry das der Post so lang geworden ist, aber ich wollte alle meine Erkenntnisse zusammentragen, damit sich mein Problem besser herauskristallisiert
