001 /* PrintStream.java -- OutputStream for printing output
002 Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.io;
040
041 import java.util.Formatter;
042 import java.util.Locale;
043
044 import gnu.gcj.convert.UnicodeToBytes;
045
046 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
047 * "The Java Language Specification", ISBN 0-201-63451-1
048 * Status: Believed complete and correct to 1.3
049 */
050
051 /**
052 * This class prints Java primitive values and object to a stream as
053 * text. None of the methods in this class throw an exception. However,
054 * errors can be detected by calling the <code>checkError()</code> method.
055 * Additionally, this stream can be designated as "autoflush" when
056 * created so that any writes are automatically flushed to the underlying
057 * output sink when the current line is terminated.
058 * <p>
059 * This class converts char's into byte's using the system default encoding.
060 *
061 * @author Aaron M. Renn (arenn@urbanophile.com)
062 * @author Tom Tromey (tromey@cygnus.com)
063 */
064 public class PrintStream extends FilterOutputStream implements Appendable
065 {
066 /* Notice the implementation is quite similar to OutputStreamWriter.
067 * This leads to some minor duplication, because neither inherits
068 * from the other, and we want to maximize performance. */
069
070 // Line separator string.
071 private static final char[] line_separator
072 = System.getProperty("line.separator").toCharArray();
073
074 UnicodeToBytes converter;
075
076 // Work buffer of characters for converter.
077 char[] work = new char[100];
078 // Work buffer of bytes where we temporarily keep converter output.
079 byte[] work_bytes = new byte[100];
080
081 /**
082 * This boolean indicates whether or not an error has ever occurred
083 * on this stream.
084 */
085 private boolean error_occurred = false;
086
087 /**
088 * This is <code>true</code> if auto-flush is enabled,
089 * <code>false</code> otherwise
090 */
091 private boolean auto_flush;
092
093 /**
094 * This method intializes a new <code>PrintStream</code> object to write
095 * to the specified output sink.
096 *
097 * @param out The <code>OutputStream</code> to write to.
098 */
099 public PrintStream (OutputStream out)
100 {
101 this (out, false);
102 }
103
104 /**
105 * This method intializes a new <code>PrintStream</code> object to write
106 * to the specified output sink. This constructor also allows "auto-flush"
107 * functionality to be specified where the stream will be flushed after
108 * every <code>print</code> or <code>println</code> call, when the
109 * <code>write</code> methods with array arguments are called, or when a
110 * single new-line character is written.
111 * <p>
112 *
113 * @param out The <code>OutputStream</code> to write to.
114 * @param auto_flush <code>true</code> to flush the stream after every
115 * line, <code>false</code> otherwise
116 */
117 public PrintStream (OutputStream out, boolean auto_flush)
118 {
119 super (out);
120
121 converter = UnicodeToBytes.getDefaultEncoder();
122 this.auto_flush = auto_flush;
123 }
124
125 /**
126 * This method intializes a new <code>PrintStream</code> object to write
127 * to the specified output sink. This constructor also allows "auto-flush"
128 * functionality to be specified where the stream will be flushed after
129 * every <code>print</code> or <code>println</code> call, when the
130 * <code>write</code> methods with array arguments are called, or when a
131 * single new-line character is written.
132 * <p>
133 *
134 * @param out The <code>OutputStream</code> to write to.
135 * @param auto_flush <code>true</code> to flush the stream after every
136 * line, <code>false</code> otherwise
137 * @param encoding The name of the character encoding to use for this
138 * object.
139 */
140 public PrintStream (OutputStream out, boolean auto_flush, String encoding)
141 throws UnsupportedEncodingException
142 {
143 super (out);
144
145 converter = UnicodeToBytes.getEncoder (encoding);
146 this.auto_flush = auto_flush;
147 }
148
149 /**
150 * This method checks to see if an error has occurred on this stream. Note
151 * that once an error has occurred, this method will continue to report
152 * <code>true</code> forever for this stream. Before checking for an
153 * error condition, this method flushes the stream.
154 *
155 * @return <code>true</code> if an error has occurred,
156 * <code>false</code> otherwise
157 */
158 public boolean checkError ()
159 {
160 flush ();
161 return error_occurred;
162 }
163
164 /**
165 * This method can be called by subclasses to indicate that an error
166 * has occurred and should be reported by <code>checkError</code>.
167 */
168 protected void setError ()
169 {
170 error_occurred = true;
171 }
172
173 /**
174 * This method closes this stream and all underlying streams.
175 */
176 public void close ()
177 {
178 try
179 {
180 converter.setFinished();
181 writeChars(new char[0], 0, 0);
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 */
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
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
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
256 private void writeChars(char[] buf, int offset, int count)
257 throws IOException
258 {
259 do
260 {
261 converter.setOutput(work_bytes, 0);
262 int converted = converter.write(buf, offset, count);
263 offset += converted;
264 count -= converted;
265 out.write(work_bytes, 0, converter.count);
266 }
267 while (count > 0 || converter.havePendingBytes());
268 }
269
270 private void writeChars(String str, int offset, int count)
271 throws IOException
272 {
273 do
274 {
275 converter.setOutput(work_bytes, 0);
276 int converted = converter.write(str, offset, count, work);
277 offset += converted;
278 count -= converted;
279 out.write(work_bytes, 0, converter.count);
280 }
281 while (count > 0 || converter.havePendingBytes());
282 }
283
284 /**
285 * This methods prints a boolean value to the stream. <code>true</code>
286 * values are printed as "true" and <code>false</code> values are printed
287 * as "false".
288 *
289 * @param bool The <code>boolean</code> value to print
290 */
291 public void print (boolean bool)
292 {
293 print(String.valueOf(bool), false);
294 }
295
296 /**
297 * This method prints an integer to the stream. The value printed is
298 * determined using the <code>String.valueOf()</code> method.
299 *
300 * @param inum The <code>int</code> value to be printed
301 */
302 public void print (int inum)
303 {
304 print(String.valueOf(inum), false);
305 }
306
307 /**
308 * This method prints a long to the stream. The value printed is
309 * determined using the <code>String.valueOf()</code> method.
310 *
311 * @param lnum The <code>long</code> value to be printed
312 */
313 public void print (long lnum)
314 {
315 print(String.valueOf(lnum), false);
316 }
317
318 /**
319 * This method prints a float to the stream. The value printed is
320 * determined using the <code>String.valueOf()</code> method.
321 *
322 * @param fnum The <code>float</code> value to be printed
323 */
324 public void print (float fnum)
325 {
326 print(String.valueOf(fnum), false);
327 }
328
329 /**
330 * This method prints a double to the stream. The value printed is
331 * determined using the <code>String.valueOf()</code> method.
332 *
333 * @param dnum The <code>double</code> value to be printed
334 */
335 public void print (double dnum)
336 {
337 print(String.valueOf(dnum), false);
338 }
339
340 /**
341 * This method prints an <code>Object</code> to the stream. The actual
342 * value printed is determined by calling the <code>String.valueOf()</code>
343 * method.
344 *
345 * @param obj The <code>Object</code> to print.
346 */
347 public void print (Object obj)
348 {
349 print(obj == null ? "null" : obj.toString(), false);
350 }
351
352 /**
353 * This method prints a <code>String</code> to the stream. The actual
354 * value printed depends on the system default encoding.
355 *
356 * @param str The <code>String</code> to print.
357 */
358 public void print (String str)
359 {
360 print(str == null ? "null" : str, false);
361 }
362
363 /**
364 * This method prints a char to the stream. The actual value printed is
365 * determined by the character encoding in use.
366 *
367 * @param ch The <code>char</code> value to be printed
368 */
369 public synchronized void print (char ch)
370 {
371 work[0] = ch;
372 print(work, 0, 1, false);
373 }
374
375 /**
376 * This method prints an array of characters to the stream. The actual
377 * value printed depends on the system default encoding.
378 *
379 * @param charArray The array of characters to print.
380 */
381 public void print (char[] charArray)
382 {
383 print(charArray, 0, charArray.length, false);
384 }
385
386 /**
387 * This method prints a line separator sequence to the stream. The value
388 * printed is determined by the system property <xmp>line.separator</xmp>
389 * and is not necessarily the Unix '\n' newline character.
390 */
391 public void println ()
392 {
393 print(line_separator, 0, line_separator.length, false);
394 }
395
396 /**
397 * This methods prints a boolean value to the stream. <code>true</code>
398 * values are printed as "true" and <code>false</code> values are printed
399 * as "false".
400 * <p>
401 * This method prints a line termination sequence after printing the value.
402 *
403 * @param bool The <code>boolean</code> value to print
404 */
405 public void println (boolean bool)
406 {
407 print(String.valueOf(bool), true);
408 }
409
410 /**
411 * This method prints an integer to the stream. The value printed is
412 * determined using the <code>String.valueOf()</code> method.
413 * <p>
414 * This method prints a line termination sequence after printing the value.
415 *
416 * @param inum The <code>int</code> value to be printed
417 */
418 public void println (int inum)
419 {
420 print(String.valueOf(inum), true);
421 }
422
423 /**
424 * This method prints a long to the stream. The value printed is
425 * determined using the <code>String.valueOf()</code> method.
426 * <p>
427 * This method prints a line termination sequence after printing the value.
428 *
429 * @param lnum The <code>long</code> value to be printed
430 */
431 public void println (long lnum)
432 {
433 print(String.valueOf(lnum), true);
434 }
435
436 /**
437 * This method prints a float to the stream. The value printed is
438 * determined using the <code>String.valueOf()</code> method.
439 * <p>
440 * This method prints a line termination sequence after printing the value.
441 *
442 * @param fnum The <code>float</code> value to be printed
443 */
444 public void println (float fnum)
445 {
446 print(String.valueOf(fnum), true);
447 }
448
449 /**
450 * This method prints a double to the stream. The value printed is
451 * determined using the <code>String.valueOf()</code> method.
452 * <p>
453 * This method prints a line termination sequence after printing the value.
454 *
455 * @param dnum The <code>double</code> value to be printed
456 */
457 public void println (double dnum)
458 {
459 print(String.valueOf(dnum), true);
460 }
461
462 /**
463 * This method prints an <code>Object</code> to the stream. The actual
464 * value printed is determined by calling the <code>String.valueOf()</code>
465 * method.
466 * <p>
467 * This method prints a line termination sequence after printing the value.
468 *
469 * @param obj The <code>Object</code> to print.
470 */
471 public void println (Object obj)
472 {
473 print(obj == null ? "null" : obj.toString(), true);
474 }
475
476 /**
477 * This method prints a <code>String</code> to the stream. The actual
478 * value printed depends on the system default encoding.
479 * <p>
480 * This method prints a line termination sequence after printing the value.
481 *
482 * @param str The <code>String</code> to print.
483 */
484 public void println (String str)
485 {
486 print (str == null ? "null" : str, true);
487 }
488
489 /**
490 * This method prints a char to the stream. The actual value printed is
491 * determined by the character encoding in use.
492 * <p>
493 * This method prints a line termination sequence after printing the value.
494 *
495 * @param ch The <code>char</code> value to be printed
496 */
497 public synchronized void println (char ch)
498 {
499 work[0] = ch;
500 print(work, 0, 1, true);
501 }
502
503 /**
504 * This method prints an array of characters to the stream. The actual
505 * value printed depends on the system default encoding.
506 * <p>
507 * This method prints a line termination sequence after printing the value.
508 *
509 * @param charArray The array of characters to print.
510 */
511 public void println (char[] charArray)
512 {
513 print(charArray, 0, charArray.length, true);
514 }
515
516 /**
517 * This method writes a byte of data to the stream. If auto-flush is
518 * enabled, printing a newline character will cause the stream to be
519 * flushed after the character is written.
520 *
521 * @param oneByte The byte to be written
522 */
523 public void write (int oneByte)
524 {
525 try
526 {
527 out.write (oneByte & 0xff);
528
529 if (auto_flush && (oneByte == '\n'))
530 flush ();
531 }
532 catch (InterruptedIOException iioe)
533 {
534 Thread.currentThread ().interrupt ();
535 }
536 catch (IOException e)
537 {
538 setError ();
539 }
540 }
541
542 /**
543 * This method writes <code>len</code> bytes from the specified array
544 * starting at index <code>offset</code> into the array.
545 *
546 * @param buffer The array of bytes to write
547 * @param offset The index into the array to start writing from
548 * @param len The number of bytes to write
549 */
550 public void write (byte[] buffer, int offset, int len)
551 {
552 try
553 {
554 out.write (buffer, offset, len);
555
556 if (auto_flush)
557 flush ();
558 }
559 catch (InterruptedIOException iioe)
560 {
561 Thread.currentThread ().interrupt ();
562 }
563 catch (IOException e)
564 {
565 setError ();
566 }
567 }
568
569 /** @since 1.5 */
570 public PrintStream append(char c)
571 {
572 print(c);
573 return this;
574 }
575
576 /** @since 1.5 */
577 public PrintStream append(CharSequence cs)
578 {
579 print(cs == null ? "null" : cs.toString());
580 return this;
581 }
582
583 /** @since 1.5 */
584 public PrintStream append(CharSequence cs, int start, int end)
585 {
586 print(cs == null ? "null" : cs.subSequence(start, end).toString());
587 return this;
588 }
589
590 /** @since 1.5 */
591 public PrintStream printf(String format, Object... args)
592 {
593 return format(format, args);
594 }
595
596 /** @since 1.5 */
597 public PrintStream printf(Locale locale, String format, Object... args)
598 {
599 return format(locale, format, args);
600 }
601
602 /** @since 1.5 */
603 public PrintStream format(String format, Object... args)
604 {
605 return format(Locale.getDefault(), format, args);
606 }
607
608 /** @since 1.5 */
609 public PrintStream format(Locale locale, String format, Object... args)
610 {
611 Formatter f = new Formatter(this, locale);
612 f.format(format, args);
613 return this;
614 }
615 } // class PrintStream
616