Skip to content

Commit 40b9af5

Browse files
author
Gary Gregory
committed
Add IOUtils.copy(URL, File) and copy(URL, OutputStream).
1 parent 1d39856 commit 40b9af5

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

src/changes/changes.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ The <action> type attribute can be add,update,fix,remove.
175175
<action dev="ggregory" type="add" due-to="Gary Gregory">
176176
Make public and reuse IOUtils.EMPTY_BYTE_ARRAY.
177177
</action>
178+
<action dev="ggregory" type="add" due-to="Gary Gregory">
179+
Add IOUtils.copy(URL, File).
180+
</action>
181+
<action dev="ggregory" type="add" due-to="Gary Gregory">
182+
Add copy(URL, OutputStream).
183+
</action>
178184
<!-- UPDATES -->
179185
<action dev="ggregory" type="update" due-to="Dependabot">
180186
Update junit-jupiter from 5.6.2 to 5.7.0 #153.

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.io.Closeable;
2626
import java.io.EOFException;
2727
import java.io.File;
28+
import java.io.FileOutputStream;
2829
import java.io.IOException;
2930
import java.io.InputStream;
3031
import java.io.InputStreamReader;
@@ -1190,6 +1191,52 @@ public static int copy(final Reader reader, final Writer writer) throws IOExcept
11901191
return (int) count;
11911192
}
11921193

1194+
/**
1195+
* Copies bytes from a {@code URL} to an {@code OutputStream}.
1196+
* <p>
1197+
* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}.
1198+
* </p>
1199+
* <p>
1200+
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1201+
* </p>
1202+
*
1203+
* @param url the {@code URL} to read.
1204+
* @param file the {@code OutputStream} to write.
1205+
* @return the number of bytes copied.
1206+
* @throws NullPointerException if the URL is {@code null}.
1207+
* @throws NullPointerException if the OutputStream is {@code null}.
1208+
* @throws IOException if an I/O error occurs.
1209+
* @since 2.9.0
1210+
*/
1211+
public static long copy(final URL url, final File file) throws IOException {
1212+
try (FileOutputStream outputStream = new FileOutputStream(Objects.requireNonNull(file, "file"))) {
1213+
return copy(url, outputStream);
1214+
}
1215+
}
1216+
1217+
/**
1218+
* Copies bytes from a {@code URL} to an {@code OutputStream}.
1219+
* <p>
1220+
* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}.
1221+
* </p>
1222+
* <p>
1223+
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1224+
* </p>
1225+
*
1226+
* @param url the {@code URL} to read.
1227+
* @param outputStream the {@code OutputStream} to write.
1228+
* @return the number of bytes copied.
1229+
* @throws NullPointerException if the URL is {@code null}.
1230+
* @throws NullPointerException if the OutputStream is {@code null}.
1231+
* @throws IOException if an I/O error occurs.
1232+
* @since 2.9.0
1233+
*/
1234+
public static long copy(final URL url, final OutputStream outputStream) throws IOException {
1235+
try (InputStream inputStream = Objects.requireNonNull(url, "url").openStream()) {
1236+
return copyLarge(inputStream, outputStream);
1237+
}
1238+
}
1239+
11931240
/**
11941241
* Copies bytes from a large (over 2GB) {@code InputStream} to an
11951242
* {@code OutputStream}.

src/test/java/org/apache/commons/io/IOUtilsCopyTestCase.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
*/
1717
package org.apache.commons.io;
1818

19+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
1920
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertNotNull;
2022
import static org.junit.jupiter.api.Assertions.assertThrows;
2123
import static org.junit.jupiter.api.Assertions.assertTrue;
2224

@@ -27,7 +29,11 @@
2729
import java.io.OutputStreamWriter;
2830
import java.io.Reader;
2931
import java.io.Writer;
32+
import java.net.URL;
3033
import java.nio.charset.StandardCharsets;
34+
import java.nio.file.Files;
35+
import java.nio.file.Path;
36+
import java.nio.file.Paths;
3137
import java.util.Arrays;
3238

3339
import org.apache.commons.io.input.NullInputStream;
@@ -431,4 +437,32 @@ public void testCopy_readerToWriter_nullOut() {
431437
assertThrows(NullPointerException.class, () -> IOUtils.copy(reader, (Writer) null));
432438
}
433439

440+
@Test
441+
public void testCopy_URLToFile() throws Exception {
442+
final String name = "/org/apache/commons/io/abitmorethan16k.txt";
443+
URL in = getClass().getResource(name);
444+
assertNotNull(in, name);
445+
446+
Path path = Files.createTempFile("testCopy_URLToFile", ".txt");
447+
try {
448+
IOUtils.copy(in, path.toFile());
449+
450+
assertArrayEquals(Files.readAllBytes(Paths.get("src/test/resources" + name)), Files.readAllBytes(path));
451+
} finally {
452+
Files.delete(path);
453+
}
454+
}
455+
456+
@Test
457+
public void testCopy_URLToOutputStream() throws Exception {
458+
final String name = "/org/apache/commons/io/abitmorethan16k.txt";
459+
URL in = getClass().getResource(name);
460+
assertNotNull(in, name);
461+
462+
final ByteArrayOutputStream baout = new ByteArrayOutputStream();
463+
IOUtils.copy(in, baout);
464+
465+
assertArrayEquals(Files.readAllBytes(Paths.get("src/test/resources" + name)), baout.toByteArray());
466+
}
467+
434468
}

0 commit comments

Comments
 (0)