FileOutputStream write

  • Themenstarter Themenstarter Jessy12
  • Beginndatum Beginndatum
J

Jessy12

Gast
Java:
package wahlfreierZugriff;

import java.io.*;
import java.util.Arrays;

public class Testen {
	public static void main(String[] args) throws Exception {
		String datei = "C:/users/jessy/desktop/java/last.txt";
		FileOutputStream wrt = new FileOutputStream(datei);
		wrt.write('A');
	}
}

Hallo, ich hffe jemand kann mir klar machen, warum das hier funktionieren muss. Die write-Methode hat doch als Parameter gar keinen char aber warum meckert der Compiler dann nicht? Des Weiteren, welchen Sinn macht write(int i), wenn doch eh nur die ersten 8 bit ausgelesen werden... Danke im Voraus 🙂
 
Zuletzt bearbeitet von einem Moderator:
das geht weil auch
int x = 'A';
geht

und int als Parameter ist meiner Vermutung nach performanter im 32bit-Java (mit passenden Restprogramm),
und spart auch nervige Casts auf byte

ohne close() wird übrigens evtl. nichts gespeichert
 
- 'A' ist vom typ char und der lässt sich zu int upcasten. Deswegen meckert der Compiler nicht.
- write(int i) ist von der Oberklasse OutputStream vorgeschrieben und es werden tatsächlich nur die 8 low-order Bits gelesen. Was sich die JDK-Entwickler dabei gedacht haben? Keine Ahnung.
 
Hallo,
In dem Falle wird ein char in int gecastet, weil ein char eigentlich eine Zahl ist. Aber umgekehrt brauchst ein cast, weil ein char weniger bits hat als ein int. Mit dem char du kannst mit chars genau dasselbe machen wie mit ints. Sowie
Java:
'a'++;
ist erlaubt.
Gruß,
Freak
 
Danke 🙂

Noch eine letzte Frage: Auch wenn ich sagen wir mal die Zahl 40 reinschreibe, so wird in der Textdatei nur das entsprechende ASCII-Zeichen angezeigt. Ich könnte das natürlich auch mit einem PrintStream lösen aber mich würde interessieren, wie es dazu kommt, dass eine 40 in der Textdatei übersetzt wird 🙂
 
Ich verstehe das mit der Kodierung nicht ganz. Wer sagt der Textdatei dass es eine A ist und keine 65
 
Ein FileReader liest 16 Bit und ein FileInputStream 8 bit. Das ist ja der einzige Unterschied. Trotzdem lesen beide immer nur ein Zeichen. Warum liest der Reader dann nicht gleich zwei Zeichen??
 
Sowie
Java:
'a'++;
ist erlaubt.
Es ist zwar klar, was gemeint ist, aber genau so etwas geht nicht. ++ und -- dürfen/können nicht auf Konstanten angewandt werden, sonst wären es nämlich keine Konstanten. 😉

Ark

EDIT:
Ein FileReader liest 16 Bit […]
Jein. Wie viele Bytes/Bits ein Reader liest, hängt vom verwendeten Zeichensatz ab. Deine Aussage ist also im Allgemeinen falsch.
[…] und ein FileInputStream 8 bit. Das ist ja der einzige Unterschied. Trotzdem lesen beide immer nur ein Zeichen. Warum liest der Reader dann nicht gleich zwei Zeichen??
Gleiche Begründung: Es hängt vom Zeichensatz ab, wie viele Bytes zu wie vielen Zeichen dekodiert werden.

Es ist aber festgelegt, dass ein Reader in einem Schritt nur ein Zeichen ausspuckt. Möglicherweise liest also der Reader zwei Bytes ein und spuckt trotzdem nur ein Zeichen aus. Vielleicht liest er aber auch nur ein Byte ein und spuckt z.B. drei Zeichen aus (durch dreimaliges Aufrufen von [c]Reader.read()[/c])! Aus nur einem Byte macht er dir dann drei Zeichen! Wie das geht? Charset magic. 😀

Ark
 
Zuletzt bearbeitet:
Beim Schreiben ist aber von Java her festgelegt wie viele Bits ich schreibe, oder? Wenn ich den falschen Zeichensatz wähle hat dann eben das Ausgabegerät Probleme mit diesem.

Beim Lesen muss ich aber vorher wissen, auf welchem Zeichensatz das Eingabegerät arbeitet und den entsprechenden Zeichensatz wählen.
 
Beim Schreiben ist aber von Java her festgelegt wie viele Bits ich schreibe, oder?
Definiere "schreiben". Wenn du so was meinst wie "in eine Datei schreiben": Dafür kann man z.B. einen FileOutputStream verwenden. In diesen gibt man die zu schreibenden Informationen byteweise ein, ja. Aber das liegt jetzt nicht an der Programmiersprache Java selbst, sondern an der Spezifikation der Klasse OutputStream.

Ein OutputStreamWriter ist ein spezieller Writer. Deshalb gibt man in ihn Unicode-Zeichen (und nicht etwa Bytes) ein. Ein OutputStreamWriter weiß aber selbst, welchen OutputStream er bedienen soll. Wenn du also beim OutputStreamWriter, auf UTF-8 eingestellt ist, sagst, "schreibe das Zeichen ö", dann schreibt er von sich aus in den OutputStream zwei Bytes, weil das Zeichen ö UTF-8-kodiert eben zwei Bytes benötigt. Auch hier zeigt sich: Es ist alles Definitionssache. Habe ich nun das Zeichen ö oder zwei Bytes in die Datei geschrieben?

Ark
 
noch ein letzt mal melde ich mich 🙂 Ein OutputstreamWriter dient ja dazu 2Byte große Daten in 1Byte große Daten umzuwandeln und dann an einen internen Stream weiterzugeben. Ich kann dem OutputStreamWriter aber auch sagen in welcher Codierung er die Daten weitergeben soll. Nun stellt sich mir die Frage: Wenn der OutputStreamWriter nur 1Byte große Daten an dein internen OutputStream weitergibt wieso kann ich dann die Kodierung "UTF-16" bspw. als Parameter wählen. Da stimmt doch was nicht...
 
> Ein OutputstreamWriter dient ja dazu 2Byte große Daten in 1Byte große Daten umzuwandeln
nein, wie kommst du darauf?
das mag möglich sein, etwa bei UTF-8 mit den häufigsten Zeichen,

aber dass Java an sich 2 Byte-Unicode verwendet, dass der char-Bereich bis 65.000 geht hat schon seinen Grund für all die ungewöhnlichen Zeichen,
und die brauchen dann eben mehr Platz, das kann niemand einfach so halbieren
 
Wie ist dann diese Aussasge in der Java-API zu verstehen?

An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to it are encoded into bytes using a specified charset.
 
genau auf richtige Weise, was soll ich dazu sagen?
dort steht NICHT, dass '2Byte große Daten in 1Byte große Daten umzuwandeln' sind,
was meinst du sonst so unausgesprochen? was genau ist dir nicht klar?
 
warum steht da in der API "are written into Bytes"? wenn ich ein ö mit der Einstellung UTF-8 schreibe, dann ist es doch auch wieder 2 Bytes, also ein Character groß..
 
"are written into Bytes" ist kein Teil des zuvor geschriebenen Zitats,
aber was immer du auch meinst, es gibt einfach keine exakte Vorgabe der Anzahl Bytes,

10 Chars sind 10-20 Bytes im Normalfall, in exotischen Encodings vielleicht noch ganz anders,
in der allgemein Sicht auf Streams ist es ohne Sinn dort überhaupt an Details zu denken,
aus Chars werden Bytes, fertig, das ist exakt so richtig, mehr ist nicht zu sagen

normale Sätze in Goldwaagen zu interpretieren ist eh meist gefährlich,
wenn es was genaues zu sagen gibt, dann dürfte es meist auch so exakt formuliert sein wie z.B.:

In the foregoing description, the notation sgn(expression) designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive. The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
Comparable (Java 2 Platform SE v1.4.2)
 
Ein OSW ist eine Schnittstelle zwischen Writer (chars) und Streams (binär).
Bspw. kann man ihm für textbasierende Kommunikation über Sockets verwenden. Der Socket gibt einen Input/OutputStream zurück. Wenn ein Protokoll, wie z. B. der Steuerkanal von FTP auf textbasierende Kommunikation aufbaut (3 Zahlen + [Space + "Debug-Nachricht" +] Line wrappler) kannst du so chars ganz einfach per BufferedWriter(OutputStreamWriter(socket#getOutputStream())) verschicken. Ist aber nicht soooo gebräuchlich, weil Anfänger vor allem den PrintWriter verwenden (kA warum), aber beim Lesen kannst du so noch immer ganz einfach die Chars vom Socket über einen InputStreamReader bekommen.

Auch nur daran zu denken Daten per OSW zu "komprimieren" halte ich für groben Unfug.
 
Zuletzt bearbeitet:
Ich vermute mal, das Verständnisproblem an der Stelle ist ein viel Grundsätzlicheres. Zumindest würde es mich nicht wundern, denn immerhin haben fast alle Menschen, die ich so kenne, das gleiche Problem (und das soll jetzt nicht heißen, dass ich davon verschont bliebe): Dies ist keine Pfeife.

(Es folgt ein Versuch, den Unterschied zwischen Daten und Informationen zu erklären.)

Ein Datum (lat. "Gegebenes", Plural: Daten) ist mehr oder weniger einfach da. Nehmen wir mal als Beispiel den Text, den du gerade liest. Für jemanden, der mit lateinischen Buchstaben nicht umgehen kann, ist das hier kein Text, noch weniger eine Folge lateinischer Buchstaben und noch viel weniger ist das hier für denjenigen (oder diejenige) ein deutscher Text. Zum besseren Verständnis: die meisten Deutsch-Muttersprachler sind nicht in der Lage, diese Folge von Schriftzeichen sicher der japanischen Sprache zuzuordnen, weil sie sie nicht von Chinesisch unterscheiden können. Sie können diese Schriftzeichen auch nicht richtig (mit der Hand) abschreiben, weil sie nicht wissen, worauf es ankommt. Ins Deutsche übertragen können sie es auch nicht.

Warum? Weil ihnen der richtige "Dekodierer" (decoder) fehlt: Decoder machen aus Daten Informationen, indem sie diesen Daten eine Bedeutung* geben. Menschen ohne Japanischkenntnisse können dem verlinkten Bild nicht die (vom Sender intendierte) richtige Information entlocken.

Nun zu Java & Co.: Ein InputStreamReader dekodiert eine Folge von Bytes zu einer Folge von Zeichen: eine Folge von Bits steht dann für das Zeichen A. Aber da ist kein A! Der ISR tut nur so, als hätte er gerade eines gelesen.** Information kann sich also auch z.B. durch entsprechende Reaktionen manifestieren.**

Wenn wir aber Information speichern oder übertragen wollen, müssen wir sie anders greifbar machen. Dies passiert z.B. im Rechner dadurch, dass bestimmte Stromflüsse geändert werden, die wiederum als 0 bzw. 1 interpretiert werden. Nun haben wir aber nicht unendlich viel Platz dafür, also begnügen wir uns mit nur wenigen Bits: das gelesene A überträgt der ISR an den Aufrufer, indem er es wieder als int kodiert(!) an ihn zurückgibt (er macht aus der Information "Zeichen A" wieder ein Datum).

Aber woher wissen wir, dass das, was der Reader zurückgibt, in diesem Fall für den Buchstaben A steht, und nicht für etwas anderes? Weil es für die read()-Methode so definiert wurde! Man hat sich gewissermaßen darauf geeinigt, dass das, was der Reader ausspuckt, als Unicode-Zeichen zu verstehen ist. Man hat sich auch darauf geeinigt, dass die 16 Bits in einem char als Unicode-Zeichen zu deuten sind. Im Gegensatz dazu werden die 16 Bits in einem short als Ganzzahl in Zweierkomplement-Darstellung gedeutet. Dass man mit chars rechnen kann, liegt nur daran, dass z.B. bei der Addition die 16 Bits des chars als natürliche Zahl gedeutet werden.

Es ist alles eine Sache der Definition, Interpretation usw. 😉

Ark

*: Gibt es für die Stelle ein besseres Wort?
**: Es ist schwierig bis unmöglich, dies wirklich "richtig" zu erklären. Ein Zen-Meister kann das wahrscheinlich besser als ich. 😀
 

Neue Themen


Zurück
Oben