[Reader] char --> Casting notwendig, String --> nicht. Warum?

oraclin25

Erfahrenes Mitglied
Hallo zusammen,

ich habe gelernt, dass die Klasse Reader, InputStream bzw. generell der Lesevorgang unter Java immer per 2 bytes erfolgt. Daher beim Lesen eines Zeichens immer gecastet werden muss(da die meisten Rechner ein Zeichen noch mit 8 bits speichern):
Code:
(char) var = varin.read();

Nun habe ich folgendes Beispiel gefunden, wo nicht gecastet werden muss:

Code:
String sCurrentLine;
 
br = new BufferedReader(new FileReader("C:\\testing.txt"));
 
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);

Gut, hier ist die Ausgangssituation etwas anderes:
1. Statt char wird das Leseergebnis in einen String abgespeichert
2. Hier gehts nicht ums Lesen eines einzigen Zeichens sondern einer ganzen Zeile

Ich würde gerne verstehen, wie der Lesevorgang unter der Haube bitweise funktioniert. Könnte mir jemand aufklären? Vielen Dank.

Schöne Grüße aus Rheinland,

Eure Ratna:D
 
Hi

ich habe gelernt, dass die Klasse Reader, InputStream bzw. generell der Lesevorgang unter Java immer per 2 bytes erfolgt. Daher beim Lesen eines Zeichens immer gecastet werden muss(da die meisten Rechner ein Zeichen noch mit 8 bits speichern):
Code:
(char) var = varin.read();
Sorry, aber da ist ca. alles falsch.

Wenn man "normale" Rechner wie unsere anschaut ist ein Byte nicht nur meistens,
sondern immer genau 8 bit. Es gibt auch keine ernsthaften Absichten,
daran irgendwas zu ändern.

Ob ein Zeichen ein oder mehrere Byte braucht hängt vom verwendeten Zeichensatz ab
(siehe anderen Beitrag...)
Da kann jeder unserer Rechner viele Möglichkeiten, je nach dem, was man da programmiert.

Dass in Java immer zwei Byte gelesen werden ist totaler Quatsch.
Wenn das im Code ein Inputstream ist liest das genau ein Byte,
nicht mehr und nicht weniger.
Eine Zahl 0-255, die beliebig in chars, ints oÄ. gespeichert werden kann.

Was allerdings zwei Byte hat ist eine char-Variable, kann also auch höhere Zahlen speichern.
Grund: Java verwendet für Stringvariablen (und eben auch Einzelbuchstaben)
einen Zeichensatz, der je nach Zeichen zwei oder vier Byte verwendet
(ein/zwei chars hier, "UTF16"). (Grund Internationalisierung, siehe anderen Beitrag).
Man kann char trotzdem als Speicher für ein Byte verwenden, ist das andere eben sinnlos.

Wenn man mit dem Reader etc. wirklich Text statt Byte einlesen will
kann man angeben, welchen Zeichensatz die Datei hat (das muss man wissen,
sonst evt. etwas Raterei händisch).
Wenns UTF16 ist und damit zum Javastring passt wirds einfach 1:1 byteweise reinkopiert.
Wenn nicht wirds zuerst in UTF16 umgewandelt (dafür ist der Reader eben gut).

Zum Cast noch:
a) der ist syntaktisch falsch, castet also gar nichts. Bringt bestenfalls Compilerfehler
b) und ist sinnlos, da Java das sowieso macht.
Du willst etwas zw. 0-255 in etwas zw. 0-65535 (zwei Byte) speichern.
Dabei gibts überhaupt kein Problem.

Umgekehrt könnte es zum Problem werden.
zB. die Zahl 3 ist bei 0-65535 3 und auch bei 0-255 3.
aber sowas wie 1000 ist bei 0-65535 1000 und bei 0-255...genau, passt nicht rein.
Ergebnis ist dann irgendeine andere Zahl (berechenbar, aber nicht 1000).
Deswegen würde Java bei sowas warnen bzw. Fehler melden.
Mit einem extra hingeschriebenen Cast sagst du dem Compiler, dass du das wirklich willst
und die über den eventuellen Zahlenverlust im Klaren bist.

Aber, wie gesagt, machst du es ja in der problemfreien Richtung, also kein Cast nötig.
Und wenn man unbedingt einen will, dann bitte korrekt.
Java:
var = (char) varin.read();

Nun habe ich folgendes Beispiel gefunden, wo nicht gecastet werden muss:

Code:
String sCurrentLine;
 
br = new BufferedReader(new FileReader("C:\\testing.txt"));
 
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);

Gut, hier ist die Ausgangssituation etwas anderes:
1. Statt char wird das Leseergebnis in einen String abgespeichert
2. Hier gehts nicht ums Lesen eines einzigen Zeichens sondern einer ganzen Zeile

Ich würde gerne verstehen, wie der Lesevorgang unter der Haube bitweise funktioniert. Könnte mir jemand aufklären? Vielen Dank.
Wie oben geschrieben, das hängt vom Zeichensatz, der in der Datei verwendet ist, ab.
(bzw. was man dem Reader sagt, was der Dateizeichensatz ist. Man kann auch Falschangaben
machen, bringt dann nur evt. keinen vernünftigen Text mehr.
Oder vllt. auch gröbere Fehler, wenn laut Zeichensatz und Dateinhalt
noch zwei Byte sein müssten, der Reader aber schon am Dateiende steht etc.)

Wenn man keinen Zeichensatz extra angibt dürfte es auch UTF16 sein.
 
Hi.
Sorry, aber da ist ca. alles falsch.
Na so ganz komplett falsch würde ich nicht sagen.
Ob ein Zeichen ein oder mehrere Byte braucht hängt vom verwendeten Zeichensatz ab
Nicht in Java. In Java ist ein char (sprich: Zeichen) immer 2 Bytes groß.

Grund: Java verwendet für Stringvariablen (und eben auch Einzelbuchstaben) einen Zeichensatz, der je nach Zeichen zwei oder vier Byte verwendet
Nein, UTF-16 bedeutet jedes Zeichen ist 16 Bit groß.
Wenn man mit dem Reader etc. wirklich Text statt Byte einlesen will
Das ist gerade der Unterschied:

Ein Stream verarbeitet Bytes.

Ein Reader verarbeitet Zeichen.

(du hast dich etwas missverständlich ausgedrückt, bei dir klang es so, als ob man sich aussuchen könnte ob man Text oder Bytes mit einem Reader verarbeitet)
b) und ist sinnlos, da Java das sowieso macht.
Du willst etwas zw. 0-255 in etwas zw. 0-65535 (zwei Byte) speichern.
Dabei gibts überhaupt kein Problem.
Irrtum, es ist ein Cast notwendig:
Code:
Foo.java:13: error: possible loss of precision
                char c = i;
                         ^
  required: char
  found:    int
1 error
Und wenn man unbedingt einen will, dann bitte korrekt.
Java:
var = (char) varin.read();
Die Reader.read() Methode gibt aber ein int zurück, keinen char.

Diesen int sollte man erstmal prüfen, ob diese -1 ist (EOF). Falls nicht, kann man den Wert in einen char casten bzw. speichern.

Korrekt wäre:
Java:
int ic = varin.read();

if (ic != -1) {
  char c = (char)ic;
} else {
  // EOF
}
Wenn man keinen Zeichensatz extra angibt dürfte es auch UTF16 sein.
Nein, es wird dann das (plattformabhängige) Encoding verwendet.
Java:
Charset.defaultCharset().name();
 
Zuletzt bearbeitet:
Hallo deepthroat und sheel,

vielen Dank für Eure Hilfestellungen. Ich bin froh, dass ich jetzt (hoffentlich richtig) verstanden habe:
1. Gelesen wird von einem InputStream immer ein Byte
2. Da unter Java ein char in 16 Bits gespeichert wird, ist der Cast notwendig
3. Ich habe mich verschrieben, richtig wäre gewesen:
Code:
char var;
(char) var = varin.read();

Meine Ursprungsfrage bezieht sich eigentlich auf String:
Aber ich nehme an, bei String braucht man nicht zu casten, da die Ausgabe von readLine() den Datentyp String hat. Falls dies nicht richtig, bitte um Korrektur. Vielen Dank.

Schöne Grüße aus Rheinland,

Eure Ratna
 
@sheel: Leider hat oraclin ja nicht gesagt was varin eigentlich ist. Falls es ein Reader ist, dann hab ich Recht. Falls es ein Stream ist, dann liegst du richtig. Da fehlt mal wieder der Kontext - ist immer ein Fehler da allzuviel hineinzuinterpretieren... :)

Meine Ursprungsfrage bezieht sich eigentlich auf String
Ein String ist eine Folge von Zeichen. Da stellt sich die Frage nach dem Casten überhaupt nicht, da offenbar die Bytes schon intern in Zeichen umgewandelt wurden woraus dann der String erzeugt wurde.
 
Nicht in Java. In Java ist ein char (sprich: Zeichen) immer 2 Bytes groß.
Da könnte man diskutieren...
Java-char sind schon zwei Byte, aber ob ein "Zeichen" im "Zeichensatz"
1/2/4...Byte braucht ist doch ein Unterschied.
Java war erst im nächsten Absatz überhaupt ein Thema,
zuerst gings um Bytegrößen auf Rechnern.

Nein, UTF-16 bedeutet jedes Zeichen ist 16 Bit groß.
Bin ja nicht so der Spezifikationenleser (hol ich für den Fall noch nach),
aber an dem hier wird wohl irgendwas dran sein?
"pairs of 16-bit code units"
edit: http://www.ietf.org/rfc/rfc2781.txt Teil 2.1
 
Da könnte man diskutieren...
Java-char sind schon zwei Byte, aber ob ein "Zeichen" im "Zeichensatz"
1/2/4...Byte braucht ist doch ein Unterschied.
Java war erst im nächsten Absatz überhaupt ein Thema,
zuerst gings um Bytegrößen auf Rechnern.
Ja, du bist etwas vom Thema abgewichen. oraclin ging es sicherlich nur um "Java Zeichen", sprich: den Typ char.
Bin ja nicht so der Spezifikationenleser (hol ich für den Fall noch nach),
aber an dem hier wird wohl irgendwas dran sein?
"pairs of 16-bit code units"
edit: http://www.ietf.org/rfc/rfc2781.txt Teil 2.1
OK, du hast recht, da muß ich mal mein festgefahrenes UTF-16 Modell in cerebri erneuern... Danke!
 

Neue Beiträge

Zurück