1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.io;
19
20import java.util.Formatter;
21import java.util.IllegalFormatException;
22import java.util.Locale;
23
24/**
25 * Wraps either an existing {@link OutputStream} or an existing {@link Writer}
26 * and provides convenience methods for printing common data types in a human
27 * readable format. No {@code IOException} is thrown by this class. Instead,
28 * callers should use {@link #checkError()} to see if a problem has occurred in
29 * this writer.
30 */
31public class PrintWriter extends Writer {
32    /**
33     * The writer to print data to.
34     */
35    protected Writer out;
36
37    /**
38     * Indicates whether this PrintWriter is in an error state.
39     */
40    private boolean ioError;
41
42    /**
43     * Indicates whether or not this PrintWriter should flush its contents after
44     * printing a new line.
45     */
46    private boolean autoFlush;
47
48    /**
49     * Constructs a new {@code PrintWriter} with {@code out} as its target
50     * stream. By default, the new print writer does not automatically flush its
51     * contents to the target stream when a newline is encountered.
52     *
53     * @param out
54     *            the target output stream.
55     * @throws NullPointerException
56     *             if {@code out} is {@code null}.
57     */
58    public PrintWriter(OutputStream out) {
59        this(new OutputStreamWriter(out), false);
60    }
61
62    /**
63     * Constructs a new {@code PrintWriter} with {@code out} as its target
64     * stream. The parameter {@code autoFlush} determines if the print writer
65     * automatically flushes its contents to the target stream when a newline is
66     * encountered.
67     *
68     * @param out
69     *            the target output stream.
70     * @param autoFlush
71     *            indicates whether contents are flushed upon encountering a
72     *            newline sequence.
73     * @throws NullPointerException
74     *             if {@code out} is {@code null}.
75     */
76    public PrintWriter(OutputStream out, boolean autoFlush) {
77        this(new OutputStreamWriter(out), autoFlush);
78    }
79
80    /**
81     * Constructs a new {@code PrintWriter} with {@code wr} as its target
82     * writer. By default, the new print writer does not automatically flush its
83     * contents to the target writer when a newline is encountered.
84     *
85     * @param wr
86     *            the target writer.
87     * @throws NullPointerException
88     *             if {@code wr} is {@code null}.
89     */
90    public PrintWriter(Writer wr) {
91        this(wr, false);
92    }
93
94    /**
95     * Constructs a new {@code PrintWriter} with {@code out} as its target
96     * writer. The parameter {@code autoFlush} determines if the print writer
97     * automatically flushes its contents to the target writer when a newline is
98     * encountered.
99     *
100     * @param wr
101     *            the target writer.
102     * @param autoFlush
103     *            indicates whether to flush contents upon encountering a
104     *            newline sequence.
105     * @throws NullPointerException
106     *             if {@code out} is {@code null}.
107     */
108    public PrintWriter(Writer wr, boolean autoFlush) {
109        super(wr);
110        this.autoFlush = autoFlush;
111        out = wr;
112    }
113
114    /**
115     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
116     * VM's default character set is used for character encoding.
117     * The print writer does not automatically flush its contents to the target
118     * file when a newline is encountered. The output to the file is buffered.
119     *
120     * @param file
121     *            the target file. If the file already exists, its contents are
122     *            removed, otherwise a new file is created.
123     * @throws FileNotFoundException
124     *             if an error occurs while opening or creating the target file.
125     */
126    public PrintWriter(File file) throws FileNotFoundException {
127        this(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file))), false);
128    }
129
130    /**
131     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
132     * character set named {@code csn} is used for character encoding.
133     * The print writer does not automatically flush its contents to the target
134     * file when a newline is encountered. The output to the file is buffered.
135     *
136     * @param file
137     *            the target file. If the file already exists, its contents are
138     *            removed, otherwise a new file is created.
139     * @param csn
140     *            the name of the character set used for character encoding.
141     * @throws FileNotFoundException
142     *             if an error occurs while opening or creating the target file.
143     * @throws NullPointerException
144     *             if {@code csn} is {@code null}.
145     * @throws UnsupportedEncodingException
146     *             if the encoding specified by {@code csn} is not supported.
147     */
148    public PrintWriter(File file, String csn) throws FileNotFoundException,
149            UnsupportedEncodingException {
150        this(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)), csn),
151                false);
152    }
153
154    /**
155     * Constructs a new {@code PrintWriter} with the file identified by {@code
156     * fileName} as its target. The VM's default character set is
157     * used for character encoding. The print writer does not automatically
158     * flush its contents to the target file when a newline is encountered. The
159     * output to the file is buffered.
160     *
161     * @param fileName
162     *            the target file's name. If the file already exists, its
163     *            contents are removed, otherwise a new file is created.
164     * @throws FileNotFoundException
165     *             if an error occurs while opening or creating the target file.
166     */
167    public PrintWriter(String fileName) throws FileNotFoundException {
168        this(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(fileName))),
169                false);
170    }
171
172     /**
173     * Constructs a new {@code PrintWriter} with the file identified by {@code
174     * fileName} as its target. The character set named {@code csn} is used for
175     * character encoding. The print writer does not automatically flush its
176     * contents to the target file when a newline is encountered. The output to
177     * the file is buffered.
178     *
179     * @param fileName
180     *            the target file's name. If the file already exists, its
181     *            contents are removed, otherwise a new file is created.
182     * @param csn
183     *            the name of the character set used for character encoding.
184     * @throws FileNotFoundException
185     *             if an error occurs while opening or creating the target file.
186     * @throws NullPointerException
187     *             if {@code csn} is {@code null}.
188     * @throws UnsupportedEncodingException
189     *             if the encoding specified by {@code csn} is not supported.
190     */
191    public PrintWriter(String fileName, String csn)
192            throws FileNotFoundException, UnsupportedEncodingException {
193        this(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(fileName)), csn),
194                false);
195    }
196
197    /**
198     * Flushes this writer and returns the value of the error flag.
199     *
200     * @return {@code true} if either an {@code IOException} has been thrown
201     *         previously or if {@code setError()} has been called;
202     *         {@code false} otherwise.
203     * @see #setError()
204     */
205    public boolean checkError() {
206        Writer delegate = out;
207        if (delegate == null) {
208            return ioError;
209        }
210
211        flush();
212        return ioError || delegate.checkError();
213    }
214
215    /**
216     * Sets the error state of the stream to false.
217     * @since 1.6
218     */
219    protected void clearError() {
220        synchronized (lock) {
221            ioError = false;
222        }
223    }
224
225    /**
226     * Closes this print writer. Flushes this writer and then closes the target.
227     * If an I/O error occurs, this writer's error flag is set to {@code true}.
228     */
229    @Override
230    public void close() {
231        synchronized (lock) {
232            if (out != null) {
233                try {
234                    out.close();
235                } catch (IOException e) {
236                    setError();
237                }
238                out = null;
239            }
240        }
241    }
242
243    /**
244     * Ensures that all pending data is sent out to the target. It also
245     * flushes the target. If an I/O error occurs, this writer's error
246     * state is set to {@code true}.
247     */
248    @Override
249    public void flush() {
250        synchronized (lock) {
251            if (out != null) {
252                try {
253                    out.flush();
254                } catch (IOException e) {
255                    setError();
256                }
257            } else {
258                setError();
259            }
260        }
261    }
262
263    /**
264     * Formats {@code args} according to the format string {@code format}, and writes the result
265     * to this stream. This method uses the user's default locale.
266     * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
267     * If automatic flushing is enabled then the buffer is flushed as well.
268     *
269     * @param format the format string (see {@link java.util.Formatter#format})
270     * @param args
271     *            the list of arguments passed to the formatter. If there are
272     *            more arguments than required by {@code format},
273     *            additional arguments are ignored.
274     * @return this writer.
275     * @throws IllegalFormatException
276     *             if the format string is illegal or incompatible with the
277     *             arguments, if there are not enough arguments or if any other
278     *             error regarding the format string or arguments is detected.
279     * @throws NullPointerException if {@code format == null}
280     */
281    public PrintWriter format(String format, Object... args) {
282        return format(Locale.getDefault(), format, args);
283    }
284
285    /**
286     * Writes a string formatted by an intermediate {@code Formatter} to the
287     * target using the specified locale, format string and arguments. If
288     * automatic flushing is enabled then this writer is flushed.
289     *
290     * @param l
291     *            the locale used in the method. No localization will be applied
292     *            if {@code l} is {@code null}.
293     * @param format the format string (see {@link java.util.Formatter#format})
294     * @param args
295     *            the list of arguments passed to the formatter. If there are
296     *            more arguments than required by {@code format},
297     *            additional arguments are ignored.
298     * @return this writer.
299     * @throws IllegalFormatException
300     *             if the format string is illegal or incompatible with the
301     *             arguments, if there are not enough arguments or if any other
302     *             error regarding the format string or arguments is detected.
303     * @throws NullPointerException if {@code format == null}
304     */
305    public PrintWriter format(Locale l, String format, Object... args) {
306        if (format == null) {
307            throw new NullPointerException("format == null");
308        }
309        new Formatter(this, l).format(format, args);
310        if (autoFlush) {
311            flush();
312        }
313        return this;
314    }
315
316    /**
317     * Prints a formatted string. The behavior of this method is the same as
318     * this writer's {@code #format(String, Object...)} method.
319     *
320     * <p>The {@code Locale} used is the user's default locale.
321     * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
322     *
323     * @param format the format string (see {@link java.util.Formatter#format})
324     * @param args
325     *            the list of arguments passed to the formatter. If there are
326     *            more arguments than required by {@code format},
327     *            additional arguments are ignored.
328     * @return this writer.
329     * @throws IllegalFormatException
330     *             if the format string is illegal or incompatible with the
331     *             arguments, if there are not enough arguments or if any other
332     *             error regarding the format string or arguments is detected.
333     * @throws NullPointerException if {@code format == null}
334     */
335    public PrintWriter printf(String format, Object... args) {
336        return format(format, args);
337    }
338
339    /**
340     * Prints a formatted string. The behavior of this method is the same as
341     * this writer's {@code #format(Locale, String, Object...)} method.
342     *
343     * @param l
344     *            the locale used in the method. No localization will be applied
345     *            if {@code l} is {@code null}.
346     * @param format the format string (see {@link java.util.Formatter#format})
347     * @param args
348     *            the list of arguments passed to the formatter. If there are
349     *            more arguments than required by {@code format},
350     *            additional arguments are ignored.
351     * @return this writer.
352     * @throws IllegalFormatException
353     *             if the format string is illegal or incompatible with the
354     *             arguments, if there are not enough arguments or if any other
355     *             error regarding the format string or arguments is detected.
356     * @throws NullPointerException if {@code format == null}
357     */
358    public PrintWriter printf(Locale l, String format, Object... args) {
359        return format(l, format, args);
360    }
361
362    /**
363     * Prints the string representation of the specified character array
364     * to the target.
365     *
366     * @param charArray
367     *            the character array to print to the target.
368     * @see #print(String)
369     */
370    public void print(char[] charArray) {
371        print(new String(charArray, 0, charArray.length));
372    }
373
374    /**
375     * Prints the string representation of the specified character to the
376     * target.
377     *
378     * @param ch
379     *            the character to print to the target.
380     * @see #print(String)
381     */
382    public void print(char ch) {
383        print(String.valueOf(ch));
384    }
385
386    /**
387     * Prints the string representation of the specified double to the target.
388     *
389     * @param dnum
390     *            the double value to print to the target.
391     * @see #print(String)
392     */
393    public void print(double dnum) {
394        print(String.valueOf(dnum));
395    }
396
397    /**
398     * Prints the string representation of the specified float to the target.
399     *
400     * @param fnum
401     *            the float value to print to the target.
402     * @see #print(String)
403     */
404    public void print(float fnum) {
405        print(String.valueOf(fnum));
406    }
407
408    /**
409     * Prints the string representation of the specified integer to the target.
410     *
411     * @param inum
412     *            the integer value to print to the target.
413     * @see #print(String)
414     */
415    public void print(int inum) {
416        print(String.valueOf(inum));
417    }
418
419    /**
420     * Prints the string representation of the specified long to the target.
421     *
422     * @param lnum
423     *            the long value to print to the target.
424     * @see #print(String)
425     */
426    public void print(long lnum) {
427        print(String.valueOf(lnum));
428    }
429
430    /**
431     * Prints the string representation of the specified object to the target.
432     *
433     * @param obj
434     *            the object to print to the target.
435     * @see #print(String)
436     */
437    public void print(Object obj) {
438        print(String.valueOf(obj));
439    }
440
441    /**
442     * Prints a string to the target. The string is converted to an array of
443     * bytes using the encoding chosen during the construction of this writer.
444     * The bytes are then written to the target with {@code write(int)}.
445     * <p>
446     * If an I/O error occurs, this writer's error flag is set to {@code true}.
447     *
448     * @param str
449     *            the string to print to the target.
450     * @see #write(int)
451     */
452    public void print(String str) {
453        write(str != null ? str : String.valueOf((Object) null));
454    }
455
456    /**
457     * Prints the string representation of the specified boolean to the target.
458     *
459     * @param bool
460     *            the boolean value to print the target.
461     * @see #print(String)
462     */
463    public void print(boolean bool) {
464        print(String.valueOf(bool));
465    }
466
467    /**
468     * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}.
469     */
470    public void println() {
471        synchronized (lock) {
472            print(System.lineSeparator());
473            if (autoFlush) {
474                flush();
475            }
476        }
477    }
478
479    /**
480     * Prints the string representation of the character array {@code chars} followed by a newline.
481     * Flushes this writer if the autoFlush flag is set to {@code true}.
482     */
483    public void println(char[] chars) {
484        println(new String(chars, 0, chars.length));
485    }
486
487    /**
488     * Prints the string representation of the char {@code c} followed by a newline.
489     * Flushes this writer if the autoFlush flag is set to {@code true}.
490     */
491    public void println(char c) {
492        println(String.valueOf(c));
493    }
494
495    /**
496     * Prints the string representation of the double {@code d} followed by a newline.
497     * Flushes this writer if the autoFlush flag is set to {@code true}.
498     */
499    public void println(double d) {
500        println(String.valueOf(d));
501    }
502
503    /**
504     * Prints the string representation of the float {@code f} followed by a newline.
505     * Flushes this writer if the autoFlush flag is set to {@code true}.
506     */
507    public void println(float f) {
508        println(String.valueOf(f));
509    }
510
511    /**
512     * Prints the string representation of the int {@code i} followed by a newline.
513     * Flushes this writer if the autoFlush flag is set to {@code true}.
514     */
515    public void println(int i) {
516        println(String.valueOf(i));
517    }
518
519    /**
520     * Prints the string representation of the long {@code l} followed by a newline.
521     * Flushes this writer if the autoFlush flag is set to {@code true}.
522     */
523    public void println(long l) {
524        println(String.valueOf(l));
525    }
526
527    /**
528     * Prints the string representation of the object {@code o}, or {@code "null},
529     * followed by a newline.
530     * Flushes this writer if the autoFlush flag is set to {@code true}.
531     */
532    public void println(Object obj) {
533        println(String.valueOf(obj));
534    }
535
536    /**
537     * Prints the string representation of the string {@code s} followed by a newline.
538     * Flushes this writer if the autoFlush flag is set to {@code true}.
539     *
540     * <p>The string is converted to an array of bytes using the
541     * encoding chosen during the construction of this writer. The bytes are
542     * then written to the target with {@code write(int)}. Finally, this writer
543     * is flushed if the autoFlush flag is set to {@code true}.
544     *
545     * <p>If an I/O error occurs, this writer's error flag is set to {@code true}.
546     */
547    public void println(String str) {
548        synchronized (lock) {
549            print(str);
550            println();
551        }
552    }
553
554    /**
555     * Prints the string representation of the boolean {@code b} followed by a newline.
556     * Flushes this writer if the autoFlush flag is set to {@code true}.
557     */
558    public void println(boolean b) {
559        println(String.valueOf(b));
560    }
561
562    /**
563     * Sets the error flag of this writer to true.
564     */
565    protected void setError() {
566        synchronized (lock) {
567            ioError = true;
568        }
569    }
570
571    /**
572     * Writes the character buffer {@code buf} to the target.
573     *
574     * @param buf
575     *            the non-null array containing characters to write.
576     */
577    @Override
578    public void write(char[] buf) {
579        write(buf, 0, buf.length);
580    }
581
582    /**
583     * Writes {@code count} characters from {@code buffer} starting at {@code
584     * offset} to the target.
585     * <p>
586     * This writer's error flag is set to {@code true} if this writer is closed
587     * or an I/O error occurs.
588     *
589     * @param buf
590     *            the buffer to write to the target.
591     * @param offset
592     *            the index of the first character in {@code buffer} to write.
593     * @param count
594     *            the number of characters in {@code buffer} to write.
595     * @throws IndexOutOfBoundsException
596     *             if {@code offset < 0} or {@code count < 0}, or if {@code
597     *             offset + count} is greater than the length of {@code buf}.
598     */
599    @Override
600    public void write(char[] buf, int offset, int count) {
601        doWrite(buf, offset, count);
602    }
603
604    /**
605     * Writes one character to the target. Only the two least significant bytes
606     * of the integer {@code oneChar} are written.
607     * <p>
608     * This writer's error flag is set to {@code true} if this writer is closed
609     * or an I/O error occurs.
610     *
611     * @param oneChar
612     *            the character to write to the target.
613     */
614    @Override
615    public void write(int oneChar) {
616        doWrite(new char[] { (char) oneChar }, 0, 1);
617    }
618
619    private final void doWrite(char[] buf, int offset, int count) {
620        synchronized (lock) {
621            if (out != null) {
622                try {
623                    out.write(buf, offset, count);
624                } catch (IOException e) {
625                    setError();
626                }
627            } else {
628                setError();
629            }
630        }
631    }
632
633    /**
634     * Writes the characters from the specified string to the target.
635     *
636     * @param str
637     *            the non-null string containing the characters to write.
638     */
639    @Override
640    public void write(String str) {
641        write(str.toCharArray());
642    }
643
644    /**
645     * Writes {@code count} characters from {@code str} starting at {@code
646     * offset} to the target.
647     *
648     * @param str
649     *            the non-null string containing the characters to write.
650     * @param offset
651     *            the index of the first character in {@code str} to write.
652     * @param count
653     *            the number of characters from {@code str} to write.
654     * @throws IndexOutOfBoundsException
655     *             if {@code offset < 0} or {@code count < 0}, or if {@code
656     *             offset + count} is greater than the length of {@code str}.
657     */
658    @Override
659    public void write(String str, int offset, int count) {
660        write(str.substring(offset, offset + count).toCharArray());
661    }
662
663    /**
664     * Appends the character {@code c} to the target.
665     *
666     * @param c
667     *            the character to append to the target.
668     * @return this writer.
669     */
670    @Override
671    public PrintWriter append(char c) {
672        write(c);
673        return this;
674    }
675
676    /**
677     * Appends the character sequence {@code csq} to the target. This
678     * method works the same way as {@code PrintWriter.print(csq.toString())}.
679     * If {@code csq} is {@code null}, then the string "null" is written
680     * to the target.
681     *
682     * @param csq
683     *            the character sequence appended to the target.
684     * @return this writer.
685     */
686    @Override
687    public PrintWriter append(CharSequence csq) {
688        if (csq == null) {
689            csq = "null";
690        }
691        append(csq, 0, csq.length());
692        return this;
693    }
694
695    /**
696     * Appends a subsequence of the character sequence {@code csq} to the
697     * target. This method works the same way as {@code
698     * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code
699     * csq} is {@code null}, then the specified subsequence of the string "null"
700     * will be written to the target.
701     *
702     * @param csq
703     *            the character sequence appended to the target.
704     * @param start
705     *            the index of the first char in the character sequence appended
706     *            to the target.
707     * @param end
708     *            the index of the character following the last character of the
709     *            subsequence appended to the target.
710     * @return this writer.
711     * @throws StringIndexOutOfBoundsException
712     *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
713     *             either {@code start} or {@code end} are greater or equal than
714     *             the length of {@code csq}.
715     */
716    @Override
717    public PrintWriter append(CharSequence csq, int start, int end) {
718        if (csq == null) {
719            csq = "null";
720        }
721        String output = csq.subSequence(start, end).toString();
722        write(output, 0, output.length());
723        return this;
724    }
725}
726