1 /* PrintStream.java -- OutputStream for printing output
2    Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.io;
40 
41 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
42  * "The Java Language Specification", ISBN 0-201-63451-1
43  * Status:  Believed complete and correct to 1.3
44  */
45 
46 /**
47  * This class prints Java primitive values and object to a stream as
48  * text.  None of the methods in this class throw an exception.  However,
49  * errors can be detected by calling the <code>checkError()</code> method.
50  * Additionally, this stream can be designated as "autoflush" when
51  * created so that any writes are automatically flushed to the underlying
52  * output sink when the current line is terminated.
53  * <p>
54  * This class converts char's into byte's using the system default encoding.
55  *
56  * @author Aaron M. Renn (arenn@urbanophile.com)
57  * @author Tom Tromey (tromey@cygnus.com)
58  */
59 public class PrintStream extends FilterOutputStream
60 {
61   /* Notice the implementation is quite similar to OutputStreamWriter.
62    * This leads to some minor duplication, because neither inherits
63    * from the other, and we want to maximize performance. */
64 
65   // Line separator string.
66   private static final char[] line_separator
67     = System.getProperty("line.separator").toCharArray();
68 
69   /**
70    *  Encoding name
71    */
72   private String encoding;
73 
74   /**
75    * This boolean indicates whether or not an error has ever occurred
76    * on this stream.
77    */
78   private boolean error_occurred = false;
79 
80   /**
81    * This is <code>true</code> if auto-flush is enabled,
82    * <code>false</code> otherwise
83    */
84   private boolean auto_flush;
85 
86   /**
87    * This method intializes a new <code>PrintStream</code> object to write
88    * to the specified output sink.
89    *
90    * @param out The <code>OutputStream</code> to write to.
91    */
PrintStream(OutputStream out)92   public PrintStream (OutputStream out)
93   {
94     this (out, false);
95   }
96 
97   /**
98    * This method intializes a new <code>PrintStream</code> object to write
99    * to the specified output sink.  This constructor also allows "auto-flush"
100    * functionality to be specified where the stream will be flushed after
101    * every <code>print</code> or <code>println</code> call, when the
102    * <code>write</code> methods with array arguments are called, or when a
103    * single new-line character is written.
104    * <p>
105    *
106    * @param out The <code>OutputStream</code> to write to.
107    * @param auto_flush <code>true</code> to flush the stream after every
108    * line, <code>false</code> otherwise
109    */
PrintStream(OutputStream out, boolean auto_flush)110   public PrintStream (OutputStream out, boolean auto_flush)
111   {
112     super (out);
113 
114     try {
115 	this.encoding = System.getProperty("file.encoding");
116     } catch (SecurityException e){
117 	this.encoding = "ISO8859_1";
118     } catch (IllegalArgumentException e){
119 	this.encoding = "ISO8859_1";
120     } catch (NullPointerException e){
121 	this.encoding = "ISO8859_1";
122     }
123     this.auto_flush = auto_flush;
124   }
125 
126   /**
127    * This method intializes a new <code>PrintStream</code> object to write
128    * to the specified output sink.  This constructor also allows "auto-flush"
129    * functionality to be specified where the stream will be flushed after
130    * every <code>print</code> or <code>println</code> call, when the
131    * <code>write</code> methods with array arguments are called, or when a
132    * single new-line character is written.
133    * <p>
134    *
135    * @param out The <code>OutputStream</code> to write to.
136    * @param auto_flush <code>true</code> to flush the stream after every
137    * line, <code>false</code> otherwise
138    * @param encoding The name of the character encoding to use for this
139    * object.
140    */
PrintStream(OutputStream out, boolean auto_flush, String encoding)141   public PrintStream (OutputStream out, boolean auto_flush, String encoding)
142     throws UnsupportedEncodingException
143   {
144     super (out);
145 
146     new String(new byte[]{0}, encoding);    // check if encoding is supported
147     this.encoding = encoding;
148     this.auto_flush = auto_flush;
149   }
150 
151   /**
152    * This method checks to see if an error has occurred on this stream.  Note
153    * that once an error has occurred, this method will continue to report
154    * <code>true</code> forever for this stream.  Before checking for an
155    * error condition, this method flushes the stream.
156    *
157    * @return <code>true</code> if an error has occurred,
158    * <code>false</code> otherwise
159    */
checkError()160   public boolean checkError ()
161   {
162     flush ();
163     return error_occurred;
164   }
165 
166   /**
167    * This method can be called by subclasses to indicate that an error
168    * has occurred and should be reported by <code>checkError</code>.
169    */
setError()170   protected void setError ()
171   {
172     error_occurred = true;
173   }
174 
175   /**
176    * This method closes this stream and all underlying streams.
177    */
close()178   public void close ()
179   {
180     try
181       {
182 	flush();
183 	out.close();
184       }
185     catch (InterruptedIOException iioe)
186       {
187 	Thread.currentThread().interrupt();
188       }
189     catch (IOException e)
190       {
191 	setError ();
192       }
193   }
194 
195   /**
196    * This method flushes any buffered bytes to the underlying stream and
197    * then flushes that stream as well.
198    */
flush()199   public void flush ()
200   {
201     try
202       {
203 	out.flush();
204       }
205     catch (InterruptedIOException iioe)
206       {
207 	Thread.currentThread().interrupt();
208       }
209     catch (IOException e)
210       {
211 	setError ();
212       }
213   }
214 
print(String str, boolean println)215   private synchronized void print (String str, boolean println)
216   {
217     try
218       {
219         writeChars(str, 0, str.length());
220 	if (println)
221 	  writeChars(line_separator, 0, line_separator.length);
222 	if (auto_flush)
223 	  flush();
224       }
225     catch (InterruptedIOException iioe)
226       {
227 	Thread.currentThread().interrupt();
228       }
229     catch (IOException e)
230       {
231 	setError ();
232       }
233   }
234 
print(char[] chars, int pos, int len, boolean println)235   private synchronized void print (char[] chars, int pos, int len,
236 				   boolean println)
237   {
238     try
239       {
240         writeChars(chars, pos, len);
241 	if (println)
242 	  writeChars(line_separator, 0, line_separator.length);
243 	if (auto_flush)
244 	  flush();
245       }
246     catch (InterruptedIOException iioe)
247       {
248 	Thread.currentThread().interrupt();
249       }
250     catch (IOException e)
251       {
252 	setError ();
253       }
254   }
255 
writeChars(char[] buf, int offset, int count)256   private void writeChars(char[] buf, int offset, int count)
257     throws IOException
258   {
259       byte[] bytes = (new String(buf, offset, count)).getBytes(encoding);
260       out.write(bytes, 0, bytes.length);
261   }
262 
writeChars(String str, int offset, int count)263   private void writeChars(String str, int offset, int count)
264     throws IOException
265   {
266       byte[] bytes = str.substring(offset, offset+count).getBytes(encoding);
267       out.write(bytes, 0, bytes.length);
268   }
269 
270   /**
271    * This methods prints a boolean value to the stream.  <code>true</code>
272    * values are printed as "true" and <code>false</code> values are printed
273    * as "false".
274    *
275    * @param bool The <code>boolean</code> value to print
276    */
print(boolean bool)277   public void print (boolean bool)
278   {
279     print(String.valueOf(bool), false);
280   }
281 
282   /**
283    * This method prints an integer to the stream.  The value printed is
284    * determined using the <code>String.valueOf()</code> method.
285    *
286    * @param inum The <code>int</code> value to be printed
287    */
print(int inum)288   public void print (int inum)
289   {
290     print(String.valueOf(inum), false);
291   }
292 
293   /**
294    * This method prints a long to the stream.  The value printed is
295    * determined using the <code>String.valueOf()</code> method.
296    *
297    * @param lnum The <code>long</code> value to be printed
298    */
print(long lnum)299   public void print (long lnum)
300   {
301     print(String.valueOf(lnum), false);
302   }
303 
304   /**
305    * This method prints a float to the stream.  The value printed is
306    * determined using the <code>String.valueOf()</code> method.
307    *
308    * @param fnum The <code>float</code> value to be printed
309    */
print(float fnum)310   public void print (float fnum)
311   {
312     print(String.valueOf(fnum), false);
313   }
314 
315   /**
316    * This method prints a double to the stream.  The value printed is
317    * determined using the <code>String.valueOf()</code> method.
318    *
319    * @param dnum The <code>double</code> value to be printed
320    */
print(double dnum)321   public void print (double dnum)
322   {
323     print(String.valueOf(dnum), false);
324   }
325 
326   /**
327    * This method prints an <code>Object</code> to the stream.  The actual
328    * value printed is determined by calling the <code>String.valueOf()</code>
329    * method.
330    *
331    * @param obj The <code>Object</code> to print.
332    */
print(Object obj)333   public void print (Object obj)
334   {
335     print(obj == null ? "null" : obj.toString(), false);
336   }
337 
338   /**
339    * This method prints a <code>String</code> to the stream.  The actual
340    * value printed depends on the system default encoding.
341    *
342    * @param str The <code>String</code> to print.
343    */
print(String str)344   public void print (String str)
345   {
346     print(str == null ? "null" : str, false);
347   }
348 
349   /**
350    * This method prints a char to the stream.  The actual value printed is
351    * determined by the character encoding in use.
352    *
353    * @param ch The <code>char</code> value to be printed
354    */
print(char ch)355   public synchronized void print (char ch)
356   {
357     print(new char[]{ch}, 0, 1, false);
358   }
359 
360   /**
361    * This method prints an array of characters to the stream.  The actual
362    * value printed depends on the system default encoding.
363    *
364    * @param charArray The array of characters to print.
365    */
print(char[] charArray)366   public void print (char[] charArray)
367   {
368     print(charArray, 0, charArray.length, false);
369   }
370 
371   /**
372    * This method prints a line separator sequence to the stream.  The value
373    * printed is determined by the system property <xmp>line.separator</xmp>
374    * and is not necessarily the Unix '\n' newline character.
375    */
println()376   public void println ()
377   {
378     print(line_separator, 0, line_separator.length, false);
379   }
380 
381   /**
382    * This methods prints a boolean value to the stream.  <code>true</code>
383    * values are printed as "true" and <code>false</code> values are printed
384    * as "false".
385    * <p>
386    * This method prints a line termination sequence after printing the value.
387    *
388    * @param bool The <code>boolean</code> value to print
389    */
println(boolean bool)390   public void println (boolean bool)
391   {
392     print(String.valueOf(bool), true);
393   }
394 
395   /**
396    * This method prints an integer to the stream.  The value printed is
397    * determined using the <code>String.valueOf()</code> method.
398    * <p>
399    * This method prints a line termination sequence after printing the value.
400    *
401    * @param inum The <code>int</code> value to be printed
402    */
println(int inum)403   public void println (int inum)
404   {
405     print(String.valueOf(inum), true);
406   }
407 
408   /**
409    * This method prints a long to the stream.  The value printed is
410    * determined using the <code>String.valueOf()</code> method.
411    * <p>
412    * This method prints a line termination sequence after printing the value.
413    *
414    * @param lnum The <code>long</code> value to be printed
415    */
println(long lnum)416   public void println (long lnum)
417   {
418     print(String.valueOf(lnum), true);
419   }
420 
421   /**
422    * This method prints a float to the stream.  The value printed is
423    * determined using the <code>String.valueOf()</code> method.
424    * <p>
425    * This method prints a line termination sequence after printing the value.
426    *
427    * @param fnum The <code>float</code> value to be printed
428    */
println(float fnum)429   public void println (float fnum)
430   {
431     print(String.valueOf(fnum), true);
432   }
433 
434   /**
435    * This method prints a double to the stream.  The value printed is
436    * determined using the <code>String.valueOf()</code> method.
437    * <p>
438    * This method prints a line termination sequence after printing the value.
439    *
440    * @param dnum The <code>double</code> value to be printed
441    */
println(double dnum)442   public void println (double dnum)
443   {
444     print(String.valueOf(dnum), true);
445   }
446 
447   /**
448    * This method prints an <code>Object</code> to the stream.  The actual
449    * value printed is determined by calling the <code>String.valueOf()</code>
450    * method.
451    * <p>
452    * This method prints a line termination sequence after printing the value.
453    *
454    * @param obj The <code>Object</code> to print.
455    */
println(Object obj)456   public void println (Object obj)
457   {
458     print(obj == null ? "null" : obj.toString(), true);
459   }
460 
461   /**
462    * This method prints a <code>String</code> to the stream.  The actual
463    * value printed depends on the system default encoding.
464    * <p>
465    * This method prints a line termination sequence after printing the value.
466    *
467    * @param str The <code>String</code> to print.
468    */
println(String str)469   public void println (String str)
470   {
471     print (str == null ? "null" : str, true);
472   }
473 
474   /**
475    * This method prints a char to the stream.  The actual value printed is
476    * determined by the character encoding in use.
477    * <p>
478    * This method prints a line termination sequence after printing the value.
479    *
480    * @param ch The <code>char</code> value to be printed
481    */
println(char ch)482   public synchronized void println (char ch)
483   {
484     print(new char[]{ch}, 0, 1, true);
485   }
486 
487   /**
488    * This method prints an array of characters to the stream.  The actual
489    * value printed depends on the system default encoding.
490    * <p>
491    * This method prints a line termination sequence after printing the value.
492    *
493    * @param charArray The array of characters to print.
494    */
println(char[] charArray)495   public void println (char[] charArray)
496   {
497     print(charArray, 0, charArray.length, true);
498   }
499 
500   /**
501    * This method writes a byte of data to the stream.  If auto-flush is
502    * enabled, printing a newline character will cause the stream to be
503    * flushed after the character is written.
504    *
505    * @param oneByte The byte to be written
506    */
write(int oneByte)507   public void write (int oneByte)
508   {
509     try
510       {
511         out.write (oneByte & 0xff);
512 
513         if (auto_flush && (oneByte == '\n'))
514           flush ();
515       }
516     catch (InterruptedIOException iioe)
517       {
518 	Thread.currentThread ().interrupt ();
519       }
520     catch (IOException e)
521       {
522         setError ();
523       }
524   }
525 
526   /**
527    * This method writes <code>len</code> bytes from the specified array
528    * starting at index <code>offset</code> into the array.
529    *
530    * @param buffer The array of bytes to write
531    * @param offset The index into the array to start writing from
532    * @param len The number of bytes to write
533    */
write(byte[] buffer, int offset, int len)534   public void write (byte[] buffer, int offset, int len)
535   {
536     try
537       {
538         out.write (buffer, offset, len);
539 
540         if (auto_flush)
541           flush ();
542       }
543     catch (InterruptedIOException iioe)
544       {
545 	Thread.currentThread ().interrupt ();
546       }
547     catch (IOException e)
548       {
549         setError ();
550       }
551   }
552 } // class PrintStream
553 
554