Skip to content

Commit c6b8a38

Browse files
committed
[IO-554] FileUtils.copyToFile(InputStream source, File destination)
should not close input stream. Closes #49.
1 parent 4597f38 commit c6b8a38

2 files changed

Lines changed: 104 additions & 3 deletions

File tree

src/main/java/org/apache/commons/io/FileUtils.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,9 +1535,8 @@ public static void copyInputStreamToFile(final InputStream source, final File de
15351535
* @since 2.5
15361536
*/
15371537
public static void copyToFile(final InputStream source, final File destination) throws IOException {
1538-
try (InputStream in = source;
1539-
OutputStream out = openOutputStream(destination)) {
1540-
IOUtils.copy(in, out);
1538+
try (OutputStream out = openOutputStream(destination)) {
1539+
IOUtils.copy(source, out);
15411540
}
15421541
}
15431542

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* Licensed to the Apache Software Foundation (ASF) under one or more
2+
* contributor license agreements. See the NOTICE file distributed with
3+
* this work for additional information regarding copyright ownership.
4+
* The ASF licenses this file to You under the Apache License, Version 2.0
5+
* (the "License"); you may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License. */
13+
package org.apache.commons.io;
14+
15+
import java.io.ByteArrayInputStream;
16+
import java.io.File;
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import org.apache.commons.io.testtools.TestUtils;
20+
import org.junit.Assert;
21+
import org.junit.Before;
22+
import org.junit.Rule;
23+
import org.junit.Test;
24+
import org.junit.rules.TemporaryFolder;
25+
26+
27+
/**
28+
* This is used to test FileUtils for correctness.
29+
*/
30+
public class FileUtilsCopyToFileTestCase {
31+
32+
@Rule
33+
public TemporaryFolder temporaryFolder = new TemporaryFolder();
34+
35+
private File getTestDirectory() {
36+
return temporaryFolder.getRoot();
37+
}
38+
39+
private File testFile;
40+
41+
private byte[] testData;
42+
43+
@Before
44+
public void setUp() throws Exception {
45+
testFile = new File(getTestDirectory(), "file1-test.txt");
46+
if(!testFile.getParentFile().exists()) {
47+
throw new IOException("Cannot create file " + testFile +
48+
" as the parent directory does not exist");
49+
}
50+
51+
testData = TestUtils.generateTestData(1024);
52+
}
53+
54+
/**
55+
* Tests that <code>copyToFile(InputStream, File)</code> does not close the input stream.
56+
*
57+
* @throws IOException
58+
* @see FileUtils#copyToFile(InputStream, File)
59+
* @see FileUtils#copyInputStreamToFile(InputStream, File)
60+
*/
61+
@Test
62+
public void testCopyToFile() throws IOException {
63+
try(CheckingInputStream inputStream = new CheckingInputStream(testData)) {
64+
FileUtils.copyToFile(inputStream, testFile);
65+
Assert.assertFalse("inputStream should NOT be closed", inputStream.isClosed());
66+
}
67+
}
68+
69+
/**
70+
* Tests that <code>copyInputStreamToFile(InputStream, File)</code> closes the input stream.
71+
*
72+
* @throws IOException
73+
* @see FileUtils#copyInputStreamToFile(InputStream, File)
74+
* @see FileUtils#copyToFile(InputStream, File)
75+
*/
76+
@Test
77+
public void testCopyInputStreamToFile() throws IOException {
78+
try(CheckingInputStream inputStream = new CheckingInputStream(testData)) {
79+
FileUtils.copyInputStreamToFile(inputStream, testFile);
80+
Assert.assertTrue("inputStream should be closed", inputStream.isClosed());
81+
}
82+
}
83+
84+
private class CheckingInputStream extends ByteArrayInputStream {
85+
private boolean closed;
86+
87+
public CheckingInputStream(byte[] data) {
88+
super(data);
89+
closed = false;
90+
}
91+
92+
@Override
93+
public void close() throws IOException {
94+
super.close();
95+
closed = true;
96+
}
97+
98+
public boolean isClosed() {
99+
return closed;
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)