001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: import java.security.AccessController;
021: import java.util.Formatter;
022: import java.util.IllegalFormatException;
023: import java.util.Locale;
024:
025: import org.apache.harmony.luni.util.Msg;
026: import org.apache.harmony.luni.util.PriviAction;
027:
028: /**
029: * PrintWriter is a class which takes either an OutputStream or Writer and
030: * provides convenience methods for printing common data types in a human
031: * readable format on the stream. No IOExceptions are thrown by this class.
032: * Instead, callers should call checkError() to see if a problem has been
033: * encountered in this Writer.
034: */
035: public class PrintWriter extends Writer {
036: /**
037: * The writer to output data to.
038: */
039: protected Writer out;
040:
041: /**
042: * indicates whether or not this PrintWriter has incurred an error.
043: */
044: private boolean ioError;
045:
046: /**
047: * indicates whether or not this PrintWriter should flush its contents after
048: * printing a new line.
049: */
050: private boolean autoflush;
051:
052: private final String lineSeparator = AccessController
053: .doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$
054:
055: /**
056: * Constructs a new PrintWriter on the OutputStream <code>out</code>. All
057: * writes to the target can now take place through this PrintWriter. By
058: * default, the PrintWriter is set to not autoflush when println() is
059: * called.
060: *
061: * @param out
062: * the the OutputStream to provide convenience methods on.
063: */
064: public PrintWriter(OutputStream out) {
065: this (new OutputStreamWriter(out), false);
066: }
067:
068: /**
069: * Constructs a new PrintWriter on the OutputStream <code>out</code>. All
070: * writes to the target can now take place through this PrintWriter. By
071: * default, the PrintWriter is set to not autoflush when println() is
072: * called.
073: *
074: * @param out
075: * the the OutputStream to provide convenience methods on.
076: * @param autoflush
077: * whether to flush when println() is called.
078: */
079: public PrintWriter(OutputStream out, boolean autoflush) {
080: this (new OutputStreamWriter(out), autoflush);
081: }
082:
083: /**
084: * Constructs a new PrintWriter on the Writer <code>wr</code>. All writes
085: * to the target can now take place through this PrintWriter. By default,
086: * the PrintWriter is set to not autoflush when println() is called.
087: *
088: * @param wr
089: * the Writer to provide convenience methods on.
090: */
091: public PrintWriter(Writer wr) {
092: this (wr, false);
093: }
094:
095: /**
096: * Constructs a new PrintWriter on the given writer. All writes to the
097: * target can now take place through this PrintWriter. By default, the
098: * PrintWriter is set to not autoflush when println() is called.
099: *
100: * @param wr
101: * the Writer to provide convenience methods on.
102: * @param autoflush
103: * whether to flush when println() is called.
104: */
105: public PrintWriter(Writer wr, boolean autoflush) {
106: super (wr);
107: this .autoflush = autoflush;
108: out = wr;
109: }
110:
111: /**
112: * Constructs a new PrintWriter on the File <code>file</code>. The
113: * automatic flushing is set to <code>false</code>. An intermediate
114: * <code>OutputStreamWriter</code> will use the default for the current
115: * JVM instance charset to encode characters.
116: *
117: * @param file
118: * This writer's buffered destination.
119: * @throws FileNotFoundException
120: * If there is no such a file or some other error occurs due to
121: * the given file opening.
122: */
123: public PrintWriter(File file) throws FileNotFoundException {
124: this (new OutputStreamWriter(new BufferedOutputStream(
125: new FileOutputStream(file))), false);
126: }
127:
128: /**
129: * Constructs a new PrintWriter on the File <code>file</code>. The
130: * automatic flushing is set to <code>false</code>. An intermediate
131: * <code>OutputStreamWriter</code> will use a charset with the given name
132: * <code>csn</code> to encode characters.
133: *
134: * @param file
135: * This writer's buffered destination.
136: * @param csn
137: * A charset name.
138: * @throws FileNotFoundException
139: * If there is no such a file or some other error occurs due to
140: * the given file opening.
141: * @throws UnsupportedEncodingException
142: * If a charset with the given name is not supported.
143: */
144: public PrintWriter(File file, String csn)
145: throws FileNotFoundException, UnsupportedEncodingException {
146: this (new OutputStreamWriter(new BufferedOutputStream(
147: new FileOutputStream(file)), csn), false);
148: }
149:
150: /**
151: * Constructs a new PrintWriter on a file with the given file name
152: * <code>fileName</code>. The automatic flushing is set to
153: * <code>false</code>. An intermediate <code>OutputStreamWriter</code>
154: * will use the default for the current JVM instance charset to encode
155: * characters.
156: *
157: * @param fileName
158: * The name of file which is this writer's buffered destination.
159: * @throws FileNotFoundException
160: * If there is no such a file or some other error occurs due to
161: * the given file opening.
162: */
163: public PrintWriter(String fileName) throws FileNotFoundException {
164: this (new OutputStreamWriter(new BufferedOutputStream(
165: new FileOutputStream(fileName))), false);
166: }
167:
168: /**
169: * Constructs a new PrintWriter on a file with the given file name
170: * <code>fileName</code>. The automatic flushing is set to
171: * <code>false</code>. An intermediate <code>OutputStreamWriter</code>
172: * will use a charset with the given name <code>csn</code> to encode
173: * characters.
174: *
175: * @param fileName
176: * The name of file which is this writer's buffered destination.
177: * @param csn
178: * A charset name.
179: * @throws FileNotFoundException
180: * If there is no such a file or some other error occurs due to
181: * the given file opening.
182: * @throws UnsupportedEncodingException
183: * If a charset with the given name is not supported.
184: */
185: public PrintWriter(String fileName, String csn)
186: throws FileNotFoundException, UnsupportedEncodingException {
187: this (new OutputStreamWriter(new BufferedOutputStream(
188: new FileOutputStream(fileName)), csn), false);
189: }
190:
191: /**
192: * Answers a boolean indicating whether or not this PrintWriter has
193: * encountered an error. If so, the receiver should probably be closed since
194: * further writes will not actually take place. A side effect of calling
195: * checkError is that the target Writer is flushed.
196: *
197: * @return boolean has an error occurred in this PrintWriter.
198: */
199: public boolean checkError() {
200: if (out != null) {
201: flush();
202: }
203: return ioError;
204: }
205:
206: /**
207: * Close this PrintWriter. This implementation flushes and then closes the
208: * target writer. If an error occurs, set an error in this PrintWriter to
209: * <code>true</code>.
210: */
211: @Override
212: public void close() {
213: synchronized (lock) {
214: if (out != null) {
215: try {
216: out.close();
217: } catch (IOException e) {
218: setError();
219: }
220: out = null;
221: }
222: }
223: }
224:
225: /**
226: * Flush this PrintWriter to ensure all pending data is sent out to the
227: * target Writer. This implementation flushes the target writer. If an error
228: * occurs, set an error in this PrintWriter to <code>true</code>.
229: */
230: @Override
231: public void flush() {
232: synchronized (lock) {
233: if (out != null) {
234: try {
235: out.flush();
236: } catch (IOException e) {
237: setError();
238: }
239: } else {
240: setError();
241: }
242: }
243: }
244:
245: /**
246: * Writes a string formatted by an intermediate <code>Formatter</code> to
247: * this writer using the given format string and arguments. A call to this
248: * method flushes the buffered output, if the automatic flushing is enabled.
249: * <p>
250: * The method uses the default for the current JVM instance locale, as if it
251: * is specified by the <code>Locale.getDefault()</code> call.
252: *
253: * @param format
254: * A format string.
255: * @param args
256: * The arguments list. If there are more arguments than those
257: * specified by the format string, then the additional arguments
258: * are ignored.
259: * @return This writer.
260: * @throws IllegalFormatException
261: * If the format string is illegal or incompatible with the
262: * arguments or the arguments are less than those required by
263: * the format string or any other illegal situation.
264: * @throws NullPointerException
265: * If the given format is null.
266: */
267: public PrintWriter format(String format, Object... args) {
268: return format(Locale.getDefault(), format, args);
269: }
270:
271: /**
272: * Writes a string formatted by an intermediate <code>Formatter</code> to
273: * this writer using the given format string and arguments. A call to this
274: * method flushes the buffered output, if the automatic flushing is enabled.
275: *
276: * @param l
277: * The locale used in the method. If locale is null, then no
278: * localization will be applied.
279: * @param format
280: * A format string.
281: * @param args
282: * The arguments list. If there are more arguments than those
283: * specified by the format string, then the additional arguments
284: * are ignored.
285: * @return This writer.
286: * @throws IllegalFormatException
287: * If the format string is illegal or incompatible with the
288: * arguments or the arguments are less than those required by
289: * the format string or any other illegal situation.
290: * @throws NullPointerException
291: * If the given format is null.
292: */
293: public PrintWriter format(Locale l, String format, Object... args) {
294: if (format == null) {
295: throw new NullPointerException(Msg.getString("K0351")); //$NON-NLS-1$
296: }
297: new Formatter(this , l).format(format, args);
298: if (autoflush) {
299: flush();
300: }
301: return this ;
302: }
303:
304: /**
305: * Prints a formatted string. The behavior of this method is the same as
306: * this writer's <code>format(String format, Object... args)</code>
307: * method.
308: * <p>
309: * The method uses the default for the current JVM instance locale, as if it
310: * is specified by the <code>Locale.getDefault()</code> call.
311: *
312: * @param format
313: * A format string.
314: * @param args
315: * The arguments list. If there are more arguments than those
316: * specified by the format string, then the additional arguments
317: * are ignored.
318: * @return This writer.
319: * @throws IllegalFormatException
320: * If the format string is illegal or incompatible with the
321: * arguments or the arguments are less than those required by
322: * the format string or any other illegal situation.
323: * @throws NullPointerException
324: * If the given format is null.
325: */
326: public PrintWriter printf(String format, Object... args) {
327: return format(format, args);
328: }
329:
330: /**
331: * Prints a formatted string. The behavior of this method is the same as
332: * this writer's
333: * <code>format(Locale l, String format, Object... args)</code> method.
334: *
335: * @param l
336: * The locale used in the method. If locale is null, then no
337: * localization will be applied.
338: * @param format
339: * A format string.
340: * @param args
341: * The arguments list. If there are more arguments than those
342: * specified by the format string, then the additional arguments
343: * are ignored.
344: * @return the PrintWriter.
345: * @throws IllegalFormatException
346: * If the format string is illegal or incompatible with the
347: * arguments or the arguments are less than those required by
348: * the format string or any other illegal situation.
349: * @throws NullPointerException
350: * If the given format is null.
351: */
352: public PrintWriter printf(Locale l, String format, Object... args) {
353: return format(l, format, args);
354: }
355:
356: /**
357: * Print a new line String onto the writer, flushing if autoflush enabled.
358: */
359: private void newline() {
360: print(lineSeparator);
361: if (autoflush) {
362: flush();
363: }
364: }
365:
366: /**
367: * Prints the String representation of the character array parameter
368: * <code>charArray</code> to the target Writer.
369: *
370: * @param charArray
371: * the character array to print on this Writer.
372: */
373: public void print(char[] charArray) {
374: print(new String(charArray, 0, charArray.length));
375: }
376:
377: /**
378: * Prints the String representation of the character parameter
379: * <code>ch</code> to the target Writer.
380: *
381: * @param ch
382: * the character to print on this Writer.
383: */
384: public void print(char ch) {
385: print(String.valueOf(ch));
386: }
387:
388: /**
389: * Prints the String representation of the <code>double</code> parameter
390: * <code>dnum</code> to the target Writer.
391: *
392: * @param dnum
393: * the <code>double</code> to print on this Writer.
394: */
395: public void print(double dnum) {
396: print(String.valueOf(dnum));
397: }
398:
399: /**
400: * Prints the String representation of the <code>float</code> parameter
401: * <code>fnum</code> to the target Writer.
402: *
403: * @param fnum
404: * the <code>float</code> to print on this Writer.
405: */
406: public void print(float fnum) {
407: print(String.valueOf(fnum));
408: }
409:
410: /**
411: * Prints the String representation of the <code>int</code> parameter
412: * <code>inum</code> to the target Writer.
413: *
414: * @param inum
415: * the <code>int</code> to print on this Writer.
416: */
417: public void print(int inum) {
418: print(String.valueOf(inum));
419: }
420:
421: /**
422: * Prints the String representation of the <code>long</code> parameter
423: * <code>lnum</code> to the target Writer.
424: *
425: * @param lnum
426: * the <code>long</code> to print on this Writer.
427: */
428: public void print(long lnum) {
429: print(String.valueOf(lnum));
430: }
431:
432: /**
433: * Prints the String representation of the Object parameter <code>obj</code>
434: * to the target Writer.
435: *
436: * @param obj
437: * the Object to print on this Writer.
438: */
439: public void print(Object obj) {
440: print(String.valueOf(obj));
441: }
442:
443: /**
444: * Prints the String representation of the <code>String</code> parameter
445: * <code>str</code> to the target Writer.
446: *
447: * @param str
448: * the <code>String</code> to print on this Writer.
449: */
450: public void print(String str) {
451: write(str != null ? str : String.valueOf((Object) null));
452: }
453:
454: /**
455: * Prints the String representation of the <code>boolean</code> parameter
456: * <code>bool</code> to the target Writer.
457: *
458: * @param bool
459: * the <code>boolean</code> to print on this Writer.
460: */
461: public void print(boolean bool) {
462: print(String.valueOf(bool));
463: }
464:
465: /**
466: * Prints the String representation of the System property
467: * <code>"line.separator"</code> to the target Writer.
468: */
469: public void println() {
470: synchronized (lock) {
471: newline();
472: }
473: }
474:
475: /**
476: * Prints the String representation of the character array parameter
477: * <code>charArray</code> to the target Writer followed by the System
478: * property <code>"line.separator"</code>.
479: *
480: * @param charArray
481: * the character array to print on this Writer.
482: */
483: public void println(char[] charArray) {
484: println(new String(charArray, 0, charArray.length));
485: }
486:
487: /**
488: * Prints the String representation of the character parameter
489: * <code>ch</code> to the target Writer followed by the System property
490: * <code>"line.separator"</code>.
491: *
492: * @param ch
493: * the character to print on this Writer.
494: */
495: public void println(char ch) {
496: println(String.valueOf(ch));
497: }
498:
499: /**
500: * Prints the String representation of the <code>double</code> parameter
501: * <code>dnum</code> to the target Writer followed by the System property
502: * <code>"line.separator"</code>.
503: *
504: * @param dnum
505: * the double to print on this Writer.
506: */
507: public void println(double dnum) {
508: println(String.valueOf(dnum));
509: }
510:
511: /**
512: * Prints the String representation of the <code>float</code> parameter
513: * <code>fnum</code> to the target Writer followed by the System property
514: * <code>"line.separator"</code>.
515: *
516: * @param fnum
517: * the float to print on this Writer.
518: */
519: public void println(float fnum) {
520: println(String.valueOf(fnum));
521: }
522:
523: /**
524: * Prints the String representation of the <code>int</code> parameter
525: * <code>inum</code> to the target Writer followed by the System property
526: * <code>"line.separator"</code>.
527: *
528: * @param inum
529: * the int to print on this Writer.
530: */
531: public void println(int inum) {
532: println(String.valueOf(inum));
533: }
534:
535: /**
536: * Prints the String representation of the <code>long</code> parameter
537: * <code>lnum</code> to the target Writer followed by the System property
538: * <code>"line.separator"</code>.
539: *
540: * @param lnum
541: * the long to print on this Writer.
542: */
543: public void println(long lnum) {
544: println(String.valueOf(lnum));
545: }
546:
547: /**
548: * Prints the String representation of the <code>Object</code> parameter
549: * <code>obj</code> to the target Writer followed by the System property
550: * <code>"line.separator"</code>.
551: *
552: * @param obj
553: * the <code>Object</code> to print on this Writer.
554: */
555: public void println(Object obj) {
556: println(String.valueOf(obj));
557: }
558:
559: /**
560: * Prints the String representation of the <code>String</code> parameter
561: * <code>str</code> to the target Writer followed by the System property
562: * <code>"line.separator"</code>.
563: *
564: * @param str
565: * the <code>String</code> to print on this Writer.
566: */
567: public void println(String str) {
568: synchronized (lock) {
569: print(str);
570: newline();
571: }
572: }
573:
574: /**
575: * Prints the String representation of the <code>boolean</code> parameter
576: * <code>bool</code> to the target Writer followed by the System property
577: * <code>"line.separator"</code>.
578: *
579: * @param bool
580: * the boolean to print on this Writer.
581: */
582: public void println(boolean bool) {
583: println(String.valueOf(bool));
584: }
585:
586: /**
587: * Set the flag indicating that this PrintWriter has encountered an IO
588: * error.
589: */
590: protected void setError() {
591: synchronized (lock) {
592: ioError = true;
593: }
594: }
595:
596: /**
597: * Writes the entire character buffer buf to this Writer.
598: *
599: * @param buf
600: * the non-null array containing characters to write.
601: */
602: @Override
603: public void write(char buf[]) {
604: write(buf, 0, buf.length);
605: }
606:
607: /**
608: * Writes <code>count</code> characters starting at <code>offset</code>
609: * in <code>buf<code>
610: * to this Writer.
611: *
612: * @param buf the non-null array containing characters to write.
613: * @param offset offset in buf to retrieve characters
614: * @param count maximum number of characters to write
615: *
616: * @throws ArrayIndexOutOfBoundsException If offset or count are outside of bounds.
617: */
618: @Override
619: public void write(char buf[], int offset, int count) {
620: doWrite(buf, offset, count);
621: }
622:
623: /**
624: * Writes the specified character to this Writer. This implementation writes
625: * the low order two bytes to the target writer.
626: *
627: * @param oneChar
628: * The character to write
629: */
630: @Override
631: public void write(int oneChar) {
632: doWrite(new char[] { (char) oneChar }, 0, 1);
633: }
634:
635: private final void doWrite(char buf[], int offset, int count) {
636: synchronized (lock) {
637: if (out != null) {
638: try {
639: out.write(buf, offset, count);
640: } catch (IOException e) {
641: setError();
642: }
643: } else {
644: setError();
645: }
646: }
647: }
648:
649: /**
650: * Writes the characters from the String <code>str</code> to this Writer.
651: *
652: * @param str
653: * the non-null String containing the characters to write.
654: */
655: @Override
656: public void write(String str) {
657: write(str.toCharArray());
658: }
659:
660: /**
661: * Writes <code>count</code> characters from the String <code>str</code>
662: * starting at <code>offset</code> to this Writer.
663: *
664: * @param str
665: * the non-null String containing the characters to write.
666: * @param offset
667: * where in <code>str</code> to get chars from.
668: * @param count
669: * how many characters to write.
670: *
671: * @throws ArrayIndexOutOfBoundsException
672: * If offset or count are outside of bounds.
673: */
674: @Override
675: public void write(String str, int offset, int count) {
676: write(str.substring(offset, offset + count).toCharArray());
677: }
678:
679: /**
680: * Append a char <code>c</code>to the PrintWriter. The
681: * PrintWriter.append(<code>c</code>) works the same way as
682: * PrintWriter.write(<code>c</code>).
683: *
684: * @param c
685: * The character appended to the PrintWriter.
686: * @return The PrintWriter.
687: * @see Writer#append(char)
688: */
689: @Override
690: public PrintWriter append(char c) {
691: write(c);
692: return this ;
693: }
694:
695: /**
696: * Append a CharSequence <code>csq</code> to the PrintWriter. The
697: * PrintWriter.append(<code>csq</code>) works the same way as
698: * PrintWriter.write(<code>csq</code>.toString()). If <code>csq</code>
699: * is null, then "null" will be substituted for <code>csq</code>
700: *
701: * @param csq
702: * The CharSequence appended to the PrintWriter.
703: * @return The PrintWriter
704: * @see Writer#append(CharSequence)
705: */
706: @Override
707: public PrintWriter append(CharSequence csq) {
708: if (null == csq) {
709: append(TOKEN_NULL, 0, TOKEN_NULL.length());
710: } else {
711: append(csq, 0, csq.length());
712: }
713: return this ;
714: }
715:
716: /**
717: * Append a subsequence of a CharSequence <code>csq</code> to the
718: * PrintWriter. The first char and the last char of the subsequence is
719: * specified by the parameter <code>start</code> and <code>end</code>.
720: * The PrintWriter.append(<code>csq</code>) works the same way as
721: * PrintWriter.write(<code>csq</code>.subSequence(<code>start</code>,<code>end</code>).toString).If
722: * <code>csq</code> is null, then "null" will be substituted for
723: * <code>csq</code>.
724: *
725: * @param csq
726: * The CharSequence appended to the PrintWriter.
727: * @param start
728: * The index of the first char in the CharSequence appended to
729: * the PrintWriter.
730: * @param end
731: * The index of the char after the last one in the CharSequence
732: * appended to the PrintWriter.
733: * @return The PrintWriter.
734: * @throws IndexOutOfBoundsException
735: * If start is less than end, end is greater than the length of
736: * the CharSequence, or start or end is negative.
737: * @see Writer#append(CharSequence, int, int)
738: */
739: @Override
740: public PrintWriter append(CharSequence csq, int start, int end) {
741: if (null == csq) {
742: csq = TOKEN_NULL;
743: }
744: String output = csq.subSequence(start, end).toString();
745: write(output, 0, output.length());
746: return this;
747: }
748: }
|