Skip to content

Commit 4147a50

Browse files
author
Niall Pemberton
committed
IO-84 Modify copy() methods that return an int to throw an ArithmeticException if the returned size is too large for an int to handle. Add two new equivalent copyLarge() methods that return a long for large files.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@463154 13f79535-47bb-0310-9956-ffa450edef68
1 parent 46c56e6 commit 4147a50

2 files changed

Lines changed: 62 additions & 8 deletions

File tree

RELEASE-NOTES.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,12 @@ Bug fixes from 1.2
6060
- This now handles the situation where an error occurs when deleting the file
6161

6262
- IOUtils.copy [IO-84]
63-
- Comment about result byte/char count being limited to an int, thus
64-
being inacurate for large streams
63+
- The copy(InputStream, OutputStream) method now throws an exception if
64+
the count is greater than an int
65+
- The copy(Reader, Writer) method now throws an exception if
66+
the count is greater than an int
67+
- Added a new copyLarge(InputStream, OutputStream) method that returns a long
68+
- Added a new copyLarge(Reader, Writer) method that returns a long
6569

6670
- CountingInputStream/CountingOutputStream [IO-84]
6771
- methods were declared as int thus the count was innacurate for large streams

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

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -982,20 +982,46 @@ public static void writeLines(Collection lines, String lineEnding,
982982
* This method buffers the input internally, so there is no need to use a
983983
* <code>BufferedInputStream</code>.
984984
* <p>
985-
* Large streams (over 2GB) will return an inaccurate result count as the
986-
* type is an int. The copy will complete correctly however.
985+
* Large streams (over 2GB) will throw an {@link ArithmeticException}
986+
* after the copy has completed since the correct number of bytes
987+
* cannot be returned as an int. For large streams use the
988+
* <code>copyLarge(InputStream, OutputStream)</code> method.
987989
*
988990
* @param input the <code>InputStream</code> to read from
989991
* @param output the <code>OutputStream</code> to write to
990992
* @return the number of bytes copied
991993
* @throws NullPointerException if the input or output is null
992994
* @throws IOException if an I/O error occurs
995+
* @throws ArithmeticException if the byte count is too large
993996
* @since Commons IO 1.1
994997
*/
995998
public static int copy(InputStream input, OutputStream output)
996999
throws IOException {
1000+
long count = copyLarge(input, output);
1001+
if (count > Integer.MAX_VALUE) {
1002+
throw new ArithmeticException("The byte count " + count + " is too large to be converted to an int");
1003+
}
1004+
return (int)count;
1005+
}
1006+
1007+
/**
1008+
* Copy bytes from a large (over 2GB) <code>InputStream</code> to an
1009+
* <code>OutputStream</code>.
1010+
* <p>
1011+
* This method buffers the input internally, so there is no need to use a
1012+
* <code>BufferedInputStream</code>.
1013+
*
1014+
* @param input the <code>InputStream</code> to read from
1015+
* @param output the <code>OutputStream</code> to write to
1016+
* @return the number of bytes copied
1017+
* @throws NullPointerException if the input or output is null
1018+
* @throws IOException if an I/O error occurs
1019+
* @since Commons IO 1.3
1020+
*/
1021+
public static long copyLarge(InputStream input, OutputStream output)
1022+
throws IOException {
9971023
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
998-
int count = 0;
1024+
long count = 0;
9991025
int n = 0;
10001026
while (-1 != (n = input.read(buffer))) {
10011027
output.write(buffer, 0, n);
@@ -1062,19 +1088,43 @@ public static void copy(InputStream input, Writer output, String encoding)
10621088
* This method buffers the input internally, so there is no need to use a
10631089
* <code>BufferedReader</code>.
10641090
* <p>
1065-
* Large streams (over 2GB) will return an inaccurate result count as the
1066-
* type is an int. The copy will complete correctly however.
1091+
* Large streams (over 2GB) will throw an {@link ArithmeticException}
1092+
* after the copy has completed since the correct number of characters
1093+
* cannot be returned as an int. For large streams use the
1094+
* <code>copyLarge(Reader, Writer)</code> method.
10671095
*
10681096
* @param input the <code>Reader</code> to read from
10691097
* @param output the <code>Writer</code> to write to
10701098
* @return the number of characters copied
10711099
* @throws NullPointerException if the input or output is null
10721100
* @throws IOException if an I/O error occurs
1101+
* @throws ArithmeticException if the character count is too large
10731102
* @since Commons IO 1.1
10741103
*/
10751104
public static int copy(Reader input, Writer output) throws IOException {
1105+
long count = copyLarge(input, output);
1106+
if (count > Integer.MAX_VALUE) {
1107+
throw new ArithmeticException("The character count " + count + " is too large to be converted to an int");
1108+
}
1109+
return (int)count;
1110+
}
1111+
1112+
/**
1113+
* Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
1114+
* <p>
1115+
* This method buffers the input internally, so there is no need to use a
1116+
* <code>BufferedReader</code>.
1117+
*
1118+
* @param input the <code>Reader</code> to read from
1119+
* @param output the <code>Writer</code> to write to
1120+
* @return the number of characters copied
1121+
* @throws NullPointerException if the input or output is null
1122+
* @throws IOException if an I/O error occurs
1123+
* @since Commons IO 1.3
1124+
*/
1125+
public static long copyLarge(Reader input, Writer output) throws IOException {
10761126
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
1077-
int count = 0;
1127+
long count = 0;
10781128
int n = 0;
10791129
while (-1 != (n = input.read(buffer))) {
10801130
output.write(buffer, 0, n);

0 commit comments

Comments
 (0)