1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
|
<html>
<head>
<title>
Handbuch der Java-Programmierung, 5. Auflage
</title>
</head>
<body>
<a name="startofbody"></a>
<script language="JavaScript" src="hjp4lib.js">
</script>
<script language="JavaScript">
installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100125.html;106,k100126.html;107,k100128.html;108,k100130.html");
</script>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100125.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100126.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100128.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100130.html"> >> </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
<td align="right">Kapitel 19 - Byte-Streams
</table>
<hr>
<!-- Section -->
<a name="sectlevel2id019002"></a>
<h2>19.2 Ausgabe-Streams </h2>
<hr>
<ul>
<li><a href="k100127.html#sectlevel2id019002">19.2 Ausgabe-Streams</a>
<ul>
<li><a href="k100127.html#sectlevel3id019002001">19.2.1 Die Basisklasse OutputStream</a>
<li><a href="k100127.html#sectlevel3id019002002">19.2.2 Aus OutputStream direkt abgeleitete Klassen</a>
<ul>
<li><a href="k100127.html#sectlevel4id019002002001">FileOutputStream</a>
<li><a href="k100127.html#sectlevel4id019002002002">ByteArrayOutputStream</a>
<li><a href="k100127.html#sectlevel4id019002002003">ObjectOutputStream</a>
<li><a href="k100127.html#sectlevel4id019002002004">PipedOutputStream</a>
</ul>
<li><a href="k100127.html#filteroutputstream">19.2.3 Aus FilterOutputStream abgeleitete Klassen</a>
<ul>
<li><a href="k100127.html#sectlevel4id019002003001">BufferedOutputStream</a>
<li><a href="k100127.html#sectlevel4id019002003002">PrintStream</a>
<li><a href="k100127.html#sectlevel4id019002003003">DataOutput und DataOutputStream</a>
<li><a href="k100127.html#sectlevel4id019002003004">Komprimieren von Dateien</a>
<li><a href="k100127.html#sectlevel4id019002003005">Berechnung von Prüfsummen</a>
</ul>
</ul>
</ul>
<hr>
<!-- Section -->
<a name="sectlevel3id019002001"></a>
<h3>19.2.1 Die Basisklasse OutputStream </h3>
<p>
Basis der Ausgabe-Streams ist die abstrakte Klasse <a name="ixa101321"><a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a></a>.
Sie stellt folgende Methoden zur Verfügung:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
protected OutputStream()
public void close()
public void flush()
public void write(int b)
public void write(byte[] b)
public void write(byte[] b, int offs, int len)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/OutputStream.html" onClick="this.href=getApiDoc('java.io.OutputStream')"><font color="#660066" size=-1>java.io.OutputStream</font></a></td>
</tr>
</table>
<p>
Der parameterlose Konstruktor initialisiert einen <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>.
Er ist <a href="index_p.html#ixb100086"><font color=#000080><tt>protected</tt></font></a>
und wird in abgeleiteten Klassen überlagert. Mit <a name="ixa101322"><a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a></a>
wird der <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>
geschlossen, und <a name="ixa101323"><a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a></a>
schreibt die gepufferten Daten physikalisch auf das Ausgabegerät
und leert alle Puffer.
<p>
Die <a name="ixa101324"><a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a></a>-Methoden
erwarten Bytes oder Byte-Arrays als Daten. Wird ein <a href="index_b.html#ixb100242"><font color=#000080><tt>byte</tt></font></a>-Array
angegeben, so gibt die Klasse es vollständig aus, wenn nicht
zusätzlich ein Arrayoffset und die Anzahl der zu schreibenden
Bytes angegeben wird. Die Methode zum Schreiben eines einzelnen Bytes
erwartet ein <a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>
als Argument, gibt aber lediglich seine unteren 8 Bit aus und ignoriert
alle übrigen.
<!-- Section -->
<a name="sectlevel3id019002002"></a>
<h3>19.2.2 Aus OutputStream direkt abgeleitete Klassen </h3>
<p>
Aus <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>
sind einige weitere Klassen direkt abgeleitet. Wie bei den Character-Streams
bestimmen sie im wesentlichen die Art bzw. das Ziel der Datenausgabe.
<!-- Section -->
<a name="sectlevel4id019002002001"></a>
<h4>FileOutputStream </h4>
<p>
Der <a name="ixa101325"><a href="index_f.html#ixb101005"><font color=#000080><tt>FileOutputStream</tt></font></a></a>
stellt einen Byte-Stream zur Ausgabe in eine Datei zur Verfügung.
Er besitzt folgende Konstruktoren:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public FileOutputStream(String name)
throws FileNotFoundException
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
public FileOutputStream(File file)
throws IOException
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/FileOutputStream.html" onClick="this.href=getApiDoc('java.io.FileOutputStream')"><font color="#660066" size=-1>java.io.FileOutputStream</font></a></td>
</tr>
</table>
<p>
Wird lediglich ein Dateiname angegeben, legt ein <a href="index_f.html#ixb101005"><font color=#000080><tt>FileOutputStream</tt></font></a>
die gewünschte Ausgabedatei neu an und setzt den Dateizeiger
auf den Anfang der Datei. Wird der zweite Konstruktor verwendet und
<a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
als zweites Argument übergeben, wird der Dateizeiger auf das
Ende der Datei positioniert, falls diese bereits existiert. Andernfalls
entspricht das Verhalten dem des ersten Konstruktors. Der dritte Konstruktor
entspricht dem ersten, erwartet aber ein <a href="index_f.html#ixb100973"><font color=#000080><tt>File</tt></font></a>-Objekt
anstelle eines Strings.
<p>
Das folgende Programm zeigt beispielhaft die Anwendung eines <a href="index_f.html#ixb101005"><font color=#000080><tt>FileOutputStream</tt></font></a>.
Es legt die in der Kommandozeile angegebene Datei an (bzw. springt
zu ihrem Ende, falls sie bereits vorhanden ist) und hängt 256
Bytes mit den Werten 0 bis 255 an.
<a name="listingid019001"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* Listing1901.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
<font color="#555555">004 </font>
<font color="#555555">005 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing1901
<font color="#555555">006 </font>{
<font color="#555555">007 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">008 </font> {
<font color="#555555">009 </font> <font color="#0000AA">try</font> {
<font color="#555555">010 </font> FileOutputStream out = <font color="#0000AA">new</font> FileOutputStream(
<font color="#555555">011 </font> args[0],
<font color="#555555">012 </font> <font color="#006699">true</font>
<font color="#555555">013 </font> );
<font color="#555555">014 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < 256; ++i) {
<font color="#555555">015 </font> out.write(i);
<font color="#555555">016 </font> }
<font color="#555555">017 </font> out.close();
<font color="#555555">018 </font> } <font color="#0000AA">catch</font> (Exception e) {
<font color="#555555">019 </font> System.err.println(e.toString());
<font color="#555555">020 </font> System.exit(1);
<font color="#555555">021 </font> }
<font color="#555555">022 </font> }
<font color="#555555">023 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1901.java"><font color="#000055" size=-1>Listing1901.java</font></a></td>
</tr>
</table>
<i>
Listing 19.1: Verwendung eines FileOutputStream</i></p>
<!-- Section -->
<a name="sectlevel4id019002002002"></a>
<h4>ByteArrayOutputStream </h4>
<p>
Die Klasse <a name="ixa101326"><a href="index_b.html#ixb101006"><font color=#000080><tt>ByteArrayOutputStream</tt></font></a></a>
schreibt die auszugebenden Daten in ein <a href="index_b.html#ixb100242"><font color=#000080><tt>byte</tt></font></a>-Array,
dessen Größe mit dem Datenvolumen wächst. Sie besitzt
zwei Konstruktoren:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public ByteArrayOutputStream()
public ByteArrayOutputStream(int size)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/ByteArrayOutputStream.html" onClick="this.href=getApiDoc('java.io.ByteArrayOutputStream')"><font color="#660066" size=-1>java.io.ByteArrayOutputStream</font></a></td>
</tr>
</table>
<p>
Der parameterlose Konstruktor legt ein Ausgabearray mit einer anfänglichen
Größe von 32 Byte an, der andere erlaubt die freie Vorgabe
der initialen Puffergröße.
<!-- Section -->
<a name="sectlevel4id019002002003"></a>
<h4>ObjectOutputStream </h4>
<p>
Ein <a name="ixa101327"><a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a></a>
erlaubt es, primitive Datentypen und komplette Objekte (inklusive
aller referenzierten Objekte) auszugeben. Zwar ist er nicht von <a href="index_f.html#ixb101008"><font color=#000080><tt>FilterOutputStream</tt></font></a>
abgeleitet, wird aber ebenso verwendet und erwartet im Konstruktor
einen <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>
zur Weiterleitung der Ausgabedaten. Die Klasse <a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a>
ist eine der Säulen des Serialisierungs-APIs in Java. Sie wird
in <a href="k100261.html#objectoutputstream">Abschnitt 41.1.2</a>
ausführlich beschrieben.
<!-- Section -->
<a name="sectlevel4id019002002004"></a>
<h4>PipedOutputStream </h4>
<p>
Ein <a name="ixa101328"><a href="index_p.html#ixb100970"><font color=#000080><tt>PipedOutputStream</tt></font></a></a>
dient zusammen mit einem <a href="index_p.html#ixb100969"><font color=#000080><tt>PipedInputStream</tt></font></a>
zur Kommunikation zweier Threads. Beide zusammen implementieren eine
<a name="ixa101329"><i>Message Queue</i></a>, in die einer der beiden
Threads seine Daten hineinschreibt, während der andere sie daraus
liest. Ein ausführliches Beispiel zur Anwendung der beiden Klassen
findet sich in <a href="k100147.html#pipedthreads">Abschnitt 22.4.4</a>.
<!-- Section -->
<a name="filteroutputstream"></a>
<h3>19.2.3 Aus FilterOutputStream abgeleitete Klassen </h3>
<p>
Die aus <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>
abgeleitete Klasse <a name="ixa101330"><a href="index_f.html#ixb101008"><font color=#000080><tt>FilterOutputStream</tt></font></a></a>
ist die Basisklasse aller gefilterten Ausgabe-Streams. Diese definieren
kein eigenes Ausgabegerät, sondern bekommen es beim Instanzieren
in Form eines <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>-Arguments
übergeben:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public FilterOutputStream(OutputStream out)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/FilterOutputStream.html" onClick="this.href=getApiDoc('java.io.FilterOutputStream')"><font color="#660066" size=-1>java.io.FilterOutputStream</font></a></td>
</tr>
</table>
<p>
Die Aufgabe der aus <a href="index_f.html#ixb101008"><font color=#000080><tt>FilterOutputStream</tt></font></a>
abgeleiteten Klassen besteht darin, die Schreibzugriffe abzufangen,
in einer für sie charakteristischen Weise zu verarbeiten und
dann an das eigentliche Ausgabegerät (den im Konstruktor übergebenen
<a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>)
weiterzuleiten.
<!-- Section -->
<a name="sectlevel4id019002003001"></a>
<h4>BufferedOutputStream </h4>
<p>
<a name="ixa101331"><a href="index_b.html#ixb101010"><font color=#000080><tt>BufferedOutputStream</tt></font></a></a>
puffert die Ausgabe in einen <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>.
Er kann insbesondere dann die Ausgabe beschleunigen, wenn viele einzelne
<a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Aufrufe
erfolgen, die jeweils nur wenig Daten übergeben. Ein <a href="index_b.html#ixb101010"><font color=#000080><tt>BufferedOutputStream</tt></font></a>
besitzt zwei zusätzliche Konstruktoren und eine Methode <a name="ixa101332"><a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a></a>,
die dafür sorgt, dass die gepufferten Daten tatsächlich
geschrieben werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out, int size)
public void flush()
throws IOException
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/BufferedOutputStream.html" onClick="this.href=getApiDoc('java.io.BufferedOutputStream')"><font color="#660066" size=-1>java.io.BufferedOutputStream</font></a></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel4id019002003002"></a>
<h4>PrintStream </h4>
<p>
Ein <a name="ixa101333"><a href="index_p.html#ixb100114"><font color=#000080><tt>PrintStream</tt></font></a></a>
bietet die Möglichkeit, Strings und primitive Typen im Textformat
auszugeben. Er stellt eine Vielzahl von <a name="ixa101334"><a href="index_p.html#ixb100922"><font color=#000080><tt>print</tt></font></a></a>-
und <a name="ixa101335"><a href="index_p.html#ixb100555"><font color=#000080><tt>println</tt></font></a></a>-Methoden
für unterschiedliche Datentypen zur Verfügung. Seine Schnittstelle
und Anwendung entspricht der Klasse <a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>,
die in <a href="k100122.html#charausgabestreamsschachteln">Abschnitt 18.2.3</a>
beschrieben wurde.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Im Zuge der Internationalisierung des JDK wurden mit der Version 1.1
die öffentlichen Konstruktoren der Klasse <a href="index_p.html#ixb100114"><font color=#000080><tt>PrintStream</tt></font></a>
als <a name="ixa101336"><a href="index_d.html#ixb100161"><font color=#000080><tt>deprecated</tt></font></a></a>
markiert (wegen der möglicherweise unzulänglichen Konvertierung
zwischen Bytes und Zeichen). Damit war die Klasse praktisch nicht
mehr verwendbar. Insbesondere war es nicht mehr möglich, die
Methoden <a name="ixa101337"><a href="index_s.html#ixb100850"><font color=#000080><tt>setOut</tt></font></a></a>
und <a name="ixa101338"><a href="index_s.html#ixb100851"><font color=#000080><tt>setErr</tt></font></a></a>
der Klasse <a href="index_s.html#ixb100435"><font color=#000080><tt>System</tt></font></a>
sinnvoll zu verwenden (siehe <a href="k100110.html#inerrout">Abschnitt 16.3.2</a>).
Später wurde die Entscheidung als falsch angesehen und mit dem
JDK 1.2 revidiert. Seither sind die Konstruktoren wieder zulässig.
Einen einfach anzuwendenden Workaround, der die <a href="index_d.html#ixb100161"><font color=#000080><tt>deprecated</tt></font></a>-Warnungen
im JDK 1.1 vermeidet, gibt es leider nicht.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#FF9900">
<tr>
<td><font color="#FFFFFF"> JDK1.1-6.0 </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel4id019002003003"></a>
<h4>DataOutput und DataOutputStream </h4>
<p>
Ein <a name="ixa101339"><a href="index_d.html#ixb101011"><font color=#000080><tt>DataOutputStream</tt></font></a></a>
ermöglicht es, primitive Datentypen in definierter (und portabler)
Weise auszugeben. So geschriebene Daten können mit Hilfe eines
<a name="ixa101340"><a href="index_d.html#ixb101012"><font color=#000080><tt>DataInputStream</tt></font></a></a>
wieder eingelesen werden. Ein <a href="index_d.html#ixb101011"><font color=#000080><tt>DataOutputStream</tt></font></a>
implementiert das Interface <a name="ixa101341"><a href="index_d.html#ixb101013"><font color=#000080><tt>DataOutput</tt></font></a></a>,
das folgende Methoden enthält:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
void write(int b)
throws IOException
void write(byte[] b)
throws IOException
void write(byte[] b, int off, int len)
throws IOException
void writeBoolean(boolean v)
throws IOException
void writeByte(int v)
throws IOException
void writeShort(int v)
throws IOException
void writeChar(int v)
throws IOException
void writeInt(int v)
throws IOException
void writeLong(long v)
throws IOException
void writeFloat(float v)
throws IOException
void writeDouble(double v)
throws IOException
void writeBytes(String s)
throws IOException
void writeChars(String s)
throws IOException
void writeUTF(String str)
throws IOException
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/DataOutput.html" onClick="this.href=getApiDoc('java.io.DataOutput')"><font color="#660066" size=-1>java.io.DataOutput</font></a></td>
</tr>
</table>
<p>
Zu jeder einzelnen Methode ist in der JDK-Dokumentation genau angegeben,
auf welche Weise der jeweilige Datentyp ausgegeben wird. Dadurch ist
garantiert, dass eine mit <a href="index_d.html#ixb101011"><font color=#000080><tt>DataOutputStream</tt></font></a>
geschriebene Datei auf jedem anderen Java-System mit einem <a href="index_d.html#ixb101012"><font color=#000080><tt>DataInputStream</tt></font></a>
lesbar ist. Die Beschreibungen sind sogar so genau, dass Interoperabilität
mit Nicht-Java-Systemen erreicht werden kann, wenn diese in der Lage
sind, die primitiven Typen in der beschriebenen Weise zu verarbeiten.
<p>
Eine Sonderstellung nimmt die Methode <a name="ixa101342"><a href="index_w.html#ixb101014"><font color=#000080><tt>writeUTF</tt></font></a></a>
ein. Sie dient dazu, die 2 Byte langen UNICODE-Zeichen, mit denen
Java intern arbeitet, in definierter Weise in 1, 2 oder 3 Byte lange
Einzelzeichen zu verwandeln. Hat das Zeichen einen Wert zwischen \u0000
und \u007F, wird es als Einzelbyte ausgeben. Hat es einen Wert zwischen
\u0080 und \u07FF, belegt es zwei Byte, und in allen anderen Fällen
werden drei Byte verwendet. Diese Darstellung wird als <a name="ixa101343"><i>UTF-8-Codierung</i></a>
bezeichnet und ist entsprechend <a href="k100127.html#utf8encoding">Tabelle 19.1</a>
implementiert. Zusätzlich werden an den Anfang jedes UTF-8-Strings
zwei Längenbytes geschrieben. <a name="utf8encoding"></a>
<p>
<table cols=4 border width=100%>
<tr>
<td valign=top align=left width=16%><b>Von</b></td>
<td valign=top align=left width=16%><b>Bis</b></td>
<td valign=top align=left width=16%><b>Byte</b></td>
<td valign=top align=left width=50%><b>Darstellung </b></td></tr>
<tr>
<td valign=top align=left>\u0000</td>
<td valign=top align=left>\u007F</td>
<td valign=top align=left>1</td>
<td valign=top align=left>0nnnnnnn </td></tr>
<tr>
<td valign=top align=left>\u0080</td>
<td valign=top align=left>\u07FF</td>
<td valign=top align=left>2</td>
<td valign=top align=left>110nnnnn 10nnnnnn </td></tr>
<tr>
<td valign=top align=left>\u0800</td>
<td valign=top align=left>\uFFFF</td>
<td valign=top align=left>3</td>
<td valign=top align=left>1110nnnn 10nnnnnn 10nnnnnn </td></tr>
</table>
<p><i>
Tabelle 19.1: Die UTF-8-Kodierung </i></p>
<p>
Die UTF-8-Kodierung arbeitet bei den gebräuchlichsten Sprachen
platzsparend. Alle ASCII-Zeichen werden mit nur einem Byte codiert,
und viele andere wichtige Zeichen (insbesondere die im ISO-8859-Zeichensatz
definierten nationalen Sonderzeichen, aber auch griechische, hebräische
und kyrillische Zeichen), benötigen nur zwei Byte zur Darstellung.
Jedes Byte mit gesetztem High-Bit ist Teil einer Multibyte-Sequenz
und am ersten Byte einer Sequenz kann die Anzahl der Folgezeichen
abgelesen werden.
<p>
Wir wollen uns ein Beispielprogramm ansehen:
<a name="dataoutputstreamexample"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* Listing1902.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
<font color="#555555">004 </font>
<font color="#555555">005 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing1902
<font color="#555555">006 </font>{
<font color="#555555">007 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">008 </font> {
<font color="#555555">009 </font> <font color="#0000AA">try</font> {
<font color="#555555">010 </font> DataOutputStream out = <font color="#0000AA">new</font> DataOutputStream(
<font color="#555555">011 </font> <font color="#0000AA">new</font> BufferedOutputStream(
<font color="#555555">012 </font> <font color="#0000AA">new</font> FileOutputStream(<font color="#0000FF">"test.txt"</font>)));
<font color="#555555">013 </font> out.writeInt(1);
<font color="#555555">014 </font> out.writeInt(-1);
<font color="#555555">015 </font> out.writeDouble(Math.PI);
<font color="#555555">016 </font> out.writeUTF(<font color="#0000FF">"häßliches"</font>);
<font color="#555555">017 </font> out.writeUTF(<font color="#0000FF">"Entlein"</font>);
<font color="#555555">018 </font> out.close();
<font color="#555555">019 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">020 </font> System.err.println(e.toString());
<font color="#555555">021 </font> }
<font color="#555555">022 </font> }
<font color="#555555">023 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1902.java"><font color="#000055" size=-1>Listing1902.java</font></a></td>
</tr>
</table>
<i>
Listing 19.2: Verwendung der Klasse DataOutputStream</i></p>
<p>
Das Programm erzeugt eine Ausgabedatei <font color="#660099">test.txt</font>
von 38 Byte Länge (wie sie wieder eingelesen wird, zeigt <a href="k100128.html#datainputstreamexample">Listing 19.5</a>):
<font color="#333300">
<pre>
00 00 00 01 FF FF FF FF-40 09 21 FB 54 44 2D 18 ........@.!.TD-.
00 0B 68 C3 A4 C3 9F 6C-69 63 68 65 73 00 07 45 ..h....liches..E
6E 74 6C 65 69 6E ntlein
</pre>
</font>
<ul>
<li>Die ersten 4 Byte stellen den int-Wert 1 dar.
<li>Die nächsten 4 Byte repräsentieren die -1 (es wird die
übliche Zweierkomplementdarstellung verwendet).
<li>Anschließend folgen 8 Byte mit der double-Darstellung der
Zahl pi.
<li>Nun folgt die Längeninformation 000B des ersten UTF-8-Strings
und danach dessen 11 Zeichen. Man kann sehen, dass die beiden Umlaute
ä und ß jeweils zwei Byte belegen, alle übrigen Zeichen
jedoch nur eines.
<li>Schließlich folgt der zweite UTF-8-String. Er hat die Länge
7, und alle Zeichen werden mit einem Byte dargestellt.
</ul>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
<a href="index_d.html#ixb101013"><font color=#000080><tt>DataOutput</tt></font></a>
wird nicht nur von <a href="index_d.html#ixb101011"><font color=#000080><tt>DataOutputStream</tt></font></a>
implementiert, sondern auch von der Klasse <a name="ixa101344"><a href="index_r.html#ixb101016"><font color=#000080><tt>RandomAccessFile</tt></font></a></a>,
die darüber hinaus das Interface <a href="index_d.html#ixb101017"><font color=#000080><tt>DataInput</tt></font></a>
implementiert. Sollen primitive Daten wahlweise seriell oder wahlfrei
verarbeitet werden, ist es daher sinnvoll, die serielle Verarbeitung
mit Hilfe der Klassen <a href="index_d.html#ixb101011"><font color=#000080><tt>DataOutputStream</tt></font></a>
und <a href="index_d.html#ixb101012"><font color=#000080><tt>DataInputStream</tt></font></a>
vorzunehmen. Die Verarbeitung von Random-Access-Dateien wird in <a href="k100130.html#kapitelrandomaccessio">Kapitel 20</a>
behandelt.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#0099CC">
<tr>
<td><font color="#FFFFFF"> Tipp </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel4id019002003004"></a>
<h4>Komprimieren von Dateien </h4>
<p>
Die aus <a href="index_f.html#ixb101008"><font color=#000080><tt>FilterOutputStream</tt></font></a>
abgeleitete Klasse <a name="ixa101345"><a href="index_d.html#ixb101018"><font color=#000080><tt>DeflaterOutputStream</tt></font></a></a>
ist die Basisklasse der beiden Klassen <a name="ixa101346"><a href="index_z.html#ixb101019"><font color=#000080><tt>ZipOutputStream</tt></font></a></a>
und <a name="ixa101347"><a href="index_g.html#ixb101020"><font color=#000080><tt>GZIPOutputStream</tt></font></a></a>
aus dem Paket <a name="ixa101348"><a href="index_j.html#ixb101021"><font color=#000080><tt>java.util.zip</tt></font></a></a>.
Zudem ist <a href="index_z.html#ixb101019"><font color=#000080><tt>ZipOutputStream</tt></font></a>
Basisklasse von <a name="ixa101349"><a href="index_j.html#ixb101022"><font color=#000080><tt>JarOutputStream</tt></font></a></a>
aus dem Paket <a name="ixa101350"><a href="index_j.html#ixb101023"><font color=#000080><tt>java.util.jar</tt></font></a></a>.
Sie alle dienen dazu, die auszugebenden Daten in eine Archivdatei
zu schreiben und platzsparend zu komprimieren:
<ul>
<li>Das ZIP-Format stammt aus der PC-Welt, ist aber mittlerweile unter
praktisch allen Betriebssystemen verfügbar. Es kann mehrere Dateien
komprimieren und in einem Archiv zusammenfassen.
<li>Das GZIP-Format stammt aus der GNU-Welt und kann lediglich eine
einzige Datei komprimieren. Zur Erstellung von Archiven, die mehrere
Dateien enthalten, wird es meist zusammen mit <font color="#000077"><tt>tar</tt></font>
verwendet.
<li>Das JAR-Format entspricht dem ZIP-Format, beinhaltet aber zusätzlich
noch Manifest-Dateien, die Metainformationen über die gespeicherten
Dateien enthalten.
</ul>
<p>
Das folgende Listing zeigt, wie mehrere Dateien mit Hilfe eines <a href="index_z.html#ixb101019"><font color=#000080><tt>ZipOutputStream</tt></font></a>
komprimiert und in eine gemeinsame Archivdatei geschrieben werden.
Es wird als Kommandozeilenprogramm aufgerufen und erwartet die Namen
der zu erstellenden Archivdatei und der Eingabedateien als Argumente.
Das erzeugte Archiv kann mit <a href="index_j.html#ixb100146"><font color=#000080><tt>jar</tt></font></a>,
<a name="ixa101351"><a href="index_w.html#ixb101024"><font color=#000080><tt>winzip</tt></font></a></a>
oder <a name="ixa101352"><a href="index_p.html#ixb101025"><font color=#000080><tt>pkunzip</tt></font></a></a>
ausgepackt werden.
<a name="zipexample"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* Zip.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
<font color="#555555">004 </font><font color="#0000AA">import</font> java.util.zip.*;
<font color="#555555">005 </font>
<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Zip
<font color="#555555">007 </font>{
<font color="#555555">008 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">009 </font> {
<font color="#555555">010 </font> <font color="#0000AA">if</font> (args.length < 2) {
<font color="#555555">011 </font> System.out.println(<font color="#0000FF">"Usage: java Zip zipfile files..."</font>);
<font color="#555555">012 </font> System.exit(1);
<font color="#555555">013 </font> }
<font color="#555555">014 </font> <font color="#0000AA">try</font> {
<font color="#555555">015 </font> <font color="#006699">byte</font>[] buf = <font color="#0000AA">new</font> <font color="#006699">byte</font>[4096];
<font color="#555555">016 </font> ZipOutputStream out = <font color="#0000AA">new</font> ZipOutputStream(
<font color="#555555">017 </font> <font color="#0000AA">new</font> FileOutputStream(args[0]));
<font color="#555555">018 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 1; i < args.length; ++i) {
<font color="#555555">019 </font> String fname = args[i];
<font color="#555555">020 </font> System.out.println(<font color="#0000FF">"adding "</font> + fname);
<font color="#555555">021 </font> FileInputStream in = <font color="#0000AA">new</font> FileInputStream(fname);
<font color="#555555">022 </font> out.putNextEntry(<font color="#0000AA">new</font> ZipEntry(fname));
<font color="#555555">023 </font> <font color="#006699">int</font> len;
<font color="#555555">024 </font> <font color="#0000AA">while</font> ((len = in.read(buf)) > 0) {
<font color="#555555">025 </font> out.write(buf, 0, len);
<font color="#555555">026 </font> }
<font color="#555555">027 </font> in.close();
<font color="#555555">028 </font> }
<font color="#555555">029 </font> out.close();
<font color="#555555">030 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">031 </font> System.err.println(e.toString());
<font color="#555555">032 </font> }
<font color="#555555">033 </font> }
<font color="#555555">034 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Zip.java"><font color="#000055" size=-1>Zip.java</font></a></td>
</tr>
</table>
<i>
Listing 19.3: Erstellen eines ZIP-Archivs</i></p>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Bitte beachten Sie, dass das Programm nur die Grundzüge des Erstellens
von ZIP-Dateien demonstriert. Insbesondere verzichtet es darauf, die
verschiedenen Eigenschaften des jeweiligen ZIP-Eintrags korrekt zu
setzen (Größe, Datum/Uhrzeit, Prüfsumme etc.). Um
dies zu tun, müssten die entsprechenden Daten ermittelt und dann
an die jeweiligen <a href="index_s.html#ixb100181"><font color=#000080><tt>set</tt></font></a>-Methoden
des <a name="ixa101353"><a href="index_z.html#ixb101026"><font color=#000080><tt>ZipEntry</tt></font></a></a>-Objekts
übergeben werden.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel4id019002003005"></a>
<h4>Berechnung von Prüfsummen </h4>
<p>
Soll sichergestellt werden, dass Daten während einer Übertragung
unverändert bleiben (etwa weil der Übertragungskanal unsicher
oder störanfällig ist), werden diese meist mit einer Prüfsumme
übertragen. Dazu wird aus den Originaldaten eine Art mathematische
Zusammenfassung gebildet und zusammen mit den Daten übertragen.
Der Empfänger berechnet aus den empfangenen Daten mit demselben
Verfahren die Prüfsumme und vergleicht sie mit der übertragenen.
Stimmen beide überein, kann davon ausgegangen werden, dass die
Daten nicht verfälscht wurden.
<p>
Das Verfahren zur Berechnung der Prüfsumme muss natürlich
so beschaffen sein, dass möglichst viele Übertragungsfehler
aufgedeckt werden. Oder mit anderen Worten: es soll möglichst
unwahrscheinlich sein, dass zwei unterschiedliche Texte (von denen
der eine durch Modifikation des anderen enstanden ist) dieselbe Prüfsumme
ergeben.
<p>
Im JDK können Prüfsummen beim Schreiben von Daten mit der
Klasse <a name="ixa101354"><a href="index_c.html#ixb101027"><font color=#000080><tt>CheckedOutputStream</tt></font></a></a>
berechnet werden. Sie ist aus <a href="index_f.html#ixb101008"><font color=#000080><tt>FilterOutputStream</tt></font></a>
abgeleitet und erweitert deren Schnittstelle um einen Konstruktor
zur Auswahl des Prüfsummenverfahrens und um die Methode <a name="ixa101355"><a href="index_g.html#ixb101028"><font color=#000080><tt>getChecksum</tt></font></a></a>
zur Berechnung der Prüfsumme. Ihre Anwendung ist einfach und
entspricht der Klasse <a href="index_c.html#ixb101029"><font color=#000080><tt>CheckedInputStream</tt></font></a>.
Ein Beispiel ist in <a href="k100128.html#adler32example">Listing 19.6</a>
zu finden.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Ein <a name="ixa101356"><i>Message Digest</i></a> ist eine erweiterte
Form einer Prüfsumme. Er besitzt zusätzliche Eigenschaften,
die ihn für kryptografische Anwendungen qualifizieren, und wird
in <a href="k100303.html#messagedigests">Abschnitt 48.1.3</a> erläutert.
Die Klasse <a name="ixa101357"><a href="index_d.html#ixb101031"><font color=#000080><tt>DigestOutputStream</tt></font></a></a>
dient dazu, einen Message Digest für Daten zu berechnen, die
mit einem <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>
ausgegeben werden. Analog dazu gibt es eine Klasse <a name="ixa101358"><a href="index_d.html#ixb101032"><font color=#000080><tt>DigestInputStream</tt></font></a></a>
zur Berechnung eines Message Digests für einen <a href="index_i.html#ixb100642"><font color=#000080><tt>InputStream</tt></font></a>.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<hr>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
Wesley, Version 5.0.1
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100125.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100126.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100128.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100130.html"> >> </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
<td align="right">© 1998, 2007 Guido Krüger & Thomas
Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
</table>
<a name="endofbody"></a>
</body>
</html>
|