PrintStream.java 20 KB

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