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 initializes a new <code>PrintStream</code> object to write
127       * to the specified output File. Doesn't autoflush.
128       *
129       * @param file The <code>File</code> to write to.
130       * @throws FileNotFoundException if an error occurs while opening the file.
131       *
132       * @since 1.5
133       */
134      public PrintStream (File file)
135        throws FileNotFoundException
136      {
137        this (new FileOutputStream(file), false);
138      }
139    
140      /**
141       * This method initializes a new <code>PrintStream</code> object to write
142       * to the specified output File. Doesn't autoflush.
143       *
144       * @param file The <code>File</code> to write to.
145       * @param encoding The name of the character encoding to use for this
146       * object.
147       * @throws FileNotFoundException If an error occurs while opening the file.
148       * @throws UnsupportedEncodingException If the charset specified by
149       * <code>encoding</code> is invalid.
150       *
151       * @since 1.5
152       */
153      public PrintStream (File file, String encoding)
154        throws FileNotFoundException,UnsupportedEncodingException
155      {
156        this (new FileOutputStream(file), false, encoding);
157      }
158    
159      /**
160       * This method initializes a new <code>PrintStream</code> object to write
161       * to the specified output File. Doesn't autoflush.
162       *
163       * @param fileName The name of the <code>File</code> to write to.
164       * @throws FileNotFoundException if an error occurs while opening the file,
165       *
166       * @since 1.5
167       */
168      public PrintStream (String fileName)
169        throws FileNotFoundException
170      {
171        this (new FileOutputStream(new File(fileName)), false);
172      }
173    
174      /**
175       * This method initializes a new <code>PrintStream</code> object to write
176       * to the specified output File. Doesn't autoflush.
177       *
178       * @param fileName The name of the <code>File</code> to write to.
179       * @param encoding The name of the character encoding to use for this
180       * object.
181       * @throws FileNotFoundException if an error occurs while opening the file.
182       * @throws UnsupportedEncodingException If the charset specified by
183       * <code>encoding</code> is invalid.
184       *
185       * @since 1.5
186       */
187      public PrintStream (String fileName, String encoding)
188          throws FileNotFoundException,UnsupportedEncodingException
189      {
190        this (new FileOutputStream(new File(fileName)), false, encoding);
191      }
192    
193      /**
194       * This method intializes a new <code>PrintStream</code> object to write
195       * to the specified output sink.  This constructor also allows "auto-flush"
196       * functionality to be specified where the stream will be flushed after
197       * every <code>print</code> or <code>println</code> call, when the 
198       * <code>write</code> methods with array arguments are called, or when a 
199       * single new-line character is written.
200       * <p>
201       *
202       * @param out The <code>OutputStream</code> to write to.
203       * @param auto_flush <code>true</code> to flush the stream after every 
204       * line, <code>false</code> otherwise
205       * @param encoding The name of the character encoding to use for this
206       * object.
207       */
208      public PrintStream (OutputStream out, boolean auto_flush, String encoding)
209        throws UnsupportedEncodingException
210      {
211        super (out);
212    
213        converter = UnicodeToBytes.getEncoder (encoding);
214        this.auto_flush = auto_flush;
215      }
216    
217      /**
218       * This method checks to see if an error has occurred on this stream.  Note
219       * that once an error has occurred, this method will continue to report
220       * <code>true</code> forever for this stream.  Before checking for an
221       * error condition, this method flushes the stream.
222       *
223       * @return <code>true</code> if an error has occurred, 
224       * <code>false</code> otherwise
225       */
226      public boolean checkError ()
227      {
228        flush ();
229        return error_occurred;
230      }
231    
232      /**
233       * This method can be called by subclasses to indicate that an error
234       * has occurred and should be reported by <code>checkError</code>.
235       */
236      protected void setError ()
237      {
238        error_occurred = true;
239      }
240    
241      /**
242       * This method closes this stream and all underlying streams.
243       */
244      public void close ()
245      {
246        try
247          {
248            converter.setFinished();
249            writeChars(new char[0], 0, 0);
250            flush();
251            out.close();
252          }
253        catch (InterruptedIOException iioe)
254          {
255            Thread.currentThread().interrupt();
256          }
257        catch (IOException e)
258          {
259            setError ();
260          }
261      }
262    
263      /**
264       * This method flushes any buffered bytes to the underlying stream and
265       * then flushes that stream as well.
266       */
267      public void flush ()
268      {
269        try
270          {
271            out.flush();
272          }
273        catch (InterruptedIOException iioe)
274          {
275            Thread.currentThread().interrupt();
276          }
277        catch (IOException e)
278          {
279            setError ();
280          }
281      }
282    
283      private synchronized void print (String str, boolean println)
284      {
285        try
286          {
287            writeChars(str, 0, str.length());
288            if (println)
289              writeChars(line_separator, 0, line_separator.length);
290            if (auto_flush)
291              flush();
292          }
293        catch (InterruptedIOException iioe)
294          {
295            Thread.currentThread().interrupt();
296          }
297        catch (IOException e)
298          {
299            setError ();
300          }
301      }
302    
303      private synchronized void print (char[] chars, int pos, int len,
304                                       boolean println)
305      {
306        try
307          {
308            writeChars(chars, pos, len);
309            if (println)
310              writeChars(line_separator, 0, line_separator.length);
311            if (auto_flush)
312              flush();
313          }
314        catch (InterruptedIOException iioe)
315          {
316            Thread.currentThread().interrupt();
317          }
318        catch (IOException e)
319          {
320            setError ();
321          }
322      }
323    
324      private void writeChars(char[] buf, int offset, int count)
325        throws IOException
326      {
327        do
328          {
329            converter.setOutput(work_bytes, 0);
330            int converted = converter.write(buf, offset, count);
331            offset += converted;
332            count -= converted;
333            out.write(work_bytes, 0, converter.count);
334          }
335        while (count > 0 || converter.havePendingBytes());
336      }
337    
338      private void writeChars(String str, int offset, int count)
339        throws IOException
340      {
341        do
342          {
343            converter.setOutput(work_bytes, 0);
344            int converted = converter.write(str, offset, count, work);
345            offset += converted;
346            count -= converted;
347            out.write(work_bytes, 0, converter.count);
348          }
349        while (count > 0 || converter.havePendingBytes());
350      }
351    
352      /**
353       * This methods prints a boolean value to the stream.  <code>true</code>
354       * values are printed as "true" and <code>false</code> values are printed
355       * as "false".
356       *
357       * @param bool The <code>boolean</code> value to print
358       */
359      public void print (boolean bool)
360      {
361        print(String.valueOf(bool), false);
362      }
363    
364      /**
365       * This method prints an integer to the stream.  The value printed is
366       * determined using the <code>String.valueOf()</code> method.
367       *
368       * @param inum The <code>int</code> value to be printed
369       */
370      public void print (int inum)
371      {
372        print(String.valueOf(inum), false);
373      }
374    
375      /**
376       * This method prints a long to the stream.  The value printed is
377       * determined using the <code>String.valueOf()</code> method.
378       *
379       * @param lnum The <code>long</code> value to be printed
380       */
381      public void print (long lnum)
382      {
383        print(String.valueOf(lnum), false);
384      }
385    
386      /**
387       * This method prints a float to the stream.  The value printed is
388       * determined using the <code>String.valueOf()</code> method.
389       *
390       * @param fnum The <code>float</code> value to be printed
391       */
392      public void print (float fnum)
393      {
394        print(String.valueOf(fnum), false);
395      }
396    
397      /**
398       * This method prints a double to the stream.  The value printed is
399       * determined using the <code>String.valueOf()</code> method.
400       *
401       * @param dnum The <code>double</code> value to be printed
402       */
403      public void print (double dnum)
404      {
405        print(String.valueOf(dnum), false);
406      }
407    
408      /**
409       * This method prints an <code>Object</code> to the stream.  The actual
410       * value printed is determined by calling the <code>String.valueOf()</code>
411       * method.
412       *
413       * @param obj The <code>Object</code> to print.
414       */
415      public void print (Object obj)
416      {
417        print(obj == null ? "null" : obj.toString(), false);
418      }
419    
420      /**
421       * This method prints a <code>String</code> to the stream.  The actual
422       * value printed depends on the system default encoding.
423       *
424       * @param str The <code>String</code> to print.
425       */
426      public void print (String str)
427      {
428        print(str == null ? "null" : str, false);
429      }
430    
431      /**
432       * This method prints a char to the stream.  The actual value printed is
433       * determined by the character encoding in use.
434       *
435       * @param ch The <code>char</code> value to be printed
436       */
437      public synchronized void print (char ch)
438      {
439        work[0] = ch;
440        print(work, 0, 1, false);
441      }
442    
443      /**
444       * This method prints an array of characters to the stream.  The actual
445       * value printed depends on the system default encoding.
446       *
447       * @param charArray The array of characters to print.
448       */
449      public void print (char[] charArray)
450      {
451        print(charArray, 0, charArray.length, false);
452      }
453    
454      /**
455       * This method prints a line separator sequence to the stream.  The value
456       * printed is determined by the system property <xmp>line.separator</xmp>
457       * and is not necessarily the Unix '\n' newline character.
458       */
459      public void println ()
460      {
461        print(line_separator, 0, line_separator.length, false);
462      }
463    
464      /**
465       * This methods prints a boolean value to the stream.  <code>true</code>
466       * values are printed as "true" and <code>false</code> values are printed
467       * as "false".
468       * <p>
469       * This method prints a line termination sequence after printing the value.
470       *
471       * @param bool The <code>boolean</code> value to print
472       */
473      public void println (boolean bool)
474      {
475        print(String.valueOf(bool), true);
476      }
477    
478      /**
479       * This method prints an integer to the stream.  The value printed is
480       * determined using the <code>String.valueOf()</code> method.
481       * <p>
482       * This method prints a line termination sequence after printing the value.
483       *
484       * @param inum The <code>int</code> value to be printed
485       */
486      public void println (int inum)
487      {
488        print(String.valueOf(inum), true);
489      }
490    
491      /**
492       * This method prints a long to the stream.  The value printed is
493       * determined using the <code>String.valueOf()</code> method.
494       * <p>
495       * This method prints a line termination sequence after printing the value.
496       *
497       * @param lnum The <code>long</code> value to be printed
498       */
499      public void println (long lnum)
500      {
501        print(String.valueOf(lnum), true);
502      }
503    
504      /**
505       * This method prints a float to the stream.  The value printed is
506       * determined using the <code>String.valueOf()</code> method.
507       * <p>
508       * This method prints a line termination sequence after printing the value.
509       *
510       * @param fnum The <code>float</code> value to be printed
511       */
512      public void println (float fnum)
513      {
514        print(String.valueOf(fnum), true);
515      }
516    
517      /**
518       * This method prints a double to the stream.  The value printed is
519       * determined using the <code>String.valueOf()</code> method.
520       * <p>
521       * This method prints a line termination sequence after printing the value.
522       *
523       * @param dnum The <code>double</code> value to be printed
524       */
525      public void println (double dnum)
526      {
527        print(String.valueOf(dnum), true);
528      }
529    
530      /**
531       * This method prints an <code>Object</code> to the stream.  The actual
532       * value printed is determined by calling the <code>String.valueOf()</code>
533       * method.
534       * <p>
535       * This method prints a line termination sequence after printing the value.
536       *
537       * @param obj The <code>Object</code> to print.
538       */
539      public void println (Object obj)
540      {
541        print(obj == null ? "null" : obj.toString(), true);
542      }
543    
544      /**
545       * This method prints a <code>String</code> to the stream.  The actual
546       * value printed depends on the system default encoding.
547       * <p>
548       * This method prints a line termination sequence after printing the value.
549       *
550       * @param str The <code>String</code> to print.
551       */
552      public void println (String str)
553      {
554        print (str == null ? "null" : str, true);
555      }
556    
557      /**
558       * This method prints a char to the stream.  The actual value printed is
559       * determined by the character encoding in use.
560       * <p>
561       * This method prints a line termination sequence after printing the value.
562       *
563       * @param ch The <code>char</code> value to be printed
564       */
565      public synchronized void println (char ch)
566      {
567        work[0] = ch;
568        print(work, 0, 1, true);
569      }
570    
571      /**
572       * This method prints an array of characters to the stream.  The actual
573       * value printed depends on the system default encoding.
574       * <p>
575       * This method prints a line termination sequence after printing the value.
576       *
577       * @param charArray The array of characters to print.
578       */
579      public void println (char[] charArray)
580      {
581        print(charArray, 0, charArray.length, true);
582      }
583    
584      /**
585       * This method writes a byte of data to the stream.  If auto-flush is
586       * enabled, printing a newline character will cause the stream to be
587       * flushed after the character is written.
588       * 
589       * @param oneByte The byte to be written
590       */
591      public void write (int oneByte)
592      {
593        try
594          {
595            out.write (oneByte & 0xff);
596            
597            if (auto_flush && (oneByte == '\n'))
598              flush ();
599          }
600        catch (InterruptedIOException iioe)
601          {
602            Thread.currentThread ().interrupt ();
603          }
604        catch (IOException e)
605          {
606            setError ();
607          }
608      }
609    
610      /**
611       * This method writes <code>len</code> bytes from the specified array
612       * starting at index <code>offset</code> into the array.
613       *
614       * @param buffer The array of bytes to write
615       * @param offset The index into the array to start writing from
616       * @param len The number of bytes to write
617       */
618      public void write (byte[] buffer, int offset, int len)
619      {
620        try
621          {
622            out.write (buffer, offset, len);
623            
624            if (auto_flush)
625              flush ();
626          }
627        catch (InterruptedIOException iioe)
628          {
629            Thread.currentThread ().interrupt ();
630          }
631        catch (IOException e)
632          {
633            setError ();
634          }
635      }
636    
637      /** @since 1.5 */
638      public PrintStream append(char c)
639      {
640        print(c);
641        return this;
642      }
643    
644      /** @since 1.5 */
645      public PrintStream append(CharSequence cs)
646      {
647        print(cs == null ? "null" : cs.toString());
648        return this;
649      }
650    
651      /** @since 1.5 */
652      public PrintStream append(CharSequence cs, int start, int end)
653      {
654        print(cs == null ? "null" : cs.subSequence(start, end).toString());
655        return this;
656      }
657    
658      /** @since 1.5 */
659      public PrintStream printf(String format, Object... args)
660      {
661        return format(format, args);
662      }
663    
664      /** @since 1.5 */
665      public PrintStream printf(Locale locale, String format, Object... args)
666      {
667        return format(locale, format, args);
668      }
669    
670      /** @since 1.5 */
671      public PrintStream format(String format, Object... args)
672      {
673        return format(Locale.getDefault(), format, args);
674      }
675    
676      /** @since 1.5 */
677      public PrintStream format(Locale locale, String format, Object... args)
678      {
679        Formatter f = new Formatter(this, locale);
680        f.format(format, args);
681        return this;
682      }
683    } // class PrintStream
684