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 package org.apache.commons.io;
18
19 import java.io.BufferedInputStream;
20 import java.io.BufferedReader;
21 import java.io.ByteArrayInputStream;
22 import java.io.CharArrayWriter;
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.PrintWriter;
30 import java.io.Reader;
31 import java.io.StringWriter;
32 import java.io.Writer;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Iterator;
36 import java.util.List;
37
38 import org.apache.commons.io.output.ByteArrayOutputStream;
39
40 /**
41 * General IO stream manipulation utilities.
42 * <p>
43 * This class provides static utility methods for input/output operations.
44 * <ul>
45 * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
46 * <li>toXxx/read - these methods read data from a stream
47 * <li>write - these methods write data to a stream
48 * <li>copy - these methods copy all the data from one stream to another
49 * <li>contentEquals - these methods compare the content of two streams
50 * </ul>
51 * <p>
52 * The byte-to-char methods and char-to-byte methods involve a conversion step.
53 * Two methods are provided in each case, one that uses the platform default
54 * encoding and the other which allows you to specify an encoding. You are
55 * encouraged to always specify an encoding because relying on the platform
56 * default can lead to unexpected results, for example when moving from
57 * development to production.
58 * <p>
59 * All the methods in this class that read a stream are buffered internally.
60 * This means that there is no cause to use a <code>BufferedInputStream</code>
61 * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
62 * to be efficient in tests.
63 * <p>
64 * Wherever possible, the methods in this class do <em>not</em> flush or close
65 * the stream. This is to avoid making non-portable assumptions about the
66 * streams' origin and further use. Thus the caller is still responsible for
67 * closing streams after use.
68 * <p>
69 * Origin of code: Excalibur.
70 *
71 * @author Peter Donald
72 * @author Jeff Turner
73 * @author Matthew Hawthorne
74 * @author Stephen Colebourne
75 * @author Gareth Davis
76 * @author Ian Springer
77 * @author Niall Pemberton
78 * @author Sandy McArthur
79 * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
80 */
81 public class IOUtils {
82 // NOTE: This class is focussed on InputStream, OutputStream, Reader and
83 // Writer. Each method should take at least one of these as a parameter,
84 // or return one of them.
85
86 /**
87 * The Unix directory separator character.
88 */
89 public static final char DIR_SEPARATOR_UNIX = '/';
90 /**
91 * The Windows directory separator character.
92 */
93 public static final char DIR_SEPARATOR_WINDOWS = '\\';
94 /**
95 * The system directory separator character.
96 */
97 public static final char DIR_SEPARATOR = File.separatorChar;
98 /**
99 * The Unix line separator string.
100 */
101 public static final String LINE_SEPARATOR_UNIX = "\n";
102 /**
103 * The Windows line separator string.
104 */
105 public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
106 /**
107 * The system line separator string.
108 */
109 public static final String LINE_SEPARATOR;
110 static {
111 // avoid security issues
112 StringWriter buf = new StringWriter(4);
113 PrintWriter out = new PrintWriter(buf);
114 out.println();
115 LINE_SEPARATOR = buf.toString();
116 }
117
118 /**
119 * The default buffer size to use.
120 */
121 private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
122
123 /**
124 * Instances should NOT be constructed in standard programming.
125 */
126 public IOUtils() {
127 super();
128 }
129
130 //-----------------------------------------------------------------------
131 /**
132 * Unconditionally close an <code>Reader</code>.
133 * <p>
134 * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
135 * This is typically used in finally blocks.
136 *
137 * @param input the Reader to close, may be null or already closed
138 */
139 public static void closeQuietly(Reader input) {
140 try {
141 if (input != null) {
142 input.close();
143 }
144 } catch (IOException ioe) {
145 // ignore
146 }
147 }
148
149 /**
150 * Unconditionally close a <code>Writer</code>.
151 * <p>
152 * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
153 * This is typically used in finally blocks.
154 *
155 * @param output the Writer to close, may be null or already closed
156 */
157 public static void closeQuietly(Writer output) {
158 try {
159 if (output != null) {
160 output.close();
161 }
162 } catch (IOException ioe) {
163 // ignore
164 }
165 }
166
167 /**
168 * Unconditionally close an <code>InputStream</code>.
169 * <p>
170 * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
171 * This is typically used in finally blocks.
172 *
173 * @param input the InputStream to close, may be null or already closed
174 */
175 public static void closeQuietly(InputStream input) {
176 try {
177 if (input != null) {
178 input.close();
179 }
180 } catch (IOException ioe) {
181 // ignore
182 }
183 }
184
185 /**
186 * Unconditionally close an <code>OutputStream</code>.
187 * <p>
188 * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
189 * This is typically used in finally blocks.
190 *
191 * @param output the OutputStream to close, may be null or already closed
192 */
193 public static void closeQuietly(OutputStream output) {
194 try {
195 if (output != null) {
196 output.close();
197 }
198 } catch (IOException ioe) {
199 // ignore
200 }
201 }
202
203 // read toByteArray
204 //-----------------------------------------------------------------------
205 /**
206 * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
207 * <p>
208 * This method buffers the input internally, so there is no need to use a
209 * <code>BufferedInputStream</code>.
210 *
211 * @param input the <code>InputStream</code> to read from
212 * @return the requested byte array
213 * @throws NullPointerException if the input is null
214 * @throws IOException if an I/O error occurs
215 */
216 public static byte[] toByteArray(InputStream input) throws IOException {
217 ByteArrayOutputStream output = new ByteArrayOutputStream();
218 copy(input, output);
219 return output.toByteArray();
220 }
221
222 /**
223 * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
224 * using the default character encoding of the platform.
225 * <p>
226 * This method buffers the input internally, so there is no need to use a
227 * <code>BufferedReader</code>.
228 *
229 * @param input the <code>Reader</code> to read from
230 * @return the requested byte array
231 * @throws NullPointerException if the input is null
232 * @throws IOException if an I/O error occurs
233 */
234 public static byte[] toByteArray(Reader input) throws IOException {
235 ByteArrayOutputStream output = new ByteArrayOutputStream();
236 copy(input, output);
237 return output.toByteArray();
238 }
239
240 /**
241 * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
242 * using the specified character encoding.
243 * <p>
244 * Character encoding names can be found at
245 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
246 * <p>
247 * This method buffers the input internally, so there is no need to use a
248 * <code>BufferedReader</code>.
249 *
250 * @param input the <code>Reader</code> to read from
251 * @param encoding the encoding to use, null means platform default
252 * @return the requested byte array
253 * @throws NullPointerException if the input is null
254 * @throws IOException if an I/O error occurs
255 * @since Commons IO 1.1
256 */
257 public static byte[] toByteArray(Reader input, String encoding)
258 throws IOException {
259 ByteArrayOutputStream output = new ByteArrayOutputStream();
260 copy(input, output, encoding);
261 return output.toByteArray();
262 }
263
264 /**
265 * Get the contents of a <code>String</code> as a <code>byte[]</code>
266 * using the default character encoding of the platform.
267 * <p>
268 * This is the same as {@link String#getBytes()}.
269 *
270 * @param input the <code>String</code> to convert
271 * @return the requested byte array
272 * @throws NullPointerException if the input is null
273 * @throws IOException if an I/O error occurs (never occurs)
274 * @deprecated Use {@link String#getBytes()}
275 */
276 public static byte[] toByteArray(String input) throws IOException {
277 return input.getBytes();
278 }
279
280 // read char[]
281 //-----------------------------------------------------------------------
282 /**
283 * Get the contents of an <code>InputStream</code> as a character array
284 * using the default character encoding of the platform.
285 * <p>
286 * This method buffers the input internally, so there is no need to use a
287 * <code>BufferedInputStream</code>.
288 *
289 * @param is the <code>InputStream</code> to read from
290 * @return the requested character array
291 * @throws NullPointerException if the input is null
292 * @throws IOException if an I/O error occurs
293 * @since Commons IO 1.1
294 */
295 public static char[] toCharArray(InputStream is) throws IOException {
296 CharArrayWriter output = new CharArrayWriter();
297 copy(is, output);
298 return output.toCharArray();
299 }
300
301 /**
302 * Get the contents of an <code>InputStream</code> as a character array
303 * using the specified character encoding.
304 * <p>
305 * Character encoding names can be found at
306 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
307 * <p>
308 * This method buffers the input internally, so there is no need to use a
309 * <code>BufferedInputStream</code>.
310 *
311 * @param is the <code>InputStream</code> to read from
312 * @param encoding the encoding to use, null means platform default
313 * @return the requested character array
314 * @throws NullPointerException if the input is null
315 * @throws IOException if an I/O error occurs
316 * @since Commons IO 1.1
317 */
318 public static char[] toCharArray(InputStream is, String encoding)
319 throws IOException {
320 CharArrayWriter output = new CharArrayWriter();
321 copy(is, output, encoding);
322 return output.toCharArray();
323 }
324
325 /**
326 * Get the contents of a <code>Reader</code> as a character array.
327 * <p>
328 * This method buffers the input internally, so there is no need to use a
329 * <code>BufferedReader</code>.
330 *
331 * @param input the <code>Reader</code> to read from
332 * @return the requested character array
333 * @throws NullPointerException if the input is null
334 * @throws IOException if an I/O error occurs
335 * @since Commons IO 1.1
336 */
337 public static char[] toCharArray(Reader input) throws IOException {
338 CharArrayWriter sw = new CharArrayWriter();
339 copy(input, sw);
340 return sw.toCharArray();
341 }
342
343 // read toString
344 //-----------------------------------------------------------------------
345 /**
346 * Get the contents of an <code>InputStream</code> as a String
347 * using the default character encoding of the platform.
348 * <p>
349 * This method buffers the input internally, so there is no need to use a
350 * <code>BufferedInputStream</code>.
351 *
352 * @param input the <code>InputStream</code> to read from
353 * @return the requested String
354 * @throws NullPointerException if the input is null
355 * @throws IOException if an I/O error occurs
356 */
357 public static String toString(InputStream input) throws IOException {
358 StringWriter sw = new StringWriter();
359 copy(input, sw);
360 return sw.toString();
361 }
362
363 /**
364 * Get the contents of an <code>InputStream</code> as a String
365 * using the specified character encoding.
366 * <p>
367 * Character encoding names can be found at
368 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
369 * <p>
370 * This method buffers the input internally, so there is no need to use a
371 * <code>BufferedInputStream</code>.
372 *
373 * @param input the <code>InputStream</code> to read from
374 * @param encoding the encoding to use, null means platform default
375 * @return the requested String
376 * @throws NullPointerException if the input is null
377 * @throws IOException if an I/O error occurs
378 */
379 public static String toString(InputStream input, String encoding)
380 throws IOException {
381 StringWriter sw = new StringWriter();
382 copy(input, sw, encoding);
383 return sw.toString();
384 }
385
386 /**
387 * Get the contents of a <code>Reader</code> as a String.
388 * <p>
389 * This method buffers the input internally, so there is no need to use a
390 * <code>BufferedReader</code>.
391 *
392 * @param input the <code>Reader</code> to read from
393 * @return the requested String
394 * @throws NullPointerException if the input is null
395 * @throws IOException if an I/O error occurs
396 */
397 public static String toString(Reader input) throws IOException {
398 StringWriter sw = new StringWriter();
399 copy(input, sw);
400 return sw.toString();
401 }
402
403 /**
404 * Get the contents of a <code>byte[]</code> as a String
405 * using the default character encoding of the platform.
406 *
407 * @param input the byte array to read from
408 * @return the requested String
409 * @throws NullPointerException if the input is null
410 * @throws IOException if an I/O error occurs (never occurs)
411 * @deprecated Use {@link String#String(byte[])}
412 */
413 public static String toString(byte[] input) throws IOException {
414 return new String(input);
415 }
416
417 /**
418 * Get the contents of a <code>byte[]</code> as a String
419 * using the specified character encoding.
420 * <p>
421 * Character encoding names can be found at
422 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
423 *
424 * @param input the byte array to read from
425 * @param encoding the encoding to use, null means platform default
426 * @return the requested String
427 * @throws NullPointerException if the input is null
428 * @throws IOException if an I/O error occurs (never occurs)
429 * @deprecated Use {@link String#String(byte[],String)}
430 */
431 public static String toString(byte[] input, String encoding)
432 throws IOException {
433 if (encoding == null) {
434 return new String(input);
435 } else {
436 return new String(input, encoding);
437 }
438 }
439
440 // readLines
441 //-----------------------------------------------------------------------
442 /**
443 * Get the contents of an <code>InputStream</code> as a list of Strings,
444 * one entry per line, using the default character encoding of the platform.
445 * <p>
446 * This method buffers the input internally, so there is no need to use a
447 * <code>BufferedInputStream</code>.
448 *
449 * @param input the <code>InputStream</code> to read from, not null
450 * @return the list of Strings, never null
451 * @throws NullPointerException if the input is null
452 * @throws IOException if an I/O error occurs
453 * @since Commons IO 1.1
454 */
455 public static List readLines(InputStream input) throws IOException {
456 InputStreamReader reader = new InputStreamReader(input);
457 return readLines(reader);
458 }
459
460 /**
461 * Get the contents of an <code>InputStream</code> as a list of Strings,
462 * one entry per line, using the specified character encoding.
463 * <p>
464 * Character encoding names can be found at
465 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
466 * <p>
467 * This method buffers the input internally, so there is no need to use a
468 * <code>BufferedInputStream</code>.
469 *
470 * @param input the <code>InputStream</code> to read from, not null
471 * @param encoding the encoding to use, null means platform default
472 * @return the list of Strings, never null
473 * @throws NullPointerException if the input is null
474 * @throws IOException if an I/O error occurs
475 * @since Commons IO 1.1
476 */
477 public static List readLines(InputStream input, String encoding) throws IOException {
478 if (encoding == null) {
479 return readLines(input);
480 } else {
481 InputStreamReader reader = new InputStreamReader(input, encoding);
482 return readLines(reader);
483 }
484 }
485
486 /**
487 * Get the contents of a <code>Reader</code> as a list of Strings,
488 * one entry per line.
489 * <p>
490 * This method buffers the input internally, so there is no need to use a
491 * <code>BufferedReader</code>.
492 *
493 * @param input the <code>Reader</code> to read from, not null
494 * @return the list of Strings, never null
495 * @throws NullPointerException if the input is null
496 * @throws IOException if an I/O error occurs
497 * @since Commons IO 1.1
498 */
499 public static List readLines(Reader input) throws IOException {
500 BufferedReader reader = new BufferedReader(input);
501 List list = new ArrayList();
502 String line = reader.readLine();
503 while (line != null) {
504 list.add(line);
505 line = reader.readLine();
506 }
507 return list;
508 }
509
510 // lineIterator
511 //-----------------------------------------------------------------------
512 /**
513 * Return an Iterator for the lines in a <code>Reader</code>.
514 * <p>
515 * <code>LineIterator</code> holds a reference to the open
516 * <code>Reader</code> specified here. When you have finished with the
517 * iterator you should close the reader to free internal resources.
518 * This can be done by closing the reader directly, or by calling
519 * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
520 * <p>
521 * The recommended usage pattern is:
522 * <pre>
523 * try {
524 * LineIterator it = IOUtils.lineIterator(reader);
525 * while (it.hasNext()) {
526 * String line = it.nextLine();
527 * /// do something with line
528 * }
529 * } finally {
530 * IOUtils.closeQuietly(reader);
531 * }
532 * </pre>
533 *
534 * @param reader the <code>Reader</code> to read from, not null
535 * @return an Iterator of the lines in the reader, never null
536 * @throws IllegalArgumentException if the reader is null
537 * @since Commons IO 1.2
538 */
539 public static LineIterator lineIterator(Reader reader) {
540 return new LineIterator(reader);
541 }
542
543 /**
544 * Return an Iterator for the lines in an <code>InputStream</code>, using
545 * the character encoding specified (or default encoding if null).
546 * <p>
547 * <code>LineIterator</code> holds a reference to the open
548 * <code>InputStream</code> specified here. When you have finished with
549 * the iterator you should close the stream to free internal resources.
550 * This can be done by closing the stream directly, or by calling
551 * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}.
552 * <p>
553 * The recommended usage pattern is:
554 * <pre>
555 * try {
556 * LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
557 * while (it.hasNext()) {
558 * String line = it.nextLine();
559 * /// do something with line
560 * }
561 * } finally {
562 * IOUtils.closeQuietly(stream);
563 * }
564 * </pre>
565 *
566 * @param input the <code>InputStream</code> to read from, not null
567 * @param encoding the encoding to use, null means platform default
568 * @return an Iterator of the lines in the reader, never null
569 * @throws IllegalArgumentException if the input is null
570 * @throws IOException if an I/O error occurs, such as if the encoding is invalid
571 * @since Commons IO 1.2
572 */
573 public static LineIterator lineIterator(InputStream input, String encoding)
574 throws IOException {
575 Reader reader = null;
576 if (encoding == null) {
577 reader = new InputStreamReader(input);
578 } else {
579 reader = new InputStreamReader(input, encoding);
580 }
581 return new LineIterator(reader);
582 }
583
584 //-----------------------------------------------------------------------
585 /**
586 * Convert the specified string to an input stream, encoded as bytes
587 * using the default character encoding of the platform.
588 *
589 * @param input the string to convert
590 * @return an input stream
591 * @since Commons IO 1.1
592 */
593 public static InputStream toInputStream(String input) {
594 byte[] bytes = input.getBytes();
595 return new ByteArrayInputStream(bytes);
596 }
597
598 /**
599 * Convert the specified string to an input stream, encoded as bytes
600 * using the specified character encoding.
601 * <p>
602 * Character encoding names can be found at
603 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
604 *
605 * @param input the string to convert
606 * @param encoding the encoding to use, null means platform default
607 * @throws IOException if the encoding is invalid
608 * @return an input stream
609 * @since Commons IO 1.1
610 */
611 public static InputStream toInputStream(String input, String encoding) throws IOException {
612 byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
613 return new ByteArrayInputStream(bytes);
614 }
615
616 // write byte[]
617 //-----------------------------------------------------------------------
618 /**
619 * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
620 *
621 * @param data the byte array to write, do not modify during output,
622 * null ignored
623 * @param output the <code>OutputStream</code> to write to
624 * @throws NullPointerException if output is null
625 * @throws IOException if an I/O error occurs
626 * @since Commons IO 1.1
627 */
628 public static void write(byte[] data, OutputStream output)
629 throws IOException {
630 if (data != null) {
631 output.write(data);
632 }
633 }
634
635 /**
636 * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
637 * using the default character encoding of the platform.
638 * <p>
639 * This method uses {@link String#String(byte[])}.
640 *
641 * @param data the byte array to write, do not modify during output,
642 * null ignored
643 * @param output the <code>Writer</code> to write to
644 * @throws NullPointerException if output is null
645 * @throws IOException if an I/O error occurs
646 * @since Commons IO 1.1
647 */
648 public static void write(byte[] data, Writer output) throws IOException {
649 if (data != null) {
650 output.write(new String(data));
651 }
652 }
653
654 /**
655 * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
656 * using the specified character encoding.
657 * <p>
658 * Character encoding names can be found at
659 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
660 * <p>
661 * This method uses {@link String#String(byte[], String)}.
662 *
663 * @param data the byte array to write, do not modify during output,
664 * null ignored
665 * @param output the <code>Writer</code> to write to
666 * @param encoding the encoding to use, null means platform default
667 * @throws NullPointerException if output is null
668 * @throws IOException if an I/O error occurs
669 * @since Commons IO 1.1
670 */
671 public static void write(byte[] data, Writer output, String encoding)
672 throws IOException {
673 if (data != null) {
674 if (encoding == null) {
675 write(data, output);
676 } else {
677 output.write(new String(data, encoding));
678 }
679 }
680 }
681
682 // write char[]
683 //-----------------------------------------------------------------------
684 /**
685 * Writes chars from a <code>char[]</code> to a <code>Writer</code>
686 * using the default character encoding of the platform.
687 *
688 * @param data the char array to write, do not modify during output,
689 * null ignored
690 * @param output the <code>Writer</code> to write to
691 * @throws NullPointerException if output is null
692 * @throws IOException if an I/O error occurs
693 * @since Commons IO 1.1
694 */
695 public static void write(char[] data, Writer output) throws IOException {
696 if (data != null) {
697 output.write(data);
698 }
699 }
700
701 /**
702 * Writes chars from a <code>char[]</code> to bytes on an
703 * <code>OutputStream</code>.
704 * <p>
705 * This method uses {@link String#String(char[])} and
706 * {@link String#getBytes()}.
707 *
708 * @param data the char array to write, do not modify during output,
709 * null ignored
710 * @param output the <code>OutputStream</code> to write to
711 * @throws NullPointerException if output is null
712 * @throws IOException if an I/O error occurs
713 * @since Commons IO 1.1
714 */
715 public static void write(char[] data, OutputStream output)
716 throws IOException {
717 if (data != null) {
718 output.write(new String(data).getBytes());
719 }
720 }
721
722 /**
723 * Writes chars from a <code>char[]</code> to bytes on an
724 * <code>OutputStream</code> using the specified character encoding.
725 * <p>
726 * Character encoding names can be found at
727 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
728 * <p>
729 * This method uses {@link String#String(char[])} and
730 * {@link String#getBytes(String)}.
731 *
732 * @param data the char array to write, do not modify during output,
733 * null ignored
734 * @param output the <code>OutputStream</code> to write to
735 * @param encoding the encoding to use, null means platform default
736 * @throws NullPointerException if output is null
737 * @throws IOException if an I/O error occurs
738 * @since Commons IO 1.1
739 */
740 public static void write(char[] data, OutputStream output, String encoding)
741 throws IOException {
742 if (data != null) {
743 if (encoding == null) {
744 write(data, output);
745 } else {
746 output.write(new String(data).getBytes(encoding));
747 }
748 }
749 }
750
751 // write String
752 //-----------------------------------------------------------------------
753 /**
754 * Writes chars from a <code>String</code> to a <code>Writer</code>.
755 *
756 * @param data the <code>String</code> to write, null ignored
757 * @param output the <code>Writer</code> to write to
758 * @throws NullPointerException if output is null
759 * @throws IOException if an I/O error occurs
760 * @since Commons IO 1.1
761 */
762 public static void write(String data, Writer output) throws IOException {
763 if (data != null) {
764 output.write(data);
765 }
766 }
767
768 /**
769 * Writes chars from a <code>String</code> to bytes on an
770 * <code>OutputStream</code> using the default character encoding of the
771 * platform.
772 * <p>
773 * This method uses {@link String#getBytes()}.
774 *
775 * @param data the <code>String</code> to write, null ignored
776 * @param output the <code>OutputStream</code> to write to
777 * @throws NullPointerException if output is null
778 * @throws IOException if an I/O error occurs
779 * @since Commons IO 1.1
780 */
781 public static void write(String data, OutputStream output)
782 throws IOException {
783 if (data != null) {
784 output.write(data.getBytes());
785 }
786 }
787
788 /**
789 * Writes chars from a <code>String</code> to bytes on an
790 * <code>OutputStream</code> using the specified character encoding.
791 * <p>
792 * Character encoding names can be found at
793 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
794 * <p>
795 * This method uses {@link String#getBytes(String)}.
796 *
797 * @param data the <code>String</code> to write, null ignored
798 * @param output the <code>OutputStream</code> to write to
799 * @param encoding the encoding to use, null means platform default
800 * @throws NullPointerException if output is null
801 * @throws IOException if an I/O error occurs
802 * @since Commons IO 1.1
803 */
804 public static void write(String data, OutputStream output, String encoding)
805 throws IOException {
806 if (data != null) {
807 if (encoding == null) {
808 write(data, output);
809 } else {
810 output.write(data.getBytes(encoding));
811 }
812 }
813 }
814
815 // write StringBuffer
816 //-----------------------------------------------------------------------
817 /**
818 * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
819 *
820 * @param data the <code>StringBuffer</code> to write, null ignored
821 * @param output the <code>Writer</code> to write to
822 * @throws NullPointerException if output is null
823 * @throws IOException if an I/O error occurs
824 * @since Commons IO 1.1
825 */
826 public static void write(StringBuffer data, Writer output)
827 throws IOException {
828 if (data != null) {
829 output.write(data.toString());
830 }
831 }
832
833 /**
834 * Writes chars from a <code>StringBuffer</code> to bytes on an
835 * <code>OutputStream</code> using the default character encoding of the
836 * platform.
837 * <p>
838 * This method uses {@link String#getBytes()}.
839 *
840 * @param data the <code>StringBuffer</code> to write, null ignored
841 * @param output the <code>OutputStream</code> to write to
842 * @throws NullPointerException if output is null
843 * @throws IOException if an I/O error occurs
844 * @since Commons IO 1.1
845 */
846 public static void write(StringBuffer data, OutputStream output)
847 throws IOException {
848 if (data != null) {
849 output.write(data.toString().getBytes());
850 }
851 }
852
853 /**
854 * Writes chars from a <code>StringBuffer</code> to bytes on an
855 * <code>OutputStream</code> using the specified character encoding.
856 * <p>
857 * Character encoding names can be found at
858 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
859 * <p>
860 * This method uses {@link String#getBytes(String)}.
861 *
862 * @param data the <code>StringBuffer</code> to write, null ignored
863 * @param output the <code>OutputStream</code> to write to
864 * @param encoding the encoding to use, null means platform default
865 * @throws NullPointerException if output is null
866 * @throws IOException if an I/O error occurs
867 * @since Commons IO 1.1
868 */
869 public static void write(StringBuffer data, OutputStream output,
870 String encoding) throws IOException {
871 if (data != null) {
872 if (encoding == null) {
873 write(data, output);
874 } else {
875 output.write(data.toString().getBytes(encoding));
876 }
877 }
878 }
879
880 // writeLines
881 //-----------------------------------------------------------------------
882 /**
883 * Writes the <code>toString()</code> value of each item in a collection to
884 * an <code>OutputStream</code> line by line, using the default character
885 * encoding of the platform and the specified line ending.
886 *
887 * @param lines the lines to write, null entries produce blank lines
888 * @param lineEnding the line separator to use, null is system default
889 * @param output the <code>OutputStream</code> to write to, not null, not closed
890 * @throws NullPointerException if the output is null
891 * @throws IOException if an I/O error occurs
892 * @since Commons IO 1.1
893 */
894 public static void writeLines(Collection lines, String lineEnding,
895 OutputStream output) throws IOException {
896 if (lines == null) {
897 return;
898 }
899 if (lineEnding == null) {
900 lineEnding = LINE_SEPARATOR;
901 }
902 for (Iterator it = lines.iterator(); it.hasNext(); ) {
903 Object line = it.next();
904 if (line != null) {
905 output.write(line.toString().getBytes());
906 }
907 output.write(lineEnding.getBytes());
908 }
909 }
910
911 /**
912 * Writes the <code>toString()</code> value of each item in a collection to
913 * an <code>OutputStream</code> line by line, using the specified character
914 * encoding and the specified line ending.
915 * <p>
916 * Character encoding names can be found at
917 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
918 *
919 * @param lines the lines to write, null entries produce blank lines
920 * @param lineEnding the line separator to use, null is system default
921 * @param output the <code>OutputStream</code> to write to, not null, not closed
922 * @param encoding the encoding to use, null means platform default
923 * @throws NullPointerException if the output is null
924 * @throws IOException if an I/O error occurs
925 * @since Commons IO 1.1
926 */
927 public static void writeLines(Collection lines, String lineEnding,
928 OutputStream output, String encoding) throws IOException {
929 if (encoding == null) {
930 writeLines(lines, lineEnding, output);
931 } else {
932 if (lines == null) {
933 return;
934 }
935 if (lineEnding == null) {
936 lineEnding = LINE_SEPARATOR;
937 }
938 for (Iterator it = lines.iterator(); it.hasNext(); ) {
939 Object line = it.next();
940 if (line != null) {
941 output.write(line.toString().getBytes(encoding));
942 }
943 output.write(lineEnding.getBytes(encoding));
944 }
945 }
946 }
947
948 /**
949 * Writes the <code>toString()</code> value of each item in a collection to
950 * a <code>Writer</code> line by line, using the specified line ending.
951 *
952 * @param lines the lines to write, null entries produce blank lines
953 * @param lineEnding the line separator to use, null is system default
954 * @param writer the <code>Writer</code> to write to, not null, not closed
955 * @throws NullPointerException if the input is null
956 * @throws IOException if an I/O error occurs
957 * @since Commons IO 1.1
958 */
959 public static void writeLines(Collection lines, String lineEnding,
960 Writer writer) throws IOException {
961 if (lines == null) {
962 return;
963 }
964 if (lineEnding == null) {
965 lineEnding = LINE_SEPARATOR;
966 }
967 for (Iterator it = lines.iterator(); it.hasNext(); ) {
968 Object line = it.next();
969 if (line != null) {
970 writer.write(line.toString());
971 }
972 writer.write(lineEnding);
973 }
974 }
975
976 // copy from InputStream
977 //-----------------------------------------------------------------------
978 /**
979 * Copy bytes from an <code>InputStream</code> to an
980 * <code>OutputStream</code>.
981 * <p>
982 * This method buffers the input internally, so there is no need to use a
983 * <code>BufferedInputStream</code>.
984 * <p>
985 * Large streams (over 2GB) will return a bytes copied value of
986 * <code>-1</code> after the copy has completed since the correct
987 * number of bytes cannot be returned as an int. For large streams
988 * use the <code>copyLarge(InputStream, OutputStream)</code> method.
989 *
990 * @param input the <code>InputStream</code> to read from
991 * @param output the <code>OutputStream</code> to write to
992 * @return the number of bytes copied
993 * @throws NullPointerException if the input or output is null
994 * @throws IOException if an I/O error occurs
995 * @throws ArithmeticException if the byte count is too large
996 * @since Commons IO 1.1
997 */
998 public static int copy(InputStream input, OutputStream output) throws IOException {
999 long count = copyLarge(input, output);
1000 if (count > Integer.MAX_VALUE) {
1001 return -1;
1002 }
1003 return (int) count;
1004 }
1005
1006 /**
1007 * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
1008 * <code>OutputStream</code>.
1009 * <p>
1010 * This method buffers the input internally, so there is no need to use a
1011 * <code>BufferedInputStream</code>.
1012 *
1013 * @param input the <code>InputStream</code> to read from
1014 * @param output the <code>OutputStream</code> to write to
1015 * @return the number of bytes copied
1016 * @throws NullPointerException if the input or output is null
1017 * @throws IOException if an I/O error occurs
1018 * @since Commons IO 1.3
1019 */
1020 public static long copyLarge(InputStream input, OutputStream output)
1021 throws IOException {
1022 byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
1023 long count = 0;
1024 int n = 0;
1025 while (-1 != (n = input.read(buffer))) {
1026 output.write(buffer, 0, n);
1027 count += n;
1028 }
1029 return count;
1030 }
1031
1032 /**
1033 * Copy bytes from an <code>InputStream</code> to chars on a
1034 * <code>Writer</code> using the default character encoding of the platform.
1035 * <p>
1036 * This method buffers the input internally, so there is no need to use a
1037 * <code>BufferedInputStream</code>.
1038 * <p>
1039 * This method uses {@link InputStreamReader}.
1040 *
1041 * @param input the <code>InputStream</code> to read from
1042 * @param output the <code>Writer</code> to write to
1043 * @throws NullPointerException if the input or output is null
1044 * @throws IOException if an I/O error occurs
1045 * @since Commons IO 1.1
1046 */
1047 public static void copy(InputStream input, Writer output)
1048 throws IOException {
1049 InputStreamReader in = new InputStreamReader(input);
1050 copy(in, output);
1051 }
1052
1053 /**
1054 * Copy bytes from an <code>InputStream</code> to chars on a
1055 * <code>Writer</code> using the specified character encoding.
1056 * <p>
1057 * This method buffers the input internally, so there is no need to use a
1058 * <code>BufferedInputStream</code>.
1059 * <p>
1060 * Character encoding names can be found at
1061 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1062 * <p>
1063 * This method uses {@link InputStreamReader}.
1064 *
1065 * @param input the <code>InputStream</code> to read from
1066 * @param output the <code>Writer</code> to write to
1067 * @param encoding the encoding to use, null means platform default
1068 * @throws NullPointerException if the input or output is null
1069 * @throws IOException if an I/O error occurs
1070 * @since Commons IO 1.1
1071 */
1072 public static void copy(InputStream input, Writer output, String encoding)
1073 throws IOException {
1074 if (encoding == null) {
1075 copy(input, output);
1076 } else {
1077 InputStreamReader in = new InputStreamReader(input, encoding);
1078 copy(in, output);
1079 }
1080 }
1081
1082 // copy from Reader
1083 //-----------------------------------------------------------------------
1084 /**
1085 * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
1086 * <p>
1087 * This method buffers the input internally, so there is no need to use a
1088 * <code>BufferedReader</code>.
1089 * <p>
1090 * Large streams (over 2GB) will return a chars copied value of
1091 * <code>-1</code> after the copy has completed since the correct
1092 * number of chars cannot be returned as an int. For large streams
1093 * use the <code>copyLarge(Reader, Writer)</code> method.
1094 *
1095 * @param input the <code>Reader</code> to read from
1096 * @param output the <code>Writer</code> to write to
1097 * @return the number of characters copied
1098 * @throws NullPointerException if the input or output is null
1099 * @throws IOException if an I/O error occurs
1100 * @throws ArithmeticException if the character count is too large
1101 * @since Commons IO 1.1
1102 */
1103 public static int copy(Reader input, Writer output) throws IOException {
1104 long count = copyLarge(input, output);
1105 if (count > Integer.MAX_VALUE) {
1106 return -1;
1107 }
1108 return (int) count;
1109 }
1110
1111 /**
1112 * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
1113 * <p>
1114 * This method buffers the input internally, so there is no need to use a
1115 * <code>BufferedReader</code>.
1116 *
1117 * @param input the <code>Reader</code> to read from
1118 * @param output the <code>Writer</code> to write to
1119 * @return the number of characters copied
1120 * @throws NullPointerException if the input or output is null
1121 * @throws IOException if an I/O error occurs
1122 * @since Commons IO 1.3
1123 */
1124 public static long copyLarge(Reader input, Writer output) throws IOException {
1125 char[] buffer = new char[DEFAULT_BUFFER_SIZE];
1126 long count = 0;
1127 int n = 0;
1128 while (-1 != (n = input.read(buffer))) {
1129 output.write(buffer, 0, n);
1130 count += n;
1131 }
1132 return count;
1133 }
1134
1135 /**
1136 * Copy chars from a <code>Reader</code> to bytes on an
1137 * <code>OutputStream</code> using the default character encoding of the
1138 * platform, and calling flush.
1139 * <p>
1140 * This method buffers the input internally, so there is no need to use a
1141 * <code>BufferedReader</code>.
1142 * <p>
1143 * Due to the implementation of OutputStreamWriter, this method performs a
1144 * flush.
1145 * <p>
1146 * This method uses {@link OutputStreamWriter}.
1147 *
1148 * @param input the <code>Reader</code> to read from
1149 * @param output the <code>OutputStream</code> to write to
1150 * @throws NullPointerException if the input or output is null
1151 * @throws IOException if an I/O error occurs
1152 * @since Commons IO 1.1
1153 */
1154 public static void copy(Reader input, OutputStream output)
1155 throws IOException {
1156 OutputStreamWriter out = new OutputStreamWriter(output);
1157 copy(input, out);
1158 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
1159 // have to flush here.
1160 out.flush();
1161 }
1162
1163 /**
1164 * Copy chars from a <code>Reader</code> to bytes on an
1165 * <code>OutputStream</code> using the specified character encoding, and
1166 * calling flush.
1167 * <p>
1168 * This method buffers the input internally, so there is no need to use a
1169 * <code>BufferedReader</code>.
1170 * <p>
1171 * Character encoding names can be found at
1172 * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
1173 * <p>
1174 * Due to the implementation of OutputStreamWriter, this method performs a
1175 * flush.
1176 * <p>
1177 * This method uses {@link OutputStreamWriter}.
1178 *
1179 * @param input the <code>Reader</code> to read from
1180 * @param output the <code>OutputStream</code> to write to
1181 * @param encoding the encoding to use, null means platform default
1182 * @throws NullPointerException if the input or output is null
1183 * @throws IOException if an I/O error occurs
1184 * @since Commons IO 1.1
1185 */
1186 public static void copy(Reader input, OutputStream output, String encoding)
1187 throws IOException {
1188 if (encoding == null) {
1189 copy(input, output);
1190 } else {
1191 OutputStreamWriter out = new OutputStreamWriter(output, encoding);
1192 copy(input, out);
1193 // XXX Unless anyone is planning on rewriting OutputStreamWriter,
1194 // we have to flush here.
1195 out.flush();
1196 }
1197 }
1198
1199 // content equals
1200 //-----------------------------------------------------------------------
1201 /**
1202 * Compare the contents of two Streams to determine if they are equal or
1203 * not.
1204 * <p>
1205 * This method buffers the input internally using
1206 * <code>BufferedInputStream</code> if they are not already buffered.
1207 *
1208 * @param input1 the first stream
1209 * @param input2 the second stream
1210 * @return true if the content of the streams are equal or they both don't
1211 * exist, false otherwise
1212 * @throws NullPointerException if either input is null
1213 * @throws IOException if an I/O error occurs
1214 */
1215 public static boolean contentEquals(InputStream input1, InputStream input2)
1216 throws IOException {
1217 if (!(input1 instanceof BufferedInputStream)) {
1218 input1 = new BufferedInputStream(input1);
1219 }
1220 if (!(input2 instanceof BufferedInputStream)) {
1221 input2 = new BufferedInputStream(input2);
1222 }
1223
1224 int ch = input1.read();
1225 while (-1 != ch) {
1226 int ch2 = input2.read();
1227 if (ch != ch2) {
1228 return false;
1229 }
1230 ch = input1.read();
1231 }
1232
1233 int ch2 = input2.read();
1234 return (ch2 == -1);
1235 }
1236
1237 /**
1238 * Compare the contents of two Readers to determine if they are equal or
1239 * not.
1240 * <p>
1241 * This method buffers the input internally using
1242 * <code>BufferedReader</code> if they are not already buffered.
1243 *
1244 * @param input1 the first reader
1245 * @param input2 the second reader
1246 * @return true if the content of the readers are equal or they both don't
1247 * exist, false otherwise
1248 * @throws NullPointerException if either input is null
1249 * @throws IOException if an I/O error occurs
1250 * @since Commons IO 1.1
1251 */
1252 public static boolean contentEquals(Reader input1, Reader input2)
1253 throws IOException {
1254 if (!(input1 instanceof BufferedReader)) {
1255 input1 = new BufferedReader(input1);
1256 }
1257 if (!(input2 instanceof BufferedReader)) {
1258 input2 = new BufferedReader(input2);
1259 }
1260
1261 int ch = input1.read();
1262 while (-1 != ch) {
1263 int ch2 = input2.read();
1264 if (ch != ch2) {
1265 return false;
1266 }
1267 ch = input1.read();
1268 }
1269
1270 int ch2 = input2.read();
1271 return (ch2 == -1);
1272 }
1273
1274 }