View Javadoc
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 static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNotSame;
25  import static org.junit.jupiter.api.Assertions.assertNull;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.junit.jupiter.api.Assertions.assertTrue;
29  import static org.junit.jupiter.api.Assertions.fail;
30  
31  import java.io.BufferedInputStream;
32  import java.io.BufferedOutputStream;
33  import java.io.BufferedReader;
34  import java.io.BufferedWriter;
35  import java.io.ByteArrayInputStream;
36  import java.io.ByteArrayOutputStream;
37  import java.io.CharArrayReader;
38  import java.io.CharArrayWriter;
39  import java.io.Closeable;
40  import java.io.EOFException;
41  import java.io.File;
42  import java.io.FileInputStream;
43  import java.io.IOException;
44  import java.io.InputStream;
45  import java.io.InputStreamReader;
46  import java.io.OutputStream;
47  import java.io.Reader;
48  import java.io.SequenceInputStream;
49  import java.io.StringReader;
50  import java.io.Writer;
51  import java.net.ServerSocket;
52  import java.net.Socket;
53  import java.net.URI;
54  import java.net.URL;
55  import java.net.URLConnection;
56  import java.nio.ByteBuffer;
57  import java.nio.channels.FileChannel;
58  import java.nio.channels.Selector;
59  import java.nio.charset.Charset;
60  import java.nio.charset.StandardCharsets;
61  import java.nio.file.Files;
62  import java.nio.file.Path;
63  import java.util.Arrays;
64  import java.util.Collections;
65  import java.util.List;
66  import java.util.concurrent.atomic.AtomicBoolean;
67  import java.util.function.Consumer;
68  import java.util.function.Supplier;
69  import java.util.stream.Stream;
70  
71  import org.apache.commons.io.function.IOConsumer;
72  import org.apache.commons.io.input.BrokenInputStream;
73  import org.apache.commons.io.input.CharSequenceInputStream;
74  import org.apache.commons.io.input.CircularInputStream;
75  import org.apache.commons.io.input.NullInputStream;
76  import org.apache.commons.io.input.NullReader;
77  import org.apache.commons.io.output.AppendableWriter;
78  import org.apache.commons.io.output.BrokenOutputStream;
79  import org.apache.commons.io.output.CountingOutputStream;
80  import org.apache.commons.io.output.NullOutputStream;
81  import org.apache.commons.io.output.NullWriter;
82  import org.apache.commons.io.output.StringBuilderWriter;
83  import org.apache.commons.io.test.TestUtils;
84  import org.apache.commons.io.test.ThrowOnCloseReader;
85  import org.apache.commons.lang3.StringUtils;
86  import org.apache.commons.lang3.exception.ExceptionUtils;
87  import org.junit.jupiter.api.AfterAll;
88  import org.junit.jupiter.api.BeforeAll;
89  import org.junit.jupiter.api.BeforeEach;
90  import org.junit.jupiter.api.Disabled;
91  import org.junit.jupiter.api.Test;
92  import org.junit.jupiter.api.io.TempDir;
93  
94  /**
95   * This is used to test {@link IOUtils} for correctness. The following checks are performed:
96   * <ul>
97   * <li>The return must not be null, must be the same type and equals() to the method's second arg</li>
98   * <li>All bytes must have been read from the source (available() == 0)</li>
99   * <li>The source and destination content must be identical (byte-wise comparison check)</li>
100  * <li>The output stream must not have been closed (a byte/char is written to test this, and subsequent size
101  * checked)</li>
102  * </ul>
103  * Due to interdependencies in IOUtils and IOUtilsTest, one bug may cause multiple tests to fail.
104  */
105 @SuppressWarnings("deprecation") // deliberately testing deprecated code
106 public class IOUtilsTest {
107 
108     private static final String UTF_8 = StandardCharsets.UTF_8.name();
109 
110     private static final int FILE_SIZE = 1024 * 4 + 1;
111 
112     /** Determine if this is windows. */
113     private static final boolean WINDOWS = File.separatorChar == '\\';
114 
115     /*
116      * Note: this is not particularly beautiful code. A better way to check for flush and close status would be to
117      * implement "trojan horse" wrapper implementations of the various stream classes, which set a flag when relevant
118      * methods are called. (JT)
119      */
120 
121     @BeforeAll
122     @AfterAll
123     public static void beforeAll() {
124         // Not required, just to exercise the method and make sure there are no adverse side-effect when recycling thread locals.
125         IO.clear();
126     }
127 
128     @TempDir
129     public File temporaryFolder;
130 
131     private char[] carr;
132 
133     private byte[] iarr;
134 
135     private File testFile;
136 
137     /**
138      * Path constructed from {@code testFile}.
139      */
140     private Path testFilePath;
141 
142     /** Assert that the contents of two byte arrays are the same. */
143     private void assertEqualContent(final byte[] b0, final byte[] b1) {
144         assertArrayEquals(b0, b1, "Content not equal according to java.util.Arrays#equals()");
145     }
146 
147     @BeforeEach
148     public void setUp() {
149         try {
150             testFile = new File(temporaryFolder, "file2-test.txt");
151             testFilePath = testFile.toPath();
152 
153             if (!testFile.getParentFile().exists()) {
154                 throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist");
155             }
156             try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFilePath))) {
157                 TestUtils.generateTestData(output, FILE_SIZE);
158             }
159         } catch (final IOException e) {
160             fail("Can't run this test because the environment could not be built: " + e.getMessage());
161         }
162         // Create and init a byte array as input data
163         iarr = new byte[200];
164         Arrays.fill(iarr, (byte) -1);
165         for (int i = 0; i < 80; i++) {
166             iarr[i] = (byte) i;
167         }
168         carr = new char[200];
169         Arrays.fill(carr, (char) -1);
170         for (int i = 0; i < 80; i++) {
171             carr[i] = (char) i;
172         }
173     }
174 
175     @Test
176     public void testAsBufferedInputStream() {
177         final InputStream is = new InputStream() {
178             @Override
179             public int read() throws IOException {
180                 return 0;
181             }
182         };
183         final BufferedInputStream bis = IOUtils.buffer(is);
184         assertNotSame(is, bis);
185         assertSame(bis, IOUtils.buffer(bis));
186     }
187 
188     @Test
189     public void testAsBufferedInputStreamWithBufferSize() {
190         final InputStream is = new InputStream() {
191             @Override
192             public int read() throws IOException {
193                 return 0;
194             }
195         };
196         final BufferedInputStream bis = IOUtils.buffer(is, 2048);
197         assertNotSame(is, bis);
198         assertSame(bis, IOUtils.buffer(bis));
199         assertSame(bis, IOUtils.buffer(bis, 1024));
200     }
201 
202     @Test
203     public void testAsBufferedNull() {
204         final String npeExpectedMessage = "Expected NullPointerException";
205         assertThrows(NullPointerException.class, () -> IOUtils.buffer((InputStream) null), npeExpectedMessage);
206         assertThrows(NullPointerException.class, () -> IOUtils.buffer((OutputStream) null), npeExpectedMessage);
207         assertThrows(NullPointerException.class, () -> IOUtils.buffer((Reader) null), npeExpectedMessage);
208         assertThrows(NullPointerException.class, () -> IOUtils.buffer((Writer) null), npeExpectedMessage);
209     }
210 
211     @Test
212     public void testAsBufferedOutputStream() {
213         final OutputStream is = new OutputStream() {
214             @Override
215             public void write(final int b) throws IOException {
216             }
217         };
218         final BufferedOutputStream bis = IOUtils.buffer(is);
219         assertNotSame(is, bis);
220         assertSame(bis, IOUtils.buffer(bis));
221     }
222 
223     @Test
224     public void testAsBufferedOutputStreamWithBufferSize() {
225         final OutputStream os = new OutputStream() {
226             @Override
227             public void write(final int b) throws IOException {
228             }
229         };
230         final BufferedOutputStream bos = IOUtils.buffer(os, 2048);
231         assertNotSame(os, bos);
232         assertSame(bos, IOUtils.buffer(bos));
233         assertSame(bos, IOUtils.buffer(bos, 1024));
234     }
235 
236     @Test
237     public void testAsBufferedReader() {
238         final Reader is = new Reader() {
239             @Override
240             public void close() throws IOException {
241             }
242 
243             @Override
244             public int read(final char[] cbuf, final int off, final int len) throws IOException {
245                 return 0;
246             }
247         };
248         final BufferedReader bis = IOUtils.buffer(is);
249         assertNotSame(is, bis);
250         assertSame(bis, IOUtils.buffer(bis));
251     }
252 
253     @Test
254     public void testAsBufferedReaderWithBufferSize() {
255         final Reader r = new Reader() {
256             @Override
257             public void close() throws IOException {
258             }
259 
260             @Override
261             public int read(final char[] cbuf, final int off, final int len) throws IOException {
262                 return 0;
263             }
264         };
265         final BufferedReader br = IOUtils.buffer(r, 2048);
266         assertNotSame(r, br);
267         assertSame(br, IOUtils.buffer(br));
268         assertSame(br, IOUtils.buffer(br, 1024));
269     }
270 
271     @Test
272     public void testAsBufferedWriter() {
273         final Writer nullWriter = NullWriter.INSTANCE;
274         final BufferedWriter bis = IOUtils.buffer(nullWriter);
275         assertNotSame(nullWriter, bis);
276         assertSame(bis, IOUtils.buffer(bis));
277     }
278 
279     @Test
280     public void testAsBufferedWriterWithBufferSize() {
281         final Writer nullWriter = NullWriter.INSTANCE;
282         final BufferedWriter bw = IOUtils.buffer(nullWriter, 2024);
283         assertNotSame(nullWriter, bw);
284         assertSame(bw, IOUtils.buffer(bw));
285         assertSame(bw, IOUtils.buffer(bw, 1024));
286     }
287 
288     @Test
289     public void testAsWriterAppendable() throws IOException {
290         final Appendable a = new StringBuffer();
291         try (Writer w = IOUtils.writer(a)) {
292             assertNotSame(w, a);
293             assertEquals(AppendableWriter.class, w.getClass());
294             assertSame(w, IOUtils.writer(w));
295         }
296     }
297 
298     @Test
299     public void testAsWriterNull() {
300         assertThrows(NullPointerException.class, () -> IOUtils.writer(null));
301     }
302 
303     @Test
304     public void testAsWriterStringBuilder() throws IOException {
305         final Appendable a = new StringBuilder();
306         try (Writer w = IOUtils.writer(a)) {
307             assertNotSame(w, a);
308             assertEquals(StringBuilderWriter.class, w.getClass());
309             assertSame(w, IOUtils.writer(w));
310         }
311     }
312 
313     @Test
314     public void testByteArrayWithNegativeSize() {
315         assertThrows(NegativeArraySizeException.class, () -> IOUtils.byteArray(-1));
316     }
317 
318     @Test
319     public void testClose() {
320         assertDoesNotThrow(() -> IOUtils.close((Closeable) null));
321         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s")));
322         assertThrows(IOException.class, () -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s"))));
323     }
324 
325     @Test
326     public void testCloseConsumer() {
327         // null consumer
328         final Closeable nullCloseable = null;
329         assertDoesNotThrow(() -> IOUtils.close(nullCloseable, null));
330         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), null));
331         assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), null));
332         // null consumer doesn't throw
333         final IOConsumer<IOException> nullConsumer = null;
334         assertDoesNotThrow(() -> IOUtils.close(nullCloseable, nullConsumer));
335         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), nullConsumer));
336         assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), nullConsumer));
337         // noop consumer doesn't throw
338         final IOConsumer<IOException> silentConsumer = IOConsumer.noop();
339         assertDoesNotThrow(() -> IOUtils.close(nullCloseable, silentConsumer));
340         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), silentConsumer));
341         assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), silentConsumer));
342         // consumer passes on the throw
343         final IOConsumer<IOException> noisyConsumer = ExceptionUtils::rethrow;
344         // no throw
345         assertDoesNotThrow(() -> IOUtils.close(nullCloseable, noisyConsumer));
346         // no throw
347         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), noisyConsumer));
348         // closeable throws
349         assertThrows(IOException.class, () -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), noisyConsumer));
350         // consumes other than IOException
351         final AtomicBoolean b = new AtomicBoolean();
352         final IOConsumer<IOException> consumer = e -> b.set(true);
353         // IOException subclass
354         assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream((Throwable) new EOFException()), consumer));
355         assertTrue(b.get());
356         b.set(false);
357         // RuntimeException
358         assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream(new RuntimeException()), consumer));
359         assertTrue(b.get());
360         b.set(false);
361         // RuntimeException subclass
362         assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream(new UnsupportedOperationException()), consumer));
363         assertTrue(b.get());
364     }
365 
366     @Test
367     public void testCloseMulti() {
368         final Closeable nullCloseable = null;
369         final Closeable[] closeables = {null, null};
370         assertDoesNotThrow(() -> IOUtils.close(nullCloseable, nullCloseable));
371         assertDoesNotThrow(() -> IOUtils.close(closeables));
372         assertDoesNotThrow(() -> IOUtils.close((Closeable[]) null));
373         assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), nullCloseable));
374         assertThrows(IOException.class, () -> IOUtils.close(nullCloseable, new ThrowOnCloseReader(new StringReader("s"))));
375     }
376 
377     @Test
378     public void testCloseQuietly_AllCloseableIOException() {
379         final Closeable closeable = BrokenInputStream.INSTANCE;
380         assertDoesNotThrow(() -> IOUtils.closeQuietly(closeable, null, closeable));
381         assertDoesNotThrow(() -> IOUtils.closeQuietly(Arrays.asList(closeable, null, closeable)));
382         assertDoesNotThrow(() -> IOUtils.closeQuietly(Stream.of(closeable, null, closeable)));
383         assertDoesNotThrow(() -> IOUtils.closeQuietly((Iterable<Closeable>) null));
384     }
385 
386     @Test
387     public void testCloseQuietly_CloseableException() {
388         // IOException
389         assertDoesNotThrow(() -> IOUtils.closeQuietly(BrokenInputStream.INSTANCE));
390         assertDoesNotThrow(() -> IOUtils.closeQuietly(BrokenOutputStream.INSTANCE));
391         // IOException subclass
392         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream((Throwable) new EOFException())));
393         // RuntimeException
394         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream(new RuntimeException())));
395         // RuntimeException subclass
396         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream(new UnsupportedOperationException())));
397     }
398 
399     @Test
400     public void testCloseQuietly_CloseableExceptionConsumer() {
401         final AtomicBoolean b = new AtomicBoolean();
402         final Consumer<Exception> consumer = e -> b.set(true);
403         // IOException
404         assertDoesNotThrow(() -> IOUtils.closeQuietly(BrokenInputStream.INSTANCE, consumer));
405         assertTrue(b.get());
406         b.set(false);
407         assertDoesNotThrow(() -> IOUtils.closeQuietly(BrokenOutputStream.INSTANCE, consumer));
408         assertTrue(b.get());
409         b.set(false);
410         // IOException subclass
411         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream((Throwable) new EOFException()), consumer));
412         assertTrue(b.get());
413         b.set(false);
414         // RuntimeException
415         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream(new RuntimeException()), consumer));
416         assertTrue(b.get());
417         b.set(false);
418         // RuntimeException subclass
419         assertDoesNotThrow(() -> IOUtils.closeQuietly(new BrokenOutputStream(new UnsupportedOperationException()), consumer));
420         assertTrue(b.get());
421     }
422 
423     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
424     @Test
425     public void testCloseQuietly_Selector() {
426         Selector selector = null;
427         try {
428             selector = Selector.open();
429         } catch (final IOException ignore) {
430         } finally {
431             IOUtils.closeQuietly(selector);
432         }
433     }
434 
435     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
436     @Test
437     public void testCloseQuietly_SelectorIOException() {
438         final Selector selector = new SelectorAdapter() {
439             @Override
440             public void close() throws IOException {
441                 throw new IOException();
442             }
443         };
444         IOUtils.closeQuietly(selector);
445     }
446 
447     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
448     @Test
449     public void testCloseQuietly_SelectorNull() {
450         final Selector selector = null;
451         IOUtils.closeQuietly(selector);
452     }
453 
454     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
455     @Test
456     public void testCloseQuietly_SelectorTwice() {
457         Selector selector = null;
458         try {
459             selector = Selector.open();
460         } catch (final IOException ignore) {
461         } finally {
462             IOUtils.closeQuietly(selector);
463             IOUtils.closeQuietly(selector);
464         }
465     }
466 
467     @Test
468     public void testCloseQuietly_ServerSocket() {
469         assertDoesNotThrow(() -> IOUtils.closeQuietly((ServerSocket) null));
470         assertDoesNotThrow(() -> IOUtils.closeQuietly(new ServerSocket()));
471     }
472 
473     @Test
474     public void testCloseQuietly_ServerSocketIOException() {
475         assertDoesNotThrow(() -> {
476             IOUtils.closeQuietly(new ServerSocket() {
477                 @Override
478                 public void close() throws IOException {
479                     throw new IOException();
480                 }
481             });
482         });
483     }
484 
485     @Test
486     public void testCloseQuietly_Socket() {
487         assertDoesNotThrow(() -> IOUtils.closeQuietly((Socket) null));
488         assertDoesNotThrow(() -> IOUtils.closeQuietly(new Socket()));
489     }
490 
491     @Test
492     public void testCloseQuietly_SocketIOException() {
493         assertDoesNotThrow(() -> {
494             IOUtils.closeQuietly(new Socket() {
495                 @Override
496                 public synchronized void close() throws IOException {
497                     throw new IOException();
498                 }
499             });
500         });
501     }
502 
503     @Test
504     public void testCloseURLConnection() {
505         assertDoesNotThrow(() -> IOUtils.close((URLConnection) null));
506         assertDoesNotThrow(() -> IOUtils.close(new URL("https://www.apache.org/").openConnection()));
507         assertDoesNotThrow(() -> IOUtils.close(new URL("file:///").openConnection()));
508     }
509 
510     @Test
511     public void testConstants() {
512         assertEquals('/', IOUtils.DIR_SEPARATOR_UNIX);
513         assertEquals('\\', IOUtils.DIR_SEPARATOR_WINDOWS);
514         assertEquals("\n", IOUtils.LINE_SEPARATOR_UNIX);
515         assertEquals("\r\n", IOUtils.LINE_SEPARATOR_WINDOWS);
516         if (WINDOWS) {
517             assertEquals('\\', IOUtils.DIR_SEPARATOR);
518             assertEquals("\r\n", IOUtils.LINE_SEPARATOR);
519         } else {
520             assertEquals('/', IOUtils.DIR_SEPARATOR);
521             assertEquals("\n", IOUtils.LINE_SEPARATOR);
522         }
523         assertEquals('\r', IOUtils.CR);
524         assertEquals('\n', IOUtils.LF);
525         assertEquals(-1, IOUtils.EOF);
526     }
527 
528     @Test
529     public void testConsumeInputStream() throws Exception {
530         final long size = (long) Integer.MAX_VALUE + (long) 1;
531         final NullInputStream in = new NullInputStream(size);
532         final OutputStream out = NullOutputStream.INSTANCE;
533 
534         // Test copy() method
535         assertEquals(-1, IOUtils.copy(in, out));
536 
537         // reset the input
538         in.init();
539 
540         // Test consume() method
541         assertEquals(size, IOUtils.consume(in), "consume()");
542     }
543 
544     @Test
545     public void testConsumeReader() throws Exception {
546         final long size = (long) Integer.MAX_VALUE + (long) 1;
547         final Reader in = new NullReader(size);
548         final Writer out = NullWriter.INSTANCE;
549 
550         // Test copy() method
551         assertEquals(-1, IOUtils.copy(in, out));
552 
553         // reset the input
554         in.close();
555 
556         // Test consume() method
557         assertEquals(size, IOUtils.consume(in), "consume()");
558     }
559 
560     @Test
561     public void testContentEquals_InputStream_InputStream() throws Exception {
562         {
563             assertTrue(IOUtils.contentEquals((InputStream) null, null));
564         }
565         final byte[] dataEmpty = "".getBytes(StandardCharsets.UTF_8);
566         final byte[] dataAbc = "ABC".getBytes(StandardCharsets.UTF_8);
567         final byte[] dataAbcd = "ABCD".getBytes(StandardCharsets.UTF_8);
568         {
569             final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty);
570             assertFalse(IOUtils.contentEquals(input1, null));
571         }
572         {
573             final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty);
574             assertFalse(IOUtils.contentEquals(null, input1));
575         }
576         {
577             final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty);
578             assertTrue(IOUtils.contentEquals(input1, input1));
579         }
580         {
581             final ByteArrayInputStream input1 = new ByteArrayInputStream(dataAbc);
582             assertTrue(IOUtils.contentEquals(input1, input1));
583         }
584         assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(dataEmpty), new ByteArrayInputStream(dataEmpty)));
585         assertTrue(IOUtils.contentEquals(new BufferedInputStream(new ByteArrayInputStream(dataEmpty)),
586             new BufferedInputStream(new ByteArrayInputStream(dataEmpty))));
587         assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(dataAbc), new ByteArrayInputStream(dataAbc)));
588         assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(dataAbcd), new ByteArrayInputStream(dataAbc)));
589         assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(dataAbc), new ByteArrayInputStream(dataAbcd)));
590         assertFalse(IOUtils.contentEquals(new ByteArrayInputStream("apache".getBytes(StandardCharsets.UTF_8)),
591                 new ByteArrayInputStream("apacha".getBytes(StandardCharsets.UTF_8))));
592         // Tests with larger inputs that DEFAULT_BUFFER_SIZE in case internal buffers are used.
593         final byte[] bytes2XDefaultA = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2];
594         final byte[] bytes2XDefaultB = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2];
595         final byte[] bytes2XDefaultA2 = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2];
596         Arrays.fill(bytes2XDefaultA, (byte) 'a');
597         Arrays.fill(bytes2XDefaultB, (byte) 'b');
598         Arrays.fill(bytes2XDefaultA2, (byte) 'a');
599         bytes2XDefaultA2[bytes2XDefaultA2.length - 1] = 'd';
600         assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA),
601             new ByteArrayInputStream(bytes2XDefaultB)));
602         assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA),
603             new ByteArrayInputStream(bytes2XDefaultA2)));
604         assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA),
605             new ByteArrayInputStream(bytes2XDefaultA)));
606         // FileInputStream a bit more than 16 k.
607         try (
608             FileInputStream input1 = new FileInputStream(
609                 "src/test/resources/org/apache/commons/io/abitmorethan16k.txt");
610             FileInputStream input2 = new FileInputStream(
611                 "src/test/resources/org/apache/commons/io/abitmorethan16kcopy.txt")) {
612             assertTrue(IOUtils.contentEquals(input1, input1));
613         }
614     }
615 
616     @Test
617     public void testContentEquals_Reader_Reader() throws Exception {
618         {
619             assertTrue(IOUtils.contentEquals((Reader) null, null));
620         }
621         {
622             final StringReader input1 = new StringReader("");
623             assertFalse(IOUtils.contentEquals(null, input1));
624         }
625         {
626             final StringReader input1 = new StringReader("");
627             assertFalse(IOUtils.contentEquals(input1, null));
628         }
629         {
630             final StringReader input1 = new StringReader("");
631             assertTrue(IOUtils.contentEquals(input1, input1));
632         }
633         {
634             final StringReader input1 = new StringReader("ABC");
635             assertTrue(IOUtils.contentEquals(input1, input1));
636         }
637         assertTrue(IOUtils.contentEquals(new StringReader(""), new StringReader("")));
638         assertTrue(
639             IOUtils.contentEquals(new BufferedReader(new StringReader("")), new BufferedReader(new StringReader(""))));
640         assertTrue(IOUtils.contentEquals(new StringReader("ABC"), new StringReader("ABC")));
641         assertFalse(IOUtils.contentEquals(new StringReader("ABCD"), new StringReader("ABC")));
642         assertFalse(IOUtils.contentEquals(new StringReader("ABC"), new StringReader("ABCD")));
643         assertFalse(IOUtils.contentEquals(new StringReader("apache"), new StringReader("apacha")));
644     }
645 
646     @Test
647     public void testContentEqualsIgnoreEOL() throws Exception {
648         {
649             assertTrue(IOUtils.contentEqualsIgnoreEOL(null, null));
650         }
651         final char[] empty = {};
652         {
653             final Reader input1 = new CharArrayReader(empty);
654             assertFalse(IOUtils.contentEqualsIgnoreEOL(null, input1));
655         }
656         {
657             final Reader input1 = new CharArrayReader(empty);
658             assertFalse(IOUtils.contentEqualsIgnoreEOL(input1, null));
659         }
660         {
661             final Reader input1 = new CharArrayReader(empty);
662             assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1));
663         }
664         {
665             final Reader input1 = new CharArrayReader("321\r\n".toCharArray());
666             assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1));
667         }
668 
669         testSingleEOL("", "", true);
670         testSingleEOL("", "\n", false);
671         testSingleEOL("", "\r", false);
672         testSingleEOL("", "\r\n", false);
673         testSingleEOL("", "\r\r", false);
674         testSingleEOL("", "\n\n", false);
675         testSingleEOL("1", "1", true);
676         testSingleEOL("1", "2", false);
677         testSingleEOL("123\rabc", "123\nabc", true);
678         testSingleEOL("321", "321\r\n", true);
679         testSingleEOL("321", "321\r\naabb", false);
680         testSingleEOL("321", "321\n", true);
681         testSingleEOL("321", "321\r", true);
682         testSingleEOL("321", "321\r\n", true);
683         testSingleEOL("321", "321\r\r", false);
684         testSingleEOL("321", "321\n\r", false);
685         testSingleEOL("321\n", "321", true);
686         testSingleEOL("321\n", "321\n\r", false);
687         testSingleEOL("321\n", "321\r\n", true);
688         testSingleEOL("321\r", "321\r\n", true);
689         testSingleEOL("321\r\n", "321\r\n\r", false);
690         testSingleEOL("123", "1234", false);
691         testSingleEOL("1235", "1234", false);
692     }
693 
694     @Test
695     public void testContentEqualsSequenceInputStream() throws Exception {
696         // https://issues.apache.org/jira/browse/IO-866
697         // not equals
698         // @formatter:off
699         assertFalse(IOUtils.contentEquals(
700                 new ByteArrayInputStream("ab".getBytes()),
701                 new SequenceInputStream(
702                     new ByteArrayInputStream("a".getBytes()),
703                     new ByteArrayInputStream("b-".getBytes()))));
704         assertFalse(IOUtils.contentEquals(
705                 new ByteArrayInputStream("ab".getBytes()),
706                 new SequenceInputStream(
707                     new ByteArrayInputStream("a-".getBytes()),
708                     new ByteArrayInputStream("b".getBytes()))));
709         assertFalse(IOUtils.contentEquals(
710                 new ByteArrayInputStream("ab-".getBytes()),
711                 new SequenceInputStream(
712                     new ByteArrayInputStream("a".getBytes()),
713                     new ByteArrayInputStream("b".getBytes()))));
714         assertFalse(IOUtils.contentEquals(
715                 new ByteArrayInputStream("".getBytes()),
716                 new SequenceInputStream(
717                     new ByteArrayInputStream("a".getBytes()),
718                     new ByteArrayInputStream("b".getBytes()))));
719         assertFalse(IOUtils.contentEquals(
720                 new ByteArrayInputStream("".getBytes()),
721                 new SequenceInputStream(
722                     new ByteArrayInputStream("".getBytes()),
723                     new ByteArrayInputStream("b".getBytes()))));
724         assertFalse(IOUtils.contentEquals(
725                 new ByteArrayInputStream("ab".getBytes()),
726                 new SequenceInputStream(
727                     new ByteArrayInputStream("".getBytes()),
728                     new ByteArrayInputStream("".getBytes()))));
729         // equals
730         assertTrue(IOUtils.contentEquals(
731                 new ByteArrayInputStream("".getBytes()),
732                 new SequenceInputStream(
733                     new ByteArrayInputStream("".getBytes()),
734                     new ByteArrayInputStream("".getBytes()))));
735         assertTrue(IOUtils.contentEquals(
736                 new ByteArrayInputStream("ab".getBytes()),
737                 new SequenceInputStream(
738                     new ByteArrayInputStream("a".getBytes()),
739                     new ByteArrayInputStream("b".getBytes()))));
740         assertTrue(IOUtils.contentEquals(
741                 new ByteArrayInputStream("ab".getBytes()),
742                 new SequenceInputStream(
743                     new ByteArrayInputStream("ab".getBytes()),
744                     new ByteArrayInputStream("".getBytes()))));
745         assertTrue(IOUtils.contentEquals(
746                 new ByteArrayInputStream("ab".getBytes()),
747                 new SequenceInputStream(
748                     new ByteArrayInputStream("".getBytes()),
749                     new ByteArrayInputStream("ab".getBytes()))));
750         // @formatter:on
751         final byte[] prefixLen32 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2 };
752         final byte[] suffixLen2 = { 1, 2 };
753         final byte[] fileContents = "someTexts".getBytes(StandardCharsets.UTF_8);
754         Files.write(testFile.toPath(), fileContents);
755         final byte[] expected = new byte[prefixLen32.length + fileContents.length + suffixLen2.length];
756         System.arraycopy(prefixLen32, 0, expected, 0, prefixLen32.length);
757         System.arraycopy(fileContents, 0, expected, prefixLen32.length, fileContents.length);
758         System.arraycopy(suffixLen2, 0, expected, prefixLen32.length + fileContents.length, suffixLen2.length);
759         // @formatter:off
760         assertTrue(IOUtils.contentEquals(
761                 new ByteArrayInputStream(expected),
762                 new SequenceInputStream(
763                     Collections.enumeration(
764                         Arrays.asList(
765                             new ByteArrayInputStream(prefixLen32),
766                             new FileInputStream(testFile),
767                             new ByteArrayInputStream(suffixLen2))))));
768         // @formatter:on
769     }
770 
771     @Test
772     public void testCopy_ByteArray_OutputStream() throws Exception {
773         final File destination = TestUtils.newFile(temporaryFolder, "copy8.txt");
774         final byte[] in;
775         try (InputStream fin = Files.newInputStream(testFilePath)) {
776             // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid.
777             in = IOUtils.toByteArray(fin);
778         }
779 
780         try (OutputStream fout = Files.newOutputStream(destination.toPath())) {
781             CopyUtils.copy(in, fout);
782 
783             fout.flush();
784 
785             TestUtils.checkFile(destination, testFile);
786             TestUtils.checkWrite(fout);
787         }
788         TestUtils.deleteFile(destination);
789     }
790 
791     @Test
792     public void testCopy_ByteArray_Writer() throws Exception {
793         final File destination = TestUtils.newFile(temporaryFolder, "copy7.txt");
794         final byte[] in;
795         try (InputStream fin = Files.newInputStream(testFilePath)) {
796             // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid.
797             in = IOUtils.toByteArray(fin);
798         }
799 
800         try (Writer fout = Files.newBufferedWriter(destination.toPath())) {
801             CopyUtils.copy(in, fout);
802             fout.flush();
803             TestUtils.checkFile(destination, testFile);
804             TestUtils.checkWrite(fout);
805         }
806         TestUtils.deleteFile(destination);
807     }
808 
809     @Test
810     public void testCopy_String_Writer() throws Exception {
811         final File destination = TestUtils.newFile(temporaryFolder, "copy6.txt");
812         final String str;
813         try (Reader fin = Files.newBufferedReader(testFilePath)) {
814             // Create our String. Rely on testReaderToString() to make sure this is valid.
815             str = IOUtils.toString(fin);
816         }
817 
818         try (Writer fout = Files.newBufferedWriter(destination.toPath())) {
819             CopyUtils.copy(str, fout);
820             fout.flush();
821 
822             TestUtils.checkFile(destination, testFile);
823             TestUtils.checkWrite(fout);
824         }
825         TestUtils.deleteFile(destination);
826     }
827 
828     @Test
829     public void testCopyLarge_CharExtraLength() throws IOException {
830         CharArrayReader is = null;
831         CharArrayWriter os = null;
832         try {
833             // Create streams
834             is = new CharArrayReader(carr);
835             os = new CharArrayWriter();
836 
837             // Test our copy method
838             // for extra length, it reads till EOF
839             assertEquals(200, IOUtils.copyLarge(is, os, 0, 2000));
840             final char[] oarr = os.toCharArray();
841 
842             // check that output length is correct
843             assertEquals(200, oarr.length);
844             // check that output data corresponds to input data
845             assertEquals(1, oarr[1]);
846             assertEquals(79, oarr[79]);
847             assertEquals((char) -1, oarr[80]);
848 
849         } finally {
850             IOUtils.closeQuietly(is);
851             IOUtils.closeQuietly(os);
852         }
853     }
854 
855     @Test
856     public void testCopyLarge_CharFullLength() throws IOException {
857         CharArrayReader is = null;
858         CharArrayWriter os = null;
859         try {
860             // Create streams
861             is = new CharArrayReader(carr);
862             os = new CharArrayWriter();
863 
864             // Test our copy method
865             assertEquals(200, IOUtils.copyLarge(is, os, 0, -1));
866             final char[] oarr = os.toCharArray();
867 
868             // check that output length is correct
869             assertEquals(200, oarr.length);
870             // check that output data corresponds to input data
871             assertEquals(1, oarr[1]);
872             assertEquals(79, oarr[79]);
873             assertEquals((char) -1, oarr[80]);
874 
875         } finally {
876             IOUtils.closeQuietly(is);
877             IOUtils.closeQuietly(os);
878         }
879     }
880 
881     @Test
882     public void testCopyLarge_CharNoSkip() throws IOException {
883         CharArrayReader is = null;
884         CharArrayWriter os = null;
885         try {
886             // Create streams
887             is = new CharArrayReader(carr);
888             os = new CharArrayWriter();
889 
890             // Test our copy method
891             assertEquals(100, IOUtils.copyLarge(is, os, 0, 100));
892             final char[] oarr = os.toCharArray();
893 
894             // check that output length is correct
895             assertEquals(100, oarr.length);
896             // check that output data corresponds to input data
897             assertEquals(1, oarr[1]);
898             assertEquals(79, oarr[79]);
899             assertEquals((char) -1, oarr[80]);
900 
901         } finally {
902             IOUtils.closeQuietly(is);
903             IOUtils.closeQuietly(os);
904         }
905     }
906 
907     @Test
908     public void testCopyLarge_CharSkip() throws IOException {
909         CharArrayReader is = null;
910         CharArrayWriter os = null;
911         try {
912             // Create streams
913             is = new CharArrayReader(carr);
914             os = new CharArrayWriter();
915 
916             // Test our copy method
917             assertEquals(100, IOUtils.copyLarge(is, os, 10, 100));
918             final char[] oarr = os.toCharArray();
919 
920             // check that output length is correct
921             assertEquals(100, oarr.length);
922             // check that output data corresponds to input data
923             assertEquals(11, oarr[1]);
924             assertEquals(79, oarr[69]);
925             assertEquals((char) -1, oarr[70]);
926 
927         } finally {
928             IOUtils.closeQuietly(is);
929             IOUtils.closeQuietly(os);
930         }
931     }
932 
933     @Test
934     public void testCopyLarge_CharSkipInvalid() {
935         try (CharArrayReader is = new CharArrayReader(carr); CharArrayWriter os = new CharArrayWriter()) {
936             assertThrows(EOFException.class, () -> IOUtils.copyLarge(is, os, 1000, 100));
937         }
938     }
939 
940     @Test
941     public void testCopyLarge_ExtraLength() throws IOException {
942         try (ByteArrayInputStream is = new ByteArrayInputStream(iarr);
943             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
944             // Create streams
945 
946             // Test our copy method
947             // for extra length, it reads till EOF
948             assertEquals(200, IOUtils.copyLarge(is, os, 0, 2000));
949             final byte[] oarr = os.toByteArray();
950 
951             // check that output length is correct
952             assertEquals(200, oarr.length);
953             // check that output data corresponds to input data
954             assertEquals(1, oarr[1]);
955             assertEquals(79, oarr[79]);
956             assertEquals(-1, oarr[80]);
957         }
958     }
959 
960     @Test
961     public void testCopyLarge_FullLength() throws IOException {
962         try (ByteArrayInputStream is = new ByteArrayInputStream(iarr);
963             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
964             // Test our copy method
965             assertEquals(200, IOUtils.copyLarge(is, os, 0, -1));
966             final byte[] oarr = os.toByteArray();
967 
968             // check that output length is correct
969             assertEquals(200, oarr.length);
970             // check that output data corresponds to input data
971             assertEquals(1, oarr[1]);
972             assertEquals(79, oarr[79]);
973             assertEquals(-1, oarr[80]);
974         }
975     }
976 
977     @Test
978     public void testCopyLarge_NoSkip() throws IOException {
979         try (ByteArrayInputStream is = new ByteArrayInputStream(iarr);
980             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
981             // Test our copy method
982             assertEquals(100, IOUtils.copyLarge(is, os, 0, 100));
983             final byte[] oarr = os.toByteArray();
984 
985             // check that output length is correct
986             assertEquals(100, oarr.length);
987             // check that output data corresponds to input data
988             assertEquals(1, oarr[1]);
989             assertEquals(79, oarr[79]);
990             assertEquals(-1, oarr[80]);
991         }
992     }
993 
994     @Test
995     public void testCopyLarge_Skip() throws IOException {
996         try (ByteArrayInputStream is = new ByteArrayInputStream(iarr);
997             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
998             // Test our copy method
999             assertEquals(100, IOUtils.copyLarge(is, os, 10, 100));
1000             final byte[] oarr = os.toByteArray();
1001 
1002             // check that output length is correct
1003             assertEquals(100, oarr.length);
1004             // check that output data corresponds to input data
1005             assertEquals(11, oarr[1]);
1006             assertEquals(79, oarr[69]);
1007             assertEquals(-1, oarr[70]);
1008         }
1009     }
1010 
1011     @Test
1012     public void testCopyLarge_SkipInvalid() throws IOException {
1013         try (ByteArrayInputStream is = new ByteArrayInputStream(iarr);
1014             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
1015             // Test our copy method
1016             assertThrows(EOFException.class, () -> IOUtils.copyLarge(is, os, 1000, 100));
1017         }
1018     }
1019 
1020     @Test
1021     public void testCopyLarge_SkipWithInvalidOffset() throws IOException {
1022         ByteArrayInputStream is = null;
1023         ByteArrayOutputStream os = null;
1024         try {
1025             // Create streams
1026             is = new ByteArrayInputStream(iarr);
1027             os = new ByteArrayOutputStream();
1028 
1029             // Test our copy method
1030             assertEquals(100, IOUtils.copyLarge(is, os, -10, 100));
1031             final byte[] oarr = os.toByteArray();
1032 
1033             // check that output length is correct
1034             assertEquals(100, oarr.length);
1035             // check that output data corresponds to input data
1036             assertEquals(1, oarr[1]);
1037             assertEquals(79, oarr[79]);
1038             assertEquals(-1, oarr[80]);
1039 
1040         } finally {
1041             IOUtils.closeQuietly(is);
1042             IOUtils.closeQuietly(os);
1043         }
1044     }
1045 
1046     @Test
1047     public void testRead_ReadableByteChannel() throws Exception {
1048         final ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
1049         final FileInputStream fileInputStream = new FileInputStream(testFile);
1050         final FileChannel input = fileInputStream.getChannel();
1051         try {
1052             assertEquals(FILE_SIZE, IOUtils.read(input, buffer));
1053             assertEquals(0, IOUtils.read(input, buffer));
1054             assertEquals(0, buffer.remaining());
1055             assertEquals(0, input.read(buffer));
1056             buffer.clear();
1057             assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer), "Should have failed with EOFException");
1058         } finally {
1059             IOUtils.closeQuietly(input, fileInputStream);
1060         }
1061     }
1062 
1063     @Test
1064     public void testReadFully_InputStream__ReturnByteArray() throws Exception {
1065         final byte[] bytes = "abcd1234".getBytes(StandardCharsets.UTF_8);
1066         final ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
1067 
1068         final byte[] result = IOUtils.readFully(stream, bytes.length);
1069 
1070         IOUtils.closeQuietly(stream);
1071 
1072         assertEqualContent(result, bytes);
1073     }
1074 
1075     @Test
1076     public void testReadFully_InputStream_ByteArray() throws Exception {
1077         final int size = 1027;
1078         final byte[] buffer = new byte[size];
1079         final InputStream input = new ByteArrayInputStream(new byte[size]);
1080 
1081         assertThrows(IllegalArgumentException.class, () -> IOUtils.readFully(input, buffer, 0, -1), "Should have failed with IllegalArgumentException");
1082 
1083         IOUtils.readFully(input, buffer, 0, 0);
1084         IOUtils.readFully(input, buffer, 0, size - 1);
1085         assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer, 0, 2), "Should have failed with EOFException");
1086         IOUtils.closeQuietly(input);
1087     }
1088 
1089     @Test
1090     public void testReadFully_InputStream_Offset() throws Exception {
1091         final InputStream stream = CharSequenceInputStream.builder().setCharSequence("abcd1234").setCharset(StandardCharsets.UTF_8).get();
1092         final byte[] buffer = "wx00000000".getBytes(StandardCharsets.UTF_8);
1093         IOUtils.readFully(stream, buffer, 2, 8);
1094         assertEquals("wxabcd1234", new String(buffer, 0, buffer.length, StandardCharsets.UTF_8));
1095         IOUtils.closeQuietly(stream);
1096     }
1097 
1098     @Test
1099     public void testReadFully_ReadableByteChannel() throws Exception {
1100         final ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
1101         final FileInputStream fileInputStream = new FileInputStream(testFile);
1102         final FileChannel input = fileInputStream.getChannel();
1103         try {
1104             IOUtils.readFully(input, buffer);
1105             assertEquals(FILE_SIZE, buffer.position());
1106             assertEquals(0, buffer.remaining());
1107             assertEquals(0, input.read(buffer));
1108             IOUtils.readFully(input, buffer);
1109             assertEquals(FILE_SIZE, buffer.position());
1110             assertEquals(0, buffer.remaining());
1111             assertEquals(0, input.read(buffer));
1112             IOUtils.readFully(input, buffer);
1113             buffer.clear();
1114             assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer), "Should have failed with EOFxception");
1115         } finally {
1116             IOUtils.closeQuietly(input, fileInputStream);
1117         }
1118     }
1119 
1120     @Test
1121     public void testReadFully_Reader() throws Exception {
1122         final int size = 1027;
1123         final char[] buffer = new char[size];
1124         final Reader input = new CharArrayReader(new char[size]);
1125 
1126         IOUtils.readFully(input, buffer, 0, 0);
1127         IOUtils.readFully(input, buffer, 0, size - 3);
1128         assertThrows(IllegalArgumentException.class, () -> IOUtils.readFully(input, buffer, 0, -1), "Should have failed with IllegalArgumentException");
1129         assertThrows(EOFException.class, () -> IOUtils.readFully(input, buffer, 0, 5), "Should have failed with EOFException");
1130         IOUtils.closeQuietly(input);
1131     }
1132 
1133     @Test
1134     public void testReadFully_Reader_Offset() throws Exception {
1135         final Reader reader = new StringReader("abcd1234");
1136         final char[] buffer = "wx00000000".toCharArray();
1137         IOUtils.readFully(reader, buffer, 2, 8);
1138         assertEquals("wxabcd1234", new String(buffer));
1139         IOUtils.closeQuietly(reader);
1140     }
1141 
1142     @Test
1143     public void testReadLines_CharSequence() throws IOException {
1144         final File file = TestUtils.newFile(temporaryFolder, "lines.txt");
1145         CharSequence csq = null;
1146         try {
1147             final String[] data = {"hello", "\u1234", "", "this is", "some text"};
1148             TestUtils.createLineFileUtf8(file, data);
1149             csq = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
1150             final List<String> lines = IOUtils.readLines(csq);
1151             assertEquals(Arrays.asList(data), lines);
1152         } finally {
1153             TestUtils.deleteFile(file);
1154         }
1155     }
1156 
1157     @Test
1158     public void testReadLines_CharSequenceAsStringBuilder() throws IOException {
1159         final File file = TestUtils.newFile(temporaryFolder, "lines.txt");
1160         StringBuilder csq = null;
1161         try {
1162             final String[] data = {"hello", "\u1234", "", "this is", "some text"};
1163             TestUtils.createLineFileUtf8(file, data);
1164             csq = new StringBuilder(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8));
1165             final List<String> lines = IOUtils.readLines(csq);
1166             assertEquals(Arrays.asList(data), lines);
1167         } finally {
1168             TestUtils.deleteFile(file);
1169         }
1170     }
1171 
1172     @Test
1173     public void testReadLines_InputStream() throws Exception {
1174         final File file = TestUtils.newFile(temporaryFolder, "lines.txt");
1175         InputStream in = null;
1176         try {
1177             final String[] data = {"hello", "world", "", "this is", "some text"};
1178             TestUtils.createLineFileUtf8(file, data);
1179 
1180             in = Files.newInputStream(file.toPath());
1181             final List<String> lines = IOUtils.readLines(in);
1182             assertEquals(Arrays.asList(data), lines);
1183             assertEquals(-1, in.read());
1184         } finally {
1185             IOUtils.closeQuietly(in);
1186             TestUtils.deleteFile(file);
1187         }
1188     }
1189 
1190     @Test
1191     public void testReadLines_InputStream_String() throws Exception {
1192         final File file = TestUtils.newFile(temporaryFolder, "lines.txt");
1193         InputStream in = null;
1194         try {
1195             final String[] data = { "\u4f60\u597d", "hello", "\u1234", "", "this is", "some text" };
1196             TestUtils.createLineFileUtf8(file, data);
1197             in = Files.newInputStream(file.toPath());
1198             final List<String> lines = IOUtils.readLines(in, UTF_8);
1199             assertEquals(Arrays.asList(data), lines);
1200             assertEquals(-1, in.read());
1201         } finally {
1202             IOUtils.closeQuietly(in);
1203             TestUtils.deleteFile(file);
1204         }
1205     }
1206 
1207     @Test
1208     public void testReadLines_Reader() throws Exception {
1209         final File file = TestUtils.newFile(temporaryFolder, "lines.txt");
1210         Reader in = null;
1211         try {
1212             // Don't use non-ASCII in this test fixture because this test uses the default platform encoding.
1213             final String[] data = {"hello", "1234", "", "this is", "some text"};
1214             TestUtils.createLineFileUtf8(file, data);
1215             in = new InputStreamReader(Files.newInputStream(file.toPath()));
1216             final List<String> lines = IOUtils.readLines(in);
1217             assertEquals(Arrays.asList(data), lines);
1218             assertEquals(-1, in.read());
1219         } finally {
1220             IOUtils.closeQuietly(in);
1221             TestUtils.deleteFile(file);
1222         }
1223     }
1224 
1225     @Test
1226     public void testResourceToByteArray_ExistingResourceAtRootPackage() throws Exception {
1227         final long fileSize = TestResources.getFile("test-file-utf8.bin").length();
1228         final byte[] bytes = IOUtils.resourceToByteArray("/org/apache/commons/io/test-file-utf8.bin");
1229         assertNotNull(bytes);
1230         assertEquals(fileSize, bytes.length);
1231     }
1232 
1233     @Test
1234     public void testResourceToByteArray_ExistingResourceAtRootPackage_WithClassLoader() throws Exception {
1235         final long fileSize = TestResources.getFile("test-file-utf8.bin").length();
1236         final byte[] bytes = IOUtils.resourceToByteArray("org/apache/commons/io/test-file-utf8.bin",
1237             ClassLoader.getSystemClassLoader());
1238         assertNotNull(bytes);
1239         assertEquals(fileSize, bytes.length);
1240     }
1241 
1242     @Test
1243     public void testResourceToByteArray_ExistingResourceAtSubPackage() throws Exception {
1244         final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length();
1245         final byte[] bytes = IOUtils.resourceToByteArray("/org/apache/commons/io/FileUtilsTestDataCR.dat");
1246         assertNotNull(bytes);
1247         assertEquals(fileSize, bytes.length);
1248     }
1249 
1250     @Test
1251     public void testResourceToByteArray_ExistingResourceAtSubPackage_WithClassLoader() throws Exception {
1252         final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length();
1253         final byte[] bytes = IOUtils.resourceToByteArray("org/apache/commons/io/FileUtilsTestDataCR.dat",
1254             ClassLoader.getSystemClassLoader());
1255         assertNotNull(bytes);
1256         assertEquals(fileSize, bytes.length);
1257     }
1258 
1259     @Test
1260     public void testResourceToByteArray_NonExistingResource() {
1261         assertThrows(IOException.class, () -> IOUtils.resourceToByteArray("/non-existing-file.bin"));
1262     }
1263 
1264     @Test
1265     public void testResourceToByteArray_NonExistingResource_WithClassLoader() {
1266         assertThrows(IOException.class,
1267             () -> IOUtils.resourceToByteArray("non-existing-file.bin", ClassLoader.getSystemClassLoader()));
1268     }
1269 
1270     @Test
1271     public void testResourceToByteArray_Null() {
1272         assertThrows(NullPointerException.class, () -> IOUtils.resourceToByteArray(null));
1273     }
1274 
1275     @Test
1276     public void testResourceToByteArray_Null_WithClassLoader() {
1277         assertThrows(NullPointerException.class,
1278             () -> IOUtils.resourceToByteArray(null, ClassLoader.getSystemClassLoader()));
1279     }
1280 
1281     @Test
1282     public void testResourceToString_ExistingResourceAtRootPackage() throws Exception {
1283         final long fileSize = TestResources.getFile("test-file-simple-utf8.bin").length();
1284         final String content = IOUtils.resourceToString("/org/apache/commons/io/test-file-simple-utf8.bin",
1285             StandardCharsets.UTF_8);
1286 
1287         assertNotNull(content);
1288         assertEquals(fileSize, content.getBytes().length);
1289     }
1290 
1291     @Test
1292     public void testResourceToString_ExistingResourceAtRootPackage_WithClassLoader() throws Exception {
1293         final long fileSize = TestResources.getFile("test-file-simple-utf8.bin").length();
1294         final String content = IOUtils.resourceToString("org/apache/commons/io/test-file-simple-utf8.bin",
1295             StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader());
1296 
1297         assertNotNull(content);
1298         assertEquals(fileSize, content.getBytes().length);
1299     }
1300 
1301     @Test
1302     public void testResourceToString_ExistingResourceAtSubPackage() throws Exception {
1303         final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length();
1304         final String content = IOUtils.resourceToString("/org/apache/commons/io/FileUtilsTestDataCR.dat",
1305             StandardCharsets.UTF_8);
1306 
1307         assertNotNull(content);
1308         assertEquals(fileSize, content.getBytes().length);
1309     }
1310 
1311     // Tests from IO-305
1312 
1313     @Test
1314     public void testResourceToString_ExistingResourceAtSubPackage_WithClassLoader() throws Exception {
1315         final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length();
1316         final String content = IOUtils.resourceToString("org/apache/commons/io/FileUtilsTestDataCR.dat",
1317             StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader());
1318 
1319         assertNotNull(content);
1320         assertEquals(fileSize, content.getBytes().length);
1321     }
1322 
1323     @Test
1324     public void testResourceToString_NonExistingResource() {
1325         assertThrows(IOException.class,
1326             () -> IOUtils.resourceToString("/non-existing-file.bin", StandardCharsets.UTF_8));
1327     }
1328 
1329     @Test
1330     public void testResourceToString_NonExistingResource_WithClassLoader() {
1331         assertThrows(IOException.class, () -> IOUtils.resourceToString("non-existing-file.bin", StandardCharsets.UTF_8,
1332             ClassLoader.getSystemClassLoader()));
1333     }
1334 
1335     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
1336     @Test
1337     public void testResourceToString_NullCharset() throws Exception {
1338         IOUtils.resourceToString("/org/apache/commons/io//test-file-utf8.bin", null);
1339     }
1340 
1341     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
1342     @Test
1343     public void testResourceToString_NullCharset_WithClassLoader() throws Exception {
1344         IOUtils.resourceToString("org/apache/commons/io/test-file-utf8.bin", null, ClassLoader.getSystemClassLoader());
1345     }
1346 
1347     @Test
1348     public void testResourceToString_NullResource() {
1349         assertThrows(NullPointerException.class, () -> IOUtils.resourceToString(null, StandardCharsets.UTF_8));
1350     }
1351 
1352     @Test
1353     public void testResourceToString_NullResource_WithClassLoader() {
1354         assertThrows(NullPointerException.class,
1355             () -> IOUtils.resourceToString(null, StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader()));
1356     }
1357 
1358     @Test
1359     public void testResourceToURL_ExistingResourceAtRootPackage() throws Exception {
1360         final URL url = IOUtils.resourceToURL("/org/apache/commons/io/test-file-utf8.bin");
1361         assertNotNull(url);
1362         assertTrue(url.getFile().endsWith("/test-file-utf8.bin"));
1363     }
1364 
1365     @Test
1366     public void testResourceToURL_ExistingResourceAtRootPackage_WithClassLoader() throws Exception {
1367         final URL url = IOUtils.resourceToURL("org/apache/commons/io/test-file-utf8.bin",
1368             ClassLoader.getSystemClassLoader());
1369         assertNotNull(url);
1370         assertTrue(url.getFile().endsWith("/org/apache/commons/io/test-file-utf8.bin"));
1371     }
1372 
1373     @Test
1374     public void testResourceToURL_ExistingResourceAtSubPackage() throws Exception {
1375         final URL url = IOUtils.resourceToURL("/org/apache/commons/io/FileUtilsTestDataCR.dat");
1376         assertNotNull(url);
1377         assertTrue(url.getFile().endsWith("/org/apache/commons/io/FileUtilsTestDataCR.dat"));
1378     }
1379 
1380     @Test
1381     public void testResourceToURL_ExistingResourceAtSubPackage_WithClassLoader() throws Exception {
1382         final URL url = IOUtils.resourceToURL("org/apache/commons/io/FileUtilsTestDataCR.dat",
1383             ClassLoader.getSystemClassLoader());
1384 
1385         assertNotNull(url);
1386         assertTrue(url.getFile().endsWith("/org/apache/commons/io/FileUtilsTestDataCR.dat"));
1387     }
1388 
1389     @Test
1390     public void testResourceToURL_NonExistingResource() {
1391         assertThrows(IOException.class, () -> IOUtils.resourceToURL("/non-existing-file.bin"));
1392     }
1393 
1394     @Test
1395     public void testResourceToURL_NonExistingResource_WithClassLoader() {
1396         assertThrows(IOException.class,
1397             () -> IOUtils.resourceToURL("non-existing-file.bin", ClassLoader.getSystemClassLoader()));
1398     }
1399 
1400     @Test
1401     public void testResourceToURL_Null() {
1402         assertThrows(NullPointerException.class, () -> IOUtils.resourceToURL(null));
1403     }
1404 
1405     @Test
1406     public void testResourceToURL_Null_WithClassLoader() {
1407         assertThrows(NullPointerException.class, () -> IOUtils.resourceToURL(null, ClassLoader.getSystemClassLoader()));
1408     }
1409 
1410     public void testSingleEOL(final String s1, final String s2, final boolean ifEquals) {
1411         assertEquals(ifEquals, IOUtils.contentEqualsIgnoreEOL(
1412                 new CharArrayReader(s1.toCharArray()),
1413                 new CharArrayReader(s2.toCharArray())
1414         ), "failed at :{" + s1 + "," + s2 + "}");
1415         assertEquals(ifEquals, IOUtils.contentEqualsIgnoreEOL(
1416                 new CharArrayReader(s2.toCharArray()),
1417                 new CharArrayReader(s1.toCharArray())
1418         ), "failed at :{" + s2 + "," + s1 + "}");
1419         assertTrue(IOUtils.contentEqualsIgnoreEOL(
1420                 new CharArrayReader(s1.toCharArray()),
1421                 new CharArrayReader(s1.toCharArray())
1422         ), "failed at :{" + s1 + "," + s1 + "}");
1423         assertTrue(IOUtils.contentEqualsIgnoreEOL(
1424                 new CharArrayReader(s2.toCharArray()),
1425                 new CharArrayReader(s2.toCharArray())
1426         ), "failed at :{" + s2 + "," + s2 + "}");
1427     }
1428 
1429     @Test
1430     public void testSkip_FileReader() throws Exception {
1431         try (Reader in = Files.newBufferedReader(testFilePath)) {
1432             assertEquals(FILE_SIZE - 10, IOUtils.skip(in, FILE_SIZE - 10));
1433             assertEquals(10, IOUtils.skip(in, 20));
1434             assertEquals(0, IOUtils.skip(in, 10));
1435         }
1436     }
1437 
1438     @Test
1439     public void testSkip_InputStream() throws Exception {
1440         try (InputStream in = Files.newInputStream(testFilePath)) {
1441             assertEquals(FILE_SIZE - 10, IOUtils.skip(in, FILE_SIZE - 10));
1442             assertEquals(10, IOUtils.skip(in, 20));
1443             assertEquals(0, IOUtils.skip(in, 10));
1444         }
1445     }
1446 
1447     @Test
1448     public void testSkip_ReadableByteChannel() throws Exception {
1449         final FileInputStream fileInputStream = new FileInputStream(testFile);
1450         final FileChannel fileChannel = fileInputStream.getChannel();
1451         try {
1452             assertEquals(FILE_SIZE - 10, IOUtils.skip(fileChannel, FILE_SIZE - 10));
1453             assertEquals(10, IOUtils.skip(fileChannel, 20));
1454             assertEquals(0, IOUtils.skip(fileChannel, 10));
1455         } finally {
1456             IOUtils.closeQuietly(fileChannel, fileInputStream);
1457         }
1458     }
1459 
1460     @Test
1461     public void testSkipFully_InputStream() throws Exception {
1462         final int size = 1027;
1463 
1464         try (InputStream input = new ByteArrayInputStream(new byte[size])) {
1465             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1), "Should have failed with IllegalArgumentException");
1466 
1467             IOUtils.skipFully(input, 0);
1468             IOUtils.skipFully(input, size - 1);
1469             assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2), "Should have failed with IOException");
1470         }
1471     }
1472 
1473     @Test
1474     public void testSkipFully_InputStream_Buffer_New_bytes() throws Exception {
1475         final int size = 1027;
1476         final Supplier<byte[]> bas = () -> new byte[size];
1477         try (InputStream input = new ByteArrayInputStream(new byte[size])) {
1478             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, bas), "Should have failed with IllegalArgumentException");
1479 
1480             IOUtils.skipFully(input, 0, bas);
1481             IOUtils.skipFully(input, size - 1, bas);
1482             assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, bas), "Should have failed with IOException");
1483         }
1484     }
1485 
1486     @Test
1487     public void testSkipFully_InputStream_Buffer_Reuse_bytes() throws Exception {
1488         final int size = 1027;
1489         final byte[] ba = new byte[size];
1490         final Supplier<byte[]> bas = () -> ba;
1491         try (InputStream input = new ByteArrayInputStream(new byte[size])) {
1492             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, bas), "Should have failed with IllegalArgumentException");
1493 
1494             IOUtils.skipFully(input, 0, bas);
1495             IOUtils.skipFully(input, size - 1, bas);
1496             assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, bas), "Should have failed with IOException");
1497         }
1498     }
1499 
1500     @Test
1501     public void testSkipFully_InputStream_Buffer_Reuse_ThreadLocal() throws Exception {
1502         final int size = 1027;
1503         final ThreadLocal<byte[]> tl = ThreadLocal.withInitial(() -> new byte[size]);
1504         try (InputStream input = new ByteArrayInputStream(new byte[size])) {
1505             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1, tl::get), "Should have failed with IllegalArgumentException");
1506 
1507             IOUtils.skipFully(input, 0, tl::get);
1508             IOUtils.skipFully(input, size - 1, tl::get);
1509             assertThrows(IOException.class, () -> IOUtils.skipFully(input, 2, tl::get), "Should have failed with IOException");
1510         }
1511     }
1512 
1513     @Test
1514     public void testSkipFully_ReadableByteChannel() throws Exception {
1515         final FileInputStream fileInputStream = new FileInputStream(testFile);
1516         final FileChannel fileChannel = fileInputStream.getChannel();
1517         try {
1518             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(fileChannel, -1), "Should have failed with IllegalArgumentException");
1519             IOUtils.skipFully(fileChannel, 0);
1520             IOUtils.skipFully(fileChannel, FILE_SIZE - 1);
1521             assertThrows(IOException.class, () -> IOUtils.skipFully(fileChannel, 2), "Should have failed with IOException");
1522         } finally {
1523             IOUtils.closeQuietly(fileChannel, fileInputStream);
1524         }
1525     }
1526 
1527     @Test
1528     public void testSkipFully_Reader() throws Exception {
1529         final int size = 1027;
1530         try (Reader input = new CharArrayReader(new char[size])) {
1531             IOUtils.skipFully(input, 0);
1532             IOUtils.skipFully(input, size - 3);
1533             assertThrows(IllegalArgumentException.class, () -> IOUtils.skipFully(input, -1), "Should have failed with IllegalArgumentException");
1534             assertThrows(IOException.class, () -> IOUtils.skipFully(input, 5), "Should have failed with IOException");
1535         }
1536     }
1537 
1538     @Test
1539     public void testStringToOutputStream() throws Exception {
1540         final File destination = TestUtils.newFile(temporaryFolder, "copy5.txt");
1541         final String str;
1542         try (Reader fin = Files.newBufferedReader(testFilePath)) {
1543             // Create our String. Rely on testReaderToString() to make sure this is valid.
1544             str = IOUtils.toString(fin);
1545         }
1546 
1547         try (OutputStream fout = Files.newOutputStream(destination.toPath())) {
1548             CopyUtils.copy(str, fout);
1549             // Note: this method *does* flush. It is equivalent to:
1550             // OutputStreamWriter _out = new OutputStreamWriter(fout);
1551             // CopyUtils.copy( str, _out, 4096 ); // copy( Reader, Writer, int );
1552             // _out.flush();
1553             // out = fout;
1554             // note: we don't flush here; this IOUtils method does it for us
1555 
1556             TestUtils.checkFile(destination, testFile);
1557             TestUtils.checkWrite(fout);
1558         }
1559         TestUtils.deleteFile(destination);
1560     }
1561 
1562     @Test
1563     public void testToBufferedInputStream_InputStream() throws Exception {
1564         try (InputStream fin = Files.newInputStream(testFilePath)) {
1565             final InputStream in = IOUtils.toBufferedInputStream(fin);
1566             final byte[] out = IOUtils.toByteArray(in);
1567             assertNotNull(out);
1568             assertEquals(0, fin.available(), "Not all bytes were read");
1569             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1570             TestUtils.assertEqualContent(out, testFile);
1571         }
1572     }
1573 
1574     @Test
1575     public void testToBufferedInputStreamWithBufferSize_InputStream() throws Exception {
1576         try (InputStream fin = Files.newInputStream(testFilePath)) {
1577             final InputStream in = IOUtils.toBufferedInputStream(fin, 2048);
1578             final byte[] out = IOUtils.toByteArray(in);
1579             assertNotNull(out);
1580             assertEquals(0, fin.available(), "Not all bytes were read");
1581             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1582             TestUtils.assertEqualContent(out, testFile);
1583         }
1584     }
1585 
1586     @Test
1587     public void testToByteArray_InputStream() throws Exception {
1588         try (InputStream fin = Files.newInputStream(testFilePath)) {
1589             final byte[] out = IOUtils.toByteArray(fin);
1590             assertNotNull(out);
1591             assertEquals(0, fin.available(), "Not all bytes were read");
1592             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1593             TestUtils.assertEqualContent(out, testFile);
1594         }
1595     }
1596 
1597     @Test
1598     @Disabled("Disable by default as it uses too much memory and can cause builds to fail.")
1599     public void testToByteArray_InputStream_LongerThanIntegerMaxValue() throws Exception {
1600         final CircularInputStream cin = new CircularInputStream(IOUtils.byteArray(), Integer.MAX_VALUE + 1L);
1601         assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(cin));
1602     }
1603 
1604     @Test
1605     public void testToByteArray_InputStream_NegativeSize() throws Exception {
1606         try (InputStream fin = Files.newInputStream(testFilePath)) {
1607             final IllegalArgumentException exc = assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(fin, -1),
1608                     "Should have failed with IllegalArgumentException");
1609             assertTrue(exc.getMessage().startsWith("Size must be equal or greater than zero"),
1610                     "Exception message does not start with \"Size must be equal or greater than zero\"");
1611         }
1612     }
1613 
1614     @Test
1615     public void testToByteArray_InputStream_Size() throws Exception {
1616         try (InputStream fin = Files.newInputStream(testFilePath)) {
1617             final byte[] out = IOUtils.toByteArray(fin, testFile.length());
1618             assertNotNull(out);
1619             assertEquals(0, fin.available(), "Not all bytes were read");
1620             assertEquals(FILE_SIZE, out.length, "Wrong output size: out.length=" + out.length + "!=" + FILE_SIZE);
1621             TestUtils.assertEqualContent(out, testFile);
1622         }
1623     }
1624 
1625     @Test
1626     public void testToByteArray_InputStream_SizeIllegal() throws Exception {
1627         try (InputStream fin = Files.newInputStream(testFilePath)) {
1628             final IOException exc = assertThrows(IOException.class, () -> IOUtils.toByteArray(fin, testFile.length() + 1),
1629                     "Should have failed with IOException");
1630             assertTrue(exc.getMessage().startsWith("Unexpected read size"), "Exception message does not start with \"Unexpected read size\"");
1631         }
1632     }
1633 
1634     @Test
1635     public void testToByteArray_InputStream_SizeLong() throws Exception {
1636         try (InputStream fin = Files.newInputStream(testFilePath)) {
1637             final IllegalArgumentException exc = assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(fin, (long) Integer.MAX_VALUE + 1),
1638                     "Should have failed with IllegalArgumentException");
1639             assertTrue(exc.getMessage().startsWith("Size cannot be greater than Integer max value"),
1640                     "Exception message does not start with \"Size cannot be greater than Integer max value\"");
1641         }
1642     }
1643 
1644     @Test
1645     public void testToByteArray_InputStream_SizeOne() throws Exception {
1646         try (InputStream fin = Files.newInputStream(testFilePath)) {
1647             final byte[] out = IOUtils.toByteArray(fin, 1);
1648             assertNotNull(out, "Out cannot be null");
1649             assertEquals(1, out.length, "Out length must be 1");
1650         }
1651     }
1652 
1653     @Test
1654     public void testToByteArray_InputStream_SizeZero() throws Exception {
1655         try (InputStream fin = Files.newInputStream(testFilePath)) {
1656             final byte[] out = IOUtils.toByteArray(fin, 0);
1657             assertNotNull(out, "Out cannot be null");
1658             assertEquals(0, out.length, "Out length must be 0");
1659         }
1660     }
1661 
1662     @Test
1663     public void testToByteArray_Reader() throws IOException {
1664         final String charsetName = UTF_8;
1665         final byte[] expected = charsetName.getBytes(charsetName);
1666         byte[] actual = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expected)));
1667         assertArrayEquals(expected, actual);
1668         actual = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expected)), charsetName);
1669         assertArrayEquals(expected, actual);
1670     }
1671 
1672     @Test
1673     public void testToByteArray_String() throws Exception {
1674         try (Reader fin = Files.newBufferedReader(testFilePath)) {
1675             // Create our String. Rely on testReaderToString() to make sure this is valid.
1676             final String str = IOUtils.toString(fin);
1677 
1678             final byte[] out = IOUtils.toByteArray(str);
1679             assertEqualContent(str.getBytes(), out);
1680         }
1681     }
1682 
1683     @Test
1684     public void testToByteArray_URI() throws Exception {
1685         final URI url = testFile.toURI();
1686         final byte[] actual = IOUtils.toByteArray(url);
1687         assertEquals(FILE_SIZE, actual.length);
1688     }
1689 
1690     @Test
1691     public void testToByteArray_URL() throws Exception {
1692         final URL url = testFile.toURI().toURL();
1693         final byte[] actual = IOUtils.toByteArray(url);
1694         assertEquals(FILE_SIZE, actual.length);
1695     }
1696 
1697     @Test
1698     public void testToByteArray_URLConnection() throws Exception {
1699         final byte[] actual;
1700         try (CloseableURLConnection urlConnection = CloseableURLConnection.open(testFile.toURI())) {
1701             actual = IOUtils.toByteArray(urlConnection);
1702         }
1703         assertEquals(FILE_SIZE, actual.length);
1704     }
1705 
1706     @Test
1707     public void testToCharArray_InputStream() throws Exception {
1708         try (InputStream fin = Files.newInputStream(testFilePath)) {
1709             final char[] out = IOUtils.toCharArray(fin);
1710             assertNotNull(out);
1711             assertEquals(0, fin.available(), "Not all chars were read");
1712             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1713             TestUtils.assertEqualContent(out, testFile);
1714         }
1715     }
1716 
1717     @Test
1718     public void testToCharArray_InputStream_CharsetName() throws Exception {
1719         try (InputStream fin = Files.newInputStream(testFilePath)) {
1720             final char[] out = IOUtils.toCharArray(fin, UTF_8);
1721             assertNotNull(out);
1722             assertEquals(0, fin.available(), "Not all chars were read");
1723             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1724             TestUtils.assertEqualContent(out, testFile);
1725         }
1726     }
1727 
1728     @Test
1729     public void testToCharArray_Reader() throws Exception {
1730         try (Reader fr = Files.newBufferedReader(testFilePath)) {
1731             final char[] out = IOUtils.toCharArray(fr);
1732             assertNotNull(out);
1733             assertEquals(FILE_SIZE, out.length, "Wrong output size");
1734             TestUtils.assertEqualContent(out, testFile);
1735         }
1736     }
1737 
1738     /**
1739      * Test for {@link IOUtils#toInputStream(CharSequence)} and {@link IOUtils#toInputStream(CharSequence, String)}.
1740      * Note, this test utilizes on {@link IOUtils#toByteArray(InputStream)} and so relies on
1741      * {@link #testToByteArray_InputStream()} to ensure this method functions correctly.
1742      *
1743      * @throws Exception on error
1744      */
1745     @Test
1746     public void testToInputStream_CharSequence() throws Exception {
1747         final CharSequence csq = new StringBuilder("Abc123Xyz!");
1748         InputStream inStream = IOUtils.toInputStream(csq); // deliberately testing deprecated method
1749         byte[] bytes = IOUtils.toByteArray(inStream);
1750         assertEqualContent(csq.toString().getBytes(), bytes);
1751         inStream = IOUtils.toInputStream(csq, (String) null);
1752         bytes = IOUtils.toByteArray(inStream);
1753         assertEqualContent(csq.toString().getBytes(), bytes);
1754         inStream = IOUtils.toInputStream(csq, UTF_8);
1755         bytes = IOUtils.toByteArray(inStream);
1756         assertEqualContent(csq.toString().getBytes(StandardCharsets.UTF_8), bytes);
1757     }
1758 
1759     /**
1760      * Test for {@link IOUtils#toInputStream(String)} and {@link IOUtils#toInputStream(String, String)}. Note, this test
1761      * utilizes on {@link IOUtils#toByteArray(InputStream)} and so relies on
1762      * {@link #testToByteArray_InputStream()} to ensure this method functions correctly.
1763      *
1764      * @throws Exception on error
1765      */
1766     @Test
1767     public void testToInputStream_String() throws Exception {
1768         final String str = "Abc123Xyz!";
1769         InputStream inStream = IOUtils.toInputStream(str);
1770         byte[] bytes = IOUtils.toByteArray(inStream);
1771         assertEqualContent(str.getBytes(), bytes);
1772         inStream = IOUtils.toInputStream(str, (String) null);
1773         bytes = IOUtils.toByteArray(inStream);
1774         assertEqualContent(str.getBytes(), bytes);
1775         inStream = IOUtils.toInputStream(str, UTF_8);
1776         bytes = IOUtils.toByteArray(inStream);
1777         assertEqualContent(str.getBytes(StandardCharsets.UTF_8), bytes);
1778     }
1779 
1780     @Test
1781     public void testToString_ByteArray() throws Exception {
1782         try (InputStream fin = Files.newInputStream(testFilePath)) {
1783             final byte[] in = IOUtils.toByteArray(fin);
1784             // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid.
1785             final String str = IOUtils.toString(in);
1786             assertEqualContent(in, str.getBytes());
1787         }
1788     }
1789 
1790     @Test
1791     public void testToString_InputStream() throws Exception {
1792         try (InputStream fin = Files.newInputStream(testFilePath)) {
1793             final String out = IOUtils.toString(fin);
1794             assertNotNull(out);
1795             assertEquals(0, fin.available(), "Not all bytes were read");
1796             assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1797         }
1798     }
1799 
1800     @Test
1801     public void testToString_InputStreamSupplier() throws Exception {
1802         final String out = IOUtils.toString(() -> Files.newInputStream(testFilePath), Charset.defaultCharset());
1803         assertNotNull(out);
1804         assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1805         assertNull(IOUtils.toString(null, Charset.defaultCharset(), () -> null));
1806         assertNull(IOUtils.toString(() -> null, Charset.defaultCharset(), () -> null));
1807         assertEquals("A", IOUtils.toString(null, Charset.defaultCharset(), () -> "A"));
1808     }
1809 
1810     @Test
1811     public void testToString_Reader() throws Exception {
1812         try (Reader fin = Files.newBufferedReader(testFilePath)) {
1813             final String out = IOUtils.toString(fin);
1814             assertNotNull(out);
1815             assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1816         }
1817     }
1818 
1819     @Test
1820     public void testToString_URI() throws Exception {
1821         final URI url = testFile.toURI();
1822         final String out = IOUtils.toString(url);
1823         assertNotNull(out);
1824         assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1825     }
1826 
1827     private void testToString_URI(final String encoding) throws Exception {
1828         final URI uri = testFile.toURI();
1829         final String out = IOUtils.toString(uri, encoding);
1830         assertNotNull(out);
1831         assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1832     }
1833 
1834     @Test
1835     public void testToString_URI_CharsetName() throws Exception {
1836         testToString_URI(StandardCharsets.US_ASCII.name());
1837     }
1838 
1839     @Test
1840     public void testToString_URI_CharsetNameNull() throws Exception {
1841         testToString_URI(null);
1842     }
1843 
1844     @Test
1845     public void testToString_URL() throws Exception {
1846         final URL url = testFile.toURI().toURL();
1847         final String out = IOUtils.toString(url);
1848         assertNotNull(out);
1849         assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1850     }
1851 
1852     private void testToString_URL(final String encoding) throws Exception {
1853         final URL url = testFile.toURI().toURL();
1854         final String out = IOUtils.toString(url, encoding);
1855         assertNotNull(out);
1856         assertEquals(FILE_SIZE, out.length(), "Wrong output size");
1857     }
1858 
1859     @Test
1860     public void testToString_URL_CharsetName() throws Exception {
1861         testToString_URL(StandardCharsets.US_ASCII.name());
1862     }
1863 
1864     @Test
1865     public void testToString_URL_CharsetNameNull() throws Exception {
1866         testToString_URL(null);
1867     }
1868 
1869     /**
1870      * IO-764 IOUtils.write() throws NegativeArraySizeException while writing big strings.
1871      * <pre>
1872      * java.lang.OutOfMemoryError: Java heap space
1873      *     at java.lang.StringCoding.encode(StringCoding.java:350)
1874      *     at java.lang.String.getBytes(String.java:941)
1875      *     at org.apache.commons.io.IOUtils.write(IOUtils.java:3367)
1876      *     at org.apache.commons.io.IOUtilsTest.testBigString(IOUtilsTest.java:1659)
1877      * </pre>
1878      */
1879     @Test
1880     public void testWriteBigString() throws IOException {
1881         // 3_000_000 is a size that we can allocate for the test string with Java 8 on the command line as:
1882         // mvn clean test -Dtest=IOUtilsTest -DtestBigString=3000000
1883         // 6_000_000 failed with the above
1884         //
1885         // TODO Can we mock the test string for this test to pretend to be larger?
1886         // Mocking the length seems simple but how about the data?
1887         final int repeat = Integer.getInteger("testBigString", 3_000_000);
1888         final String data;
1889         try {
1890             data = StringUtils.repeat("\uD83D", repeat);
1891         } catch (final OutOfMemoryError e) {
1892             System.err.printf("Don't fail the test if we cannot build the fixture, just log, fixture size = %,d%n.", repeat);
1893             e.printStackTrace();
1894             return;
1895         }
1896         try (CountingOutputStream os = new CountingOutputStream(NullOutputStream.INSTANCE)) {
1897             IOUtils.write(data, os, StandardCharsets.UTF_8);
1898             assertEquals(repeat, os.getByteCount());
1899         }
1900     }
1901 
1902     @Test
1903     public void testWriteLines() throws IOException {
1904         final String[] data = {"The", "quick"};
1905         final ByteArrayOutputStream out = new ByteArrayOutputStream();
1906         IOUtils.writeLines(Arrays.asList(data), "\n", out, StandardCharsets.UTF_16.name());
1907         final String result = new String(out.toByteArray(), StandardCharsets.UTF_16);
1908         assertEquals("The\nquick\n", result);
1909     }
1910 
1911     @Test
1912     public void testWriteLittleString() throws IOException {
1913         final String data = "\uD83D";
1914         // White-box test to check that not closing the internal channel is not a problem.
1915         for (int i = 0; i < 1_000_000; i++) {
1916             try (CountingOutputStream os = new CountingOutputStream(NullOutputStream.INSTANCE)) {
1917                 IOUtils.write(data, os, StandardCharsets.UTF_8);
1918                 assertEquals(data.length(), os.getByteCount());
1919             }
1920         }
1921     }
1922 
1923 }