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
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
|
<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,k100120.html;106,k100121.html;107,k100123.html;108,k100125.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="k100120.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100121.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100123.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100125.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 18 - Character-Streams
</table>
<hr>
<!-- Section -->
<a name="sectlevel2id018002"></a>
<h2>18.2 <a name="ixa101241">Ausgabe-Streams</a></h2>
<hr>
<ul>
<li><a href="k100122.html#sectlevel2id018002">18.2 Ausgabe-Streams</a>
<ul>
<li><a href="k100122.html#sectlevel3id018002001">18.2.1 Die abstrakte Klasse Writer</a>
<li><a href="k100122.html#sectlevel3id018002002">18.2.2 Auswahl des Ausgabegerätes</a>
<ul>
<li><a href="k100122.html#sectlevel4id018002002001">OutputStreamWriter und FileWriter</a>
<li><a href="k100122.html#sectlevel4id018002002002">StringWriter und CharArrayWriter</a>
</ul>
<li><a href="k100122.html#charausgabestreamsschachteln">18.2.3 Schachteln von Ausgabe-Streams </a>
<ul>
<li><a href="k100122.html#sectlevel4id018002003001">BufferedWriter</a>
<li><a href="k100122.html#sectlevel4id018002003002">PrintWriter</a>
<li><a href="k100122.html#sectlevel4id018002003003">FilterWriter</a>
</ul>
</ul>
</ul>
<hr>
<!-- Section -->
<a name="sectlevel3id018002001"></a>
<h3>18.2.1 Die abstrakte Klasse Writer </h3>
<p>
Basis aller sequenziellen Ausgaben ist die abstrakte Klasse <a name="ixa101242"><a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a></a>
des Pakets <a href="index_j.html#ixb100189"><font color=#000080><tt>java.io</tt></font></a>,
die eine Schnittstelle für stream-basierte Ausgaben zur Verfügung
stellt:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
protected Writer()
public void close()
public void flush()
public void write(int c)
public void write(char[] cbuf)
abstract public void write(char[] cbuf, int off, int len)
public void write(String str)
public void write(String str, int off, int len)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/Writer.html" onClick="this.href=getApiDoc('java.io.Writer')"><font color="#660066" size=-1>java.io.Writer</font></a></td>
</tr>
</table>
<p>
Neben einem parameterlosen Konstruktor definiert sie die Methoden
<a name="ixa101243"><a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a></a>
und <a name="ixa101244"><a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a></a>
und eine Reihe überladener <a name="ixa101245"><a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a></a>-Methoden.
Die Bedeutung des Konstruktors liegt darin, den Ausgabestrom zu öffnen
und für einen nachfolgenden Aufruf von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
vorzubereiten, bevor er schließlich mit <a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a>
wieder geschlossen wird. In der Grundform erwartet <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
einen einzigen <a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>-Parameter
und schreibt diesen als Byte in den Ausgabestrom. Daneben gibt es
weitere Varianten, die ein Array von Bytes oder ein <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekt
als Parameter erwarten und dieses durch wiederholten Aufruf der primitiven
<a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methode
ausgeben. Durch Aufruf von <a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a>
werden eventuell vorhandene Puffer geleert und die darin enthaltenen
Daten an das Ausgabegerät weitergegeben.
<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>
Von abgeleiteten Klassen wird erwartet, dass sie mindestens die Methoden
<a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a>
und <a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a>
sowie <font color="#000077"><tt>write(char, int, int)</tt></font>
überlagern. Aus Gründen der Performance ist es aber oftmals
sinnvoll, auch die übrigen <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
zu überlagern.</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="sectlevel3id018002002"></a>
<h3>18.2.2 Auswahl des Ausgabegerätes </h3>
<p>
Als abstrakte Basisklasse kann <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
nicht instanziert werden. Statt dessen gibt es eine Reihe konkreter
Klassen, die aus <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
abgeleitet wurden und deren Aufgabe es ist, die Verbindung zu einem
konkreten Ausgabegerät herzustellen oder Filterfunktionen zu
übernehmen. <a href="k100122.html#writerkindklassen">Tabelle 18.1</a>
gibt eine Übersicht dieser abgeleiteten Klassen. <a name="writerkindklassen"></a>
<p>
<table cols=2 border width=100%>
<tr>
<td valign=top align=left width=25%><b>Klasse</b></td>
<td valign=top align=left width=75%><b>Bedeutung </b></td></tr>
<tr>
<td valign=top align=left><a name="ixa101246"><a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a></a></td>
<td valign=top align=left>Basisklasse für alle Writer, die einen
Character-Stream in einen Byte-Stream umwandeln</td></tr>
<tr>
<td valign=top align=left><a name="ixa101247"><a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a></a></td>
<td valign=top align=left>Konkrete Ableitung von <a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a>
zur Ausgabe in eine Datei </td></tr>
<tr>
<td valign=top align=left><a name="ixa101248"><a href="index_f.html#ixb100962"><font color=#000080><tt>FilterWriter</tt></font></a></a></td>
<td valign=top align=left>Abstrakte Basisklasse für die Konstruktion
von Ausgabefiltern </td></tr>
<tr>
<td valign=top align=left><a name="ixa101249"><a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a></a></td>
<td valign=top align=left>Ausgabe aller Basistypen im Textformat </td></tr>
<tr>
<td valign=top align=left><a name="ixa101250"><a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a></a></td>
<td valign=top align=left>Writer zur Ausgabepufferung </td></tr>
<tr>
<td valign=top align=left><a name="ixa101251"><a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a></a></td>
<td valign=top align=left>Writer zur Ausgabe in einen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
</td></tr>
<tr>
<td valign=top align=left><a name="ixa101252"><a href="index_c.html#ixb100966"><font color=#000080><tt>CharArrayWriter</tt></font></a></a></td>
<td valign=top align=left>Writer zur Ausgabe in ein Zeichen-Array
</td></tr>
<tr>
<td valign=top align=left><a name="ixa101253"><a href="index_p.html#ixb100967"><font color=#000080><tt>PipedWriter</tt></font></a></a></td>
<td valign=top align=left>Writer zur Ausgabe in einen <a name="ixa101254"><a href="index_p.html#ixb100968"><font color=#000080><tt>PipedReader</tt></font></a></a>
</td></tr>
</table>
<p><i>
Tabelle 18.1: Aus Writer abgeleitete Klassen </i></p>
<p>
In den folgenden Unterabschnitten werden die Klassen <a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a>,
<a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>,
<a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>
und <a href="index_c.html#ixb100966"><font color=#000080><tt>CharArrayWriter</tt></font></a>
erläutert. Die Klassen <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>,
<a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>
und <a href="index_f.html#ixb100962"><font color=#000080><tt>FilterWriter</tt></font></a>
sind Thema des nächsten Abschnitts.
<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>
Die Klasse <a name="ixa101253"><a href="index_p.html#ixb100967"><font color=#000080><tt>PipedWriter</tt></font></a></a>
soll hier nicht erläutert werden. In <a href="k100147.html#pipedthreads">Abschnitt 22.4.4</a>
findet sich jedoch ein Beispiel zur Anwendung der Klassen <a href="index_p.html#ixb100969"><font color=#000080><tt>PipedInputStream</tt></font></a>
und <a href="index_p.html#ixb100970"><font color=#000080><tt>PipedOutputStream</tt></font></a>,
das auf <a href="index_p.html#ixb100968"><font color=#000080><tt>PipedReader</tt></font></a>
und <a href="index_p.html#ixb100967"><font color=#000080><tt>PipedWriter</tt></font></a>
übertragbar ist.</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="sectlevel4id018002002001"></a>
<h4>OutputStreamWriter und FileWriter </h4>
<p>
Die Klasse <a name="ixa101255"><a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a></a>
ist die Basisklasse für alle Writer, die eine Konvertierung zwischen
Character- und Byte-Streams vornehmen. Sie enthält ein Objekt
des Typs <a name="ixa101256"><a href="index_c.html#ixb100971"><font color=#000080><tt>CharToByteConverter</tt></font></a></a>
(aus dem undokumentierten Paket <a name="ixa101257"><a href="index_s.html#ixb100972"><font color=#000080><tt>sun.io</tt></font></a></a>),
das die Konvertierung der Ausgabezeichen bei allen schreibenden Zugriffen
vornimmt. Als übergeordnete Basisklasse ist <a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a>
für uns allerdings nicht so interessant wie die daraus abgeleitete
Klasse <a name="ixa101258"><a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a></a>,
die die Ausgabe in eine Datei ermöglicht. Sie implementiert die
abstrakten Eigenschaften von <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
und bietet vier zusätzliche Konstruktoren, die es erlauben, eine
Datei zu öffnen:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public FileWriter(String fileName)
throws IOException
public FileWriter(String fileName, boolean append)
throws IOException
public FileWriter(File file)
throws IOException
public FileWriter(FileDescriptor fd)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/FileWriter.html" onClick="this.href=getApiDoc('java.io.FileWriter')"><font color="#660066" size=-1>java.io.FileWriter</font></a></td>
</tr>
</table>
<p>
Am einfachsten kann eine Datei göffnet werden, indem der Dateiname
als <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Parameter
<font color="#000077"><tt>fileName</tt></font> übergeben wird.
Falls <font color="#000077"><tt>fileName</tt></font> eine bereits
vorhandene Datei bezeichnet, wird sie geöffnet und ihr bisheriger
Inhalt gelöscht, andernfalls wird eine neue Datei mit diesem
Namen angelegt. Sukzessive Aufrufe von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
schreiben weitere Bytes in diese Datei. Wird zusätzlich der Parameter
<font color="#000077"><tt>append</tt></font> mit dem Wert <a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
an den Konstruktor übergeben, so werden die Ausgabezeichen an
die Datei angehängt, falls sie bereits existiert.
<p>
Das folgende Programm erstellt eine Datei <font color="#660099">hallo.txt</font>
und schreibt die Zeile »Hallo JAVA« in die Datei:
<a name="listingid018001"></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">/* Listing1801.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> Listing1801
<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> String hello = <font color="#0000FF">"Hallo JAVA\r\n"</font>;
<font color="#555555">010 </font> FileWriter f1;
<font color="#555555">011 </font>
<font color="#555555">012 </font> <font color="#0000AA">try</font> {
<font color="#555555">013 </font> f1 = <font color="#0000AA">new</font> FileWriter(<font color="#0000FF">"hallo.txt"</font>);
<font color="#555555">014 </font> f1.write(hello);
<font color="#555555">015 </font> f1.close();
<font color="#555555">016 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">017 </font> System.out.println(<font color="#0000FF">"Fehler beim Erstellen der Datei"</font>);
<font color="#555555">018 </font> }
<font color="#555555">019 </font> }
<font color="#555555">020 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1801.java"><font color="#000055" size=-1>Listing1801.java</font></a></td>
</tr>
</table>
<i>
Listing 18.1: Erstellen einer Datei</i></p>
<p>
Fast alle Methoden der Klassen <a href="index_o.html#ixb100960"><font color=#000080><tt>OutputStreamWriter</tt></font></a>
und <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
deklarieren die Ausnahme <a name="ixa101259"><a href="index_i.html#ixb100709"><font color=#000080><tt>IOException</tt></font></a></a>,
die als allgemeine Fehleranzeige im Paket <a href="index_j.html#ixb100189"><font color=#000080><tt>java.io</tt></font></a>
verwendet wird. <a href="index_i.html#ixb100709"><font color=#000080><tt>IOException</tt></font></a>
kann von einer Vielzahl von Methoden ausgelöst werden und hat
dabei teilweise sehr unterschiedliche Bedeutungen. So bedeutet sie
beim Aufruf des Konstruktors, dass es nicht möglich war, die
Datei anzulegen, was wiederum eine ganze Reihe von Gründen haben
kann. Beim Aufruf von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
signalisiert sie einen Schreibfehler, und bei <a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a>
zeigt sie einen nicht näher spezifizierten I/O-Fehler an.
<p>
In unserem Beispiel wurden alle Ausnahmen dieses Typs von einer einzigen
<a href="index_t.html#ixb100569"><font color=#000080><tt>try</tt></font></a>-<a href="index_c.html#ixb100570"><font color=#000080><tt>catch</tt></font></a>-Anweisung
behandelt. Falls eine differenziertere Fehlererkennung nötig
ist, macht es Sinn, für die unterschiedlichen I/O-Operationen
verschiedene <a href="index_t.html#ixb100569"><font color=#000080><tt>try</tt></font></a>-<a href="index_c.html#ixb100570"><font color=#000080><tt>catch</tt></font></a>-Anweisungen
vorzusehen.
<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>
Die anderen Konstruktoren von <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
erwarten ein <a name="ixa101260"><a href="index_f.html#ixb100973"><font color=#000080><tt>File</tt></font></a></a>-Objekt
bzw. ein Objekt vom Typ <a name="ixa101261"><a href="index_f.html#ixb100974"><font color=#000080><tt>FileDescriptor</tt></font></a></a>.
Während wir auf die Klasse <a href="index_f.html#ixb100974"><font color=#000080><tt>FileDescriptor</tt></font></a>
nicht näher eingehen werden, ist ein <a href="index_f.html#ixb100973"><font color=#000080><tt>File</tt></font></a>
die Repräsentation einer Datei im Kontext ihres Verzeichnisses.
Wir werden später in <a href="k100136.html#verzeichnisse">Kapitel 21</a>
darauf zurückkommen.</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="sectlevel4id018002002002"></a>
<h4>StringWriter und CharArrayWriter </h4>
<p>
Die Klassen <a name="ixa101262"><a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a></a>
und <a name="ixa101263"><a href="index_c.html#ixb100966"><font color=#000080><tt>CharArrayWriter</tt></font></a></a>
sind ebenfalls aus <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
abgeleitet. Im Gegensatz zu <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
schreiben sie ihre Ausgabe jedoch nicht in eine Datei, sondern in
einen dynamisch wachsenden <a href="index_s.html#ixb100119"><font color=#000080><tt>StringBuffer</tt></font></a>
bzw. in ein Zeichenarray.
<p>
<a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>
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 StringWriter()
public StringWriter(int initialSize)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/StringWriter.html" onClick="this.href=getApiDoc('java.io.StringWriter')"><font color="#660066" size=-1>java.io.StringWriter</font></a></td>
</tr>
</table>
<p>
Der parameterlose Konstruktor legt einen <a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>
mit der Standardgröße eines <a href="index_s.html#ixb100119"><font color=#000080><tt>StringBuffer</tt></font></a>-Objekts
an, während der zweite Konstruktor es erlaubt, die initiale Größe
selbst festzulegen. Wie schon erwähnt, wächst der interne
Puffer automatisch, wenn fortgesetzte Aufrufe von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
dies erforderlich machen. Die schreibenden Zugriffe auf den Puffer
erfolgen mit den von <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
bekannten <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden.
<p>
Für den Zugriff auf den Inhalt des Puffers stehen die Methoden
<a name="ixa101264"><a href="index_g.html#ixb100975"><font color=#000080><tt>getBuffer</tt></font></a></a>
und <a name="ixa101265"><a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a></a>
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>
public StringBuffer getBuffer()
public String toString()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/StringWriter.html" onClick="this.href=getApiDoc('java.io.StringWriter')"><font color="#660066" size=-1>java.io.StringWriter</font></a></td>
</tr>
</table>
<p>
Die Methode <a href="index_g.html#ixb100975"><font color=#000080><tt>getBuffer</tt></font></a>
liefert den internen <a href="index_s.html#ixb100119"><font color=#000080><tt>StringBuffer</tt></font></a>,
während <a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a>
den Puffer in einen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
kopiert und diesen an den Aufrufer liefert.
<p>
Die Klasse <a name="ixa101263"><a href="index_c.html#ixb100966"><font color=#000080><tt>CharArrayWriter</tt></font></a></a>
arbeitet ähnlich wie <a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>,
schreibt die Zeichen allerdings in ein Character-Array. Analog zu
<a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>
wächst dieses automatisch bei fortgesetzten Aufrufen von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>.
Die Konstruktoren haben dieselbe Struktur wie bei <a href="index_s.html#ixb100965"><font color=#000080><tt>StringWriter</tt></font></a>,
und auch die dort verfügbaren <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
stehen allesamt hier 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>
public CharArrayWriter()
public CharArrayWriter(int initialSize)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/CharArrayWriter.html" onClick="this.href=getApiDoc('java.io.CharArrayWriter')"><font color="#660066" size=-1>java.io.CharArrayWriter</font></a></td>
</tr>
</table>
<p>
Auf den aktuellen Inhalt des Arrays kann mit Hilfe der Methoden <a name="ixa101266"><a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a></a>
und <a name="ixa101267"><a href="index_t.html#ixb100976"><font color=#000080><tt>toCharArray</tt></font></a></a>
zugegriffen werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public String toString()
public char[] toCharArray()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/CharArrayWriter.html" onClick="this.href=getApiDoc('java.io.CharArrayWriter')"><font color="#660066" size=-1>java.io.CharArrayWriter</font></a></td>
</tr>
</table>
<p>
Zusätzlich stehen die Methoden <a name="ixa101268"><a href="index_r.html#ixb100977"><font color=#000080><tt>reset</tt></font></a></a>
und <a name="ixa101269"><a href="index_s.html#ixb100679"><font color=#000080><tt>size</tt></font></a></a>
zur Verfügung, mit denen der interne Puffer geleert bzw. die
aktuelle Größe des Zeichen-Arrays ermittelt werden kann.
Durch Aufruf von <a name="ixa101270"><a href="index_w.html#ixb100978"><font color=#000080><tt>writeTo</tt></font></a></a>
kann des weiteren der komplette Inhalt des Arrays an einen anderen
<a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
übergeben und so beispielsweise mit einem einzigen Funktionsaufruf
in eine Datei 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 void reset()
public int size()
public void writeTo(Writer out)
throws IOException
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/CharArrayWriter.html" onClick="this.href=getApiDoc('java.io.CharArrayWriter')"><font color="#660066" size=-1>java.io.CharArrayWriter</font></a></td>
</tr>
</table>
<!-- Section -->
<a name="charausgabestreamsschachteln"></a>
<h3>18.2.3 Schachteln von Ausgabe-Streams <a name="ixa101271"></a>
</h3>
<p>
Wie eingangs erwähnt, ist es in Java möglich, Streams zu
schachteln. Dazu gibt es die aus <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
abgeleiteten Klassen <a name="ixa101272"><a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a></a>,
<a name="ixa101273"><a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a></a>
und <a name="ixa101274"><a href="index_f.html#ixb100962"><font color=#000080><tt>FilterWriter</tt></font></a></a>,
deren wesentlicher Unterschied zu <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
darin besteht, dass sie als Membervariable einen zusätzlichen
<a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
besitzen, der im Konstruktor übergeben wird. Wenn nun die <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methode
eines derart geschachtelten Writers aufgerufen wird, gibt sie die
Daten nicht direkt an den internen <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
weiter, sondern führt zuvor erst die erforderlichen Filterfunktionen
aus. Damit lassen sich beliebige Filterfunktionen transparent realisieren.
<!-- Section -->
<a name="sectlevel4id018002003001"></a>
<h4>BufferedWriter </h4>
<p>
Diese Klasse hat die Aufgabe, Stream-Ausgaben zu puffern. Dazu enthält
sie einen internen Puffer, in dem die Ausgaben von <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>
zwischengespeichert werden. Erst wenn der Puffer voll ist oder die
Methode <a name="ixa101275"><a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a></a>
aufgerufen wird, werden alle gepufferten Ausgaben in den echten Stream
geschrieben. Das Puffern der Ausgabe ist immer dann nützlich,
wenn die Ausgabe in eine Datei geschrieben werden soll. Durch die
Verringerung der <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Aufrufe
reduziert sich die Anzahl der Zugriffe auf das externe Gerät,
und die Performance wird erhöht.
<p>
<a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
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 BufferedWriter(Writer out)
public BufferedWriter(Writer out, int size)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/BufferedWriter.html" onClick="this.href=getApiDoc('java.io.BufferedWriter')"><font color="#660066" size=-1>java.io.BufferedWriter</font></a></td>
</tr>
</table>
<p>
In beiden Fällen wird ein bereits existierender <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
übergeben, an den die gepufferten Ausgaben weitergereicht werden.
Falls die Größe des Puffers nicht explizit angegeben wird,
legt <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
einen Standardpuffer an, dessen Größe für die meisten
Zwecke ausreichend ist. Die <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
von <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
entsprechen denen der Klasse <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>.
<p>
Zusätzlich gibt es eine Methode <a name="ixa101276"><a href="index_n.html#ixb100980"><font color=#000080><tt>newLine</tt></font></a></a>,
mit der eine Zeilenschaltung in den Stream geschrieben werden kann.
Diese wird dem System-Property <a name="ixa101277"><a href="index_l.html#ixb100833"><font color=#000080><tt>line.separator</tt></font></a></a>
entnommen und entspricht damit den lokalen Konventionen.
<p>
Das nachfolgende Beispiel demonstriert die gepufferte Ausgabe einer
Reihe von Textzeilen in eine Datei <font color="#660099">buffer.txt</font>:
<a name="listingid018002"></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">/* Listing1802.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> Listing1802
<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> Writer f1;
<font color="#555555">010 </font> BufferedWriter f2;
<font color="#555555">011 </font> String s;
<font color="#555555">012 </font>
<font color="#555555">013 </font> <font color="#0000AA">try</font> {
<font color="#555555">014 </font> f1 = <font color="#0000AA">new</font> FileWriter(<font color="#0000FF">"buffer.txt"</font>);
<font color="#555555">015 </font> f2 = <font color="#0000AA">new</font> BufferedWriter(f1);
<font color="#555555">016 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 1; i <= 10000; ++i) {
<font color="#555555">017 </font> s = <font color="#0000FF">"Dies ist die "</font> + i + <font color="#0000FF">". Zeile"</font>;
<font color="#555555">018 </font> f2.write(s);
<font color="#555555">019 </font> f2.newLine();
<font color="#555555">020 </font> }
<font color="#555555">021 </font> f2.close();
<font color="#555555">022 </font> f1.close();
<font color="#555555">023 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">024 </font> System.out.println(<font color="#0000FF">"Fehler beim Erstellen der Datei"</font>);
<font color="#555555">025 </font> }
<font color="#555555">026 </font> }
<font color="#555555">027 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1802.java"><font color="#000055" size=-1>Listing1802.java</font></a></td>
</tr>
</table>
<i>
Listing 18.2: Gepufferte Ausgabe in eine Datei</i></p>
<p>
Dieses Beispiel erzeugt zunächst einen neuen <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
<font color="#000077"><tt>f1</tt></font>, um die Datei <font color="#660099">buffer.txt</font>
anzulegen. Dieser wird anschließend als Parameter an den <font color="#000077"><tt>BufferedWriter
f2</tt></font> übergeben, der dann für den Aufruf der Ausgaberoutinen
verwendet wird.
<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>
Die etwas umständliche Verwendung zweier Stream-Variablen läßt
sich vereinfachen, indem die Konstruktoren direkt beim Aufruf geschachtelt
werden. Das ist die unter Java übliche Methode, die auch zukünftig
bevorzugt verwendet werden soll:</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>
<a name="listingid018003"></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">/* Listing1803.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> Listing1803
<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> BufferedWriter f;
<font color="#555555">010 </font> String s;
<font color="#555555">011 </font>
<font color="#555555">012 </font> <font color="#0000AA">try</font> {
<font color="#555555">013 </font> f = <font color="#0000AA">new</font> BufferedWriter(
<font color="#555555">014 </font> <font color="#0000AA">new</font> FileWriter(<font color="#0000FF">"buffer.txt"</font>));
<font color="#555555">015 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 1; i <= 10000; ++i) {
<font color="#555555">016 </font> s = <font color="#0000FF">"Dies ist die "</font> + i + <font color="#0000FF">". Zeile"</font>;
<font color="#555555">017 </font> f.write(s);
<font color="#555555">018 </font> f.newLine();
<font color="#555555">019 </font> }
<font color="#555555">020 </font> f.close();
<font color="#555555">021 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">022 </font> System.out.println(<font color="#0000FF">"Fehler beim Erstellen der Datei"</font>);
<font color="#555555">023 </font> }
<font color="#555555">024 </font> }
<font color="#555555">025 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1803.java"><font color="#000055" size=-1>Listing1803.java</font></a></td>
</tr>
</table>
<i>
Listing 18.3: Schachteln von Writer-Konstruktoren</i></p>
<!-- Section -->
<a name="sectlevel4id018002003002"></a>
<h4>PrintWriter </h4>
<p>
Die stream-basierten Ausgaberoutinen in anderen Programmiersprachen
bieten meistens die Möglichkeit, alle primitiven Datentypen in
textueller Form auszugeben. Java realisiert dieses Konzept über
die Klasse <a name="ixa101278"><a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a></a>,
die Ausgabemethoden für alle primitiven Datentypen und für
Objekttypen zur Verfügung stellt. <a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>
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 PrintWriter(Writer out)
public PrintWriter(Writer out, boolean autoflush)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/PrintWriter.html" onClick="this.href=getApiDoc('java.io.PrintWriter')"><font color="#660066" size=-1>java.io.PrintWriter</font></a></td>
</tr>
</table>
<p>
Der erste Konstruktor instanziert ein PrintWriter-Objekt durch Übergabe
eines Writer-Objekts, auf das die Ausgabe umgeleitet werden soll.
Beim zweiten Konstruktor gibt zusätzlich der Parameter <font color="#000077"><tt>autoflush</tt></font>
an, ob nach der Ausgabe einer Zeilenschaltung automatisch die Methode
<a href="index_f.html#ixb100958"><font color=#000080><tt>flush</tt></font></a>
aufgerufen werden soll.
<p>
Die Ausgabe von primitiven Datentypen wird durch eine Reihe überladener
Methoden mit dem Namen <a name="ixa101279"><a href="index_p.html#ixb100922"><font color=#000080><tt>print</tt></font></a></a>
realisiert. Zusätzlich gibt es alle Methoden in einer Variante
<a name="ixa101280"><a href="index_p.html#ixb100555"><font color=#000080><tt>println</tt></font></a></a>,
bei der automatisch an das Ende der Ausgabe eine Zeilenschaltung angehängt
wird. <a href="index_p.html#ixb100555"><font color=#000080><tt>println</tt></font></a>
existiert darüber hinaus parameterlos, um lediglich eine einzelne
Zeilenschaltung auszugeben. Damit stehen folgende <a href="index_p.html#ixb100922"><font color=#000080><tt>print</tt></font></a>-Methoden
zur Verfügung (analog für <a href="index_p.html#ixb100555"><font color=#000080><tt>println</tt></font></a>):
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void print(boolean b)
public void print(char c)
public void print(char[] s)
public void print(double d)
public void print(float f)
public void print(int i)
public void print(long l)
public void print(Object obj)
public void print(String s)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/io/PrintWriter.html" onClick="this.href=getApiDoc('java.io.PrintWriter')"><font color="#660066" size=-1>java.io.PrintWriter</font></a></td>
</tr>
</table>
<p>
Das folgende Beispiel berechnet die Zahlenfolge 1 + 1/2 + 1/4 + ...
und gibt die Folge der Summanden und die aktuelle Summe unter Verwendung
mehrerer unterschiedlicher <a href="index_p.html#ixb100922"><font color=#000080><tt>print</tt></font></a>-Routinen
in die Datei <font color="#660099">zwei.txt</font> aus:
<a name="listingid018004"></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">/* Listing1804.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> Listing1804
<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> PrintWriter f;
<font color="#555555">010 </font> <font color="#006699">double</font> sum = 0.0;
<font color="#555555">011 </font> <font color="#006699">int</font> nenner;
<font color="#555555">012 </font>
<font color="#555555">013 </font> <font color="#0000AA">try</font> {
<font color="#555555">014 </font> f = <font color="#0000AA">new</font> PrintWriter(
<font color="#555555">015 </font> <font color="#0000AA">new</font> BufferedWriter(
<font color="#555555">016 </font> <font color="#0000AA">new</font> FileWriter(<font color="#0000FF">"zwei.txt"</font>)));
<font color="#555555">017 </font>
<font color="#555555">018 </font> <font color="#0000AA">for</font> (nenner = 1; nenner <= 1024; nenner *= 2) {
<font color="#555555">019 </font> sum += 1.0 / nenner;
<font color="#555555">020 </font> f.print(<font color="#0000FF">"Summand: 1/"</font>);
<font color="#555555">021 </font> f.print(nenner);
<font color="#555555">022 </font> f.print(<font color="#0000FF">" Summe: "</font>);
<font color="#555555">023 </font> f.println(sum);
<font color="#555555">024 </font> }
<font color="#555555">025 </font> f.close();
<font color="#555555">026 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">027 </font> System.out.println(<font color="#0000FF">"Fehler beim Erstellen der Datei"</font>);
<font color="#555555">028 </font> }
<font color="#555555">029 </font> }
<font color="#555555">030 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1804.java"><font color="#000055" size=-1>Listing1804.java</font></a></td>
</tr>
</table>
<i>
Listing 18.4: Die Klasse PrintWriter</i></p>
<p>
Das Programm verwendet Methoden zur Ausgabe von Strings, Ganz- und
Fließkommazahlen. Nach Ende des Programms hat die Datei <font color="#660099">zwei.txt</font>
folgenden Inhalt:
<font color="#333300">
<pre>
Summand: 1/1 Summe: 1
Summand: 1/2 Summe: 1.5
Summand: 1/4 Summe: 1.75
Summand: 1/8 Summe: 1.875
Summand: 1/16 Summe: 1.9375
Summand: 1/32 Summe: 1.96875
Summand: 1/64 Summe: 1.98438
Summand: 1/128 Summe: 1.99219
Summand: 1/256 Summe: 1.99609
Summand: 1/512 Summe: 1.99805
Summand: 1/1024 Summe: 1.99902
</pre>
</font>
<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>
Das vorliegende Beispiel realisiert sogar eine doppelte Schachtelung
von <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Objekten.
Das <a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>-Objekt
schreibt in einen <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>,
der seinerseits in den <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
schreibt. Auf diese Weise werden Datentypen im ASCII-Format gepuffert
in eine Textdatei geschrieben. Eine solche Schachtelung ist durchaus
üblich in Java und kann in einer beliebigen Tiefe ausgeführt
werden.</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="sectlevel4id018002003003"></a>
<h4>FilterWriter </h4>
<p>
Wie bereits mehrfach angedeutet, bietet die Architektur der <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Klassen
die Möglichkeit, eigene Filter zu konstruieren. Dies kann beispielsweise
durch Überlagern der Klasse <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
geschehen, so wie es etwa bei <a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>
oder <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
realisiert wurde. Der offizielle Weg besteht allerdings darin, die
abstrakte Klasse <a name="ixa101281"><a href="index_f.html#ixb100962"><font color=#000080><tt>FilterWriter</tt></font></a></a>
zu überlagern. <a href="index_f.html#ixb100962"><font color=#000080><tt>FilterWriter</tt></font></a>
besitzt ein internes <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Objekt
<font color="#000077"><tt>out</tt></font>, das bei der Instanzierung
an den Konstruktor übergeben wird. Zusätzlich überlagert
es drei der vier <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden,
um die Ausgabe auf <font color="#000077"><tt>out</tt></font> umzuleiten.
Die vierte <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methode
(<font color="#000077"><tt>write(String)</tt></font>) wird dagegen
nicht überlagert, sondern ruft gemäß ihrer Implementierung
in <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
die Variante <font color="#000077"><tt>write(String, int, int)</tt></font>
auf.
<p>
Soll eine eigene Filterklasse konstruiert werden, so ist wie folgt
vorzugehen:
<ul>
<li> Die Klasse wird aus FilterWriter abgeleitet.
<li> Im Konstruktor wird der Superklassen-Konstruktor aufgerufen,
um out zu initialisieren.
<li> Die drei write-Methoden werden separat überlagert. Dabei
wird jeweils vor der Übergabe der Ausgabezeichen an die Superklassenmethode
die eigene Filterfunktion ausgeführt.
</ul>
<p>
Anschließend kann die neue Filterklasse wie gewohnt in einer
Kette von geschachtelten <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Objekten
verwendet werden.
<p>
Wir wollen uns die Konstruktion einer Filterklasse anhand der folgenden
Beispielklasse <font color="#000077"><tt>UpCaseWriter</tt></font>
ansehen, deren Aufgabe es ist, innerhalb eines Streams alle Zeichen
in Großschrift zu konvertieren:
<a name="filterwriterbsp"></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">/* Listing1805.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">class</font> UpCaseWriter
<font color="#555555">006 </font><font color="#0000AA">extends</font> FilterWriter
<font color="#555555">007 </font>{
<font color="#555555">008 </font> <font color="#0000AA">public</font> UpCaseWriter(Writer out)
<font color="#555555">009 </font> {
<font color="#555555">010 </font> <font color="#006699">super</font>(out);
<font color="#555555">011 </font> }
<font color="#555555">012 </font>
<font color="#555555">013 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> write(<font color="#006699">int</font> c)
<font color="#555555">014 </font> <font color="#0000AA">throws</font> IOException
<font color="#555555">015 </font> {
<font color="#555555">016 </font> <font color="#006699">super</font>.write(Character.toUpperCase((<font color="#006699">char</font>)c));
<font color="#555555">017 </font> }
<font color="#555555">018 </font>
<font color="#555555">019 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> write(<font color="#006699">char</font>[] cbuf, <font color="#006699">int</font> off, <font color="#006699">int</font> len)
<font color="#555555">020 </font> <font color="#0000AA">throws</font> IOException
<font color="#555555">021 </font> {
<font color="#555555">022 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < len; ++i) {
<font color="#555555">023 </font> write(cbuf[off + i]);
<font color="#555555">024 </font> }
<font color="#555555">025 </font> }
<font color="#555555">026 </font>
<font color="#555555">027 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> write(String str, <font color="#006699">int</font> off, <font color="#006699">int</font> len)
<font color="#555555">028 </font> <font color="#0000AA">throws</font> IOException
<font color="#555555">029 </font> {
<font color="#555555">030 </font> write(str.toCharArray(), off, len);
<font color="#555555">031 </font> }
<font color="#555555">032 </font>}
<font color="#555555">033 </font>
<font color="#555555">034 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing1805
<font color="#555555">035 </font>{
<font color="#555555">036 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">037 </font> {
<font color="#555555">038 </font> PrintWriter f;
<font color="#555555">039 </font> String s = <font color="#0000FF">"und dieser String auch"</font>;
<font color="#555555">040 </font>
<font color="#555555">041 </font> <font color="#0000AA">try</font> {
<font color="#555555">042 </font> f = <font color="#0000AA">new</font> PrintWriter(
<font color="#555555">043 </font> <font color="#0000AA">new</font> UpCaseWriter(
<font color="#555555">044 </font> <font color="#0000AA">new</font> FileWriter(<font color="#0000FF">"upcase.txt"</font>)));
<font color="#555555">045 </font> <font color="#00AA00">//Aufruf von außen</font>
<font color="#555555">046 </font> f.println(<font color="#0000FF">"Diese Zeile wird schön groß geschrieben"</font>);
<font color="#555555">047 </font> <font color="#00AA00">//Test von write(int)</font>
<font color="#555555">048 </font> f.write(<font color="#0000FF">'a'</font>);
<font color="#555555">049 </font> f.println();
<font color="#555555">050 </font> <font color="#00AA00">//Test von write(String)</font>
<font color="#555555">051 </font> f.write(s);
<font color="#555555">052 </font> f.println();
<font color="#555555">053 </font> <font color="#00AA00">//Test von write(String, int, int)</font>
<font color="#555555">054 </font> f.write(s,0,17);
<font color="#555555">055 </font> f.println();
<font color="#555555">056 </font> <font color="#00AA00">//Test von write(char[], int, int)</font>
<font color="#555555">057 </font> f.write(s.toCharArray(),0,10);
<font color="#555555">058 </font> f.println();
<font color="#555555">059 </font> <font color="#00AA00">//---</font>
<font color="#555555">060 </font> f.close();
<font color="#555555">061 </font> } <font color="#0000AA">catch</font> (IOException e) {
<font color="#555555">062 </font> System.out.println(<font color="#0000FF">"Fehler beim Erstellen der Datei"</font>);
<font color="#555555">063 </font> }
<font color="#555555">064 </font> }
<font color="#555555">065 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing1805.java"><font color="#000055" size=-1>Listing1805.java</font></a></td>
</tr>
</table>
<i>
Listing 18.5: Konstruktion einer eigenen FilterWriter-Klasse</i></p>
<p>
Im Konstruktor wird lediglich der Superklassen-Konstruktor aufgerufen,
da keine weiteren Aufgaben zu erledigen sind. Die drei <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
werden so überlagert, dass jeweils zunächst die Ausgabezeichen
in Großschrift konvertiert werden und anschließend die
passende Superklassenmethode aufgerufen wird, um die Daten an den
internen <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>
<font color="#000077"><tt>out</tt></font> zu übergeben.
<p>
Der Test von <font color="#000077"><tt>UpCaseWriter</tt></font> erfolgt
mit der Klasse <font color="#000077"><tt>Listing1805</tt></font>.
Sie schachtelt einen <font color="#000077"><tt>UpCaseWriter</tt></font>
innerhalb eines <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>-
und eines <a href="index_p.html#ixb100963"><font color=#000080><tt>PrintWriter</tt></font></a>-Objekts.
Die verschiedenen Aufrufe der <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-
und <a href="index_p.html#ixb100555"><font color=#000080><tt>println</tt></font></a>-Methoden
rufen dann jede der vier unterschiedlichen <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
des <font color="#000077"><tt>UpCaseWriter</tt></font>-Objekts mindestens
einmal auf, um zu testen, ob die Konvertierung in jedem Fall vorgenommen
wird. Die Ausgabe des Programms ist:
<font color="#333300">
<pre>
DIESE ZEILE WIRD SCHÖN GROß GESCHRIEBEN
A
UND DIESER STRING AUCH
UND DIESER STRING
UND DIESER
</pre>
</font>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Wenn man sich die Implementierung der <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
von <font color="#000077"><tt>UpCaseWriter</tt></font> genauer ansieht,
könnte man auf die Idee kommen, dass sie wesentlich performanter
implementiert werden könnten, wenn nicht alle Ausgaben einzeln
an <font color="#000077"><tt>write(int)</tt></font> gesendet würden.
So scheint es nahezuliegen, beispielsweise <font color="#000077"><tt>write(String,
int, int)</tt></font> in der folgenden Form zu implementieren, denn
die Methode <a name="ixa101282"><a href="index_t.html#ixb100537"><font color=#000080><tt>toUpperCase</tt></font></a></a>
existiert auch in der Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</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="#CC0000">
<tr>
<td><font color="#FFFFFF"> Warnung </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
</tr>
</table>
<font color="#000077">
<pre>
super.write(str.toUpperCase(), off, len);
</pre>
</font>
<p>
Die Sache hat nur leider den Haken, dass <font color="#000077"><tt>String.toUpperCase</tt></font>
möglicherweise die Länge des übergebenen Strings verändert.
So wird beispielsweise das »ß« in ein »SS«
umgewandelt (an sich lobenswert!) und durch die unveränderlichen
Konstanten <font color="#000077"><tt>off</tt></font> und <font color="#000077"><tt>len</tt></font>
geht ein Zeichen verloren. Der hier beschrittene Workaround besteht
darin, grundsätzlich die Methode <font color="#000077"><tt>Character.toUpperCase</tt></font>
zu verwenden. Sie kann immer nur ein einzelnes Zeichen zurückgeben
und läßt damit beispielsweise ein »ß« bei
Umwandlung unangetastet.
<p>
Als interessante Erkenntnis am Rande lernen wir dabei, dass offensichtlich
<font color="#000077"><tt>String.toUpperCase</tt></font> und <font color="#000077"><tt>Character.toUpperCase</tt></font>
unterschiedlich implementiert sind. Ein Blick in den Quellcode der
Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
bestätigt den Verdacht und zeigt zwei Sonderbehandlungen, eine
davon für das »ß«, wie folgender Auszug aus dem
Quellcode des JDK 1.1 belegt (im JDK 1.2 sieht es ähnlich aus):
<font color="#000077">
<pre>
for (i = 0; i < len; ++i) {
char ch = value[offset+i];
if (ch == '\u00DF') { // sharp s
result.append("SS");
continue;
}
result.append(Character.toUpperCase(ch));
}
</pre>
</font>
<p>
Im Umfeld dieser Methode sollte man also mit der nötigen Umsicht
agieren. Das Gegenstück <a name="ixa101283"><a href="index_l.html#ixb100981"><font color=#000080><tt>lowerCase</tt></font></a></a>
hat diese Besonderheit übrigens nicht.
<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="k100120.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100121.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100123.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100125.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>
|