Skip to content

Commit 26acd21

Browse files
committed
IO-251 Add new read method "toByteArray" to handle InputStream with known size.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1090783 13f79535-47bb-0310-9956-ffa450edef68
1 parent cea203a commit 26acd21

4 files changed

Lines changed: 144 additions & 2 deletions

File tree

src/changes/changes.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,15 @@ The <action> type attribute can be add,update,fix,remove.
4040

4141
<body>
4242
<release version="1.4" date="Not yet released">
43+
44+
<action dev="sebb" type="add" issue="IO-251" due-to="Marco Albini">
45+
Add new read method "toByteArray" to handle InputStream with known size.
46+
</action>
4347
<action dev="sebb" type="fix" issue="IO-263" due-to="Gil Adam">
4448
FileSystemUtils.freeSpaceKb throws exception for Windows volumes with no visible files.
4549
Improve coverage by also looking for hidden files.
4650
</action>
51+
4752
</release>
4853

4954
<release version="1.3.2" date="2007-Jul-02">

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,7 @@ public static byte[] readFileToByteArray(File file) throws IOException {
14281428
InputStream in = null;
14291429
try {
14301430
in = openInputStream(file);
1431-
return IOUtils.toByteArray(in);
1431+
return IOUtils.toByteArray(in, file.length());
14321432
} finally {
14331433
IOUtils.closeQuietly(in);
14341434
}

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

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public class IOUtils {
133133
// Allocated in the skip method if necessary.
134134
private static char[] SKIP_CHAR_BUFFER;
135135
private static byte[] SKIP_BYTE_BUFFER;
136-
136+
137137
/**
138138
* Instances should NOT be constructed in standard programming.
139139
*/
@@ -360,6 +360,67 @@ public static byte[] toByteArray(InputStream input) throws IOException {
360360
return output.toByteArray();
361361
}
362362

363+
/**
364+
* Get contents of an <code>InputStream</code> as a <code>byte[]</code>.
365+
* Use this method instead of <code>toByteArray(InputStream)</code>
366+
* when <code>InputStream</code> size is known.
367+
* <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
368+
* before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array.
369+
* (Arrays can have no more than Integer.MAX_VALUE entries anyway)
370+
*
371+
* @param input the <code>InputStream</code> to read from
372+
* @param size the size of <code>InputStream</code>
373+
* @return the requested byte array
374+
* @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
375+
* @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
376+
* @see IOUtils#toByteArray(java.io.InputStream, int)
377+
* @since Commons IO 2.1
378+
*/
379+
public static byte[] toByteArray(InputStream input, long size) throws IOException {
380+
381+
if(size > Integer.MAX_VALUE) {
382+
throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
383+
}
384+
385+
return toByteArray(input, (int) size);
386+
}
387+
388+
/**
389+
* Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
390+
* Use this method instead of <code>toByteArray(InputStream)</code>
391+
* when <code>InputStream</code> size is known
392+
* @param input the <code>InputStream</code> to read from
393+
* @param size the size of <code>InputStream</code>
394+
* @return the requested byte array
395+
* @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
396+
* @throws IllegalArgumentException if size is less than zero
397+
* @since Commons IO 2.1
398+
*/
399+
public static byte[] toByteArray(InputStream input, int size) throws IOException {
400+
401+
if(size < 0) {
402+
throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
403+
}
404+
405+
if(size == 0) {
406+
return new byte[0];
407+
}
408+
409+
byte[] data = new byte[size];
410+
int offset = 0;
411+
int readed;
412+
413+
while(offset < size && (readed = input.read(data, offset, (size - offset))) != -1) {
414+
offset += readed;
415+
}
416+
417+
if(offset != size) {
418+
throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
419+
}
420+
421+
return data;
422+
}
423+
363424
/**
364425
* Get the contents of a <code>Reader</code> as a <code>byte[]</code>
365426
* using the default character encoding of the platform.

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,82 @@ public void testInputStreamToByteArray()
223223
}
224224
}
225225

226+
public void testInputStreamToByteArray_Size()
227+
throws Exception {
228+
FileInputStream fin = new FileInputStream( m_testFile );
229+
try {
230+
byte[] out = IOUtils.toByteArray( fin, m_testFile.length());
231+
assertNotNull( out );
232+
assertTrue( "Not all bytes were read", fin.available() == 0 );
233+
assertTrue( "Wrong output size: out.length=" + out.length +
234+
"!=" + FILE_SIZE, out.length == FILE_SIZE );
235+
assertEqualContent( out, m_testFile );
236+
} finally {
237+
fin.close();
238+
}
239+
}
240+
241+
public void testInputStreamToByteArray_NegativeSize()
242+
throws Exception {
243+
FileInputStream fin = new FileInputStream( m_testFile );
244+
245+
try {
246+
IOUtils.toByteArray( fin, -1);
247+
fail("IllegalArgumentException excepted");
248+
} catch (IllegalArgumentException exc) {
249+
assertTrue("Exception message does not start with \"Size must be equal or greater than zero\"",
250+
exc.getMessage().startsWith("Size must be equal or greater than zero"));
251+
} finally {
252+
fin.close();
253+
}
254+
255+
}
256+
257+
public void testInputStreamToByteArray_ZeroSize()
258+
throws Exception {
259+
FileInputStream fin = new FileInputStream( m_testFile );
260+
261+
try {
262+
byte[] out = IOUtils.toByteArray( fin, 0);
263+
assertNotNull("Out cannot be null", out);
264+
assertTrue("Out length must be 0", out.length == 0);
265+
} finally {
266+
fin.close();
267+
}
268+
}
269+
270+
public void testInputStreamToByteArray_IllegalSize()
271+
throws Exception {
272+
FileInputStream fin = new FileInputStream( m_testFile );
273+
274+
try {
275+
IOUtils.toByteArray( fin, m_testFile.length() + 1);
276+
fail("IOException excepted");
277+
} catch (IOException exc) {
278+
assertTrue("Exception message does not start with \"Unexpected readed size\"",
279+
exc.getMessage().startsWith("Unexpected readed size"));
280+
} finally {
281+
fin.close();
282+
}
283+
284+
}
285+
286+
public void testInputStreamToByteArray_LongSize()
287+
throws Exception {
288+
FileInputStream fin = new FileInputStream( m_testFile );
289+
290+
try {
291+
IOUtils.toByteArray( fin, (long) Integer.MAX_VALUE + 1);
292+
fail("IOException excepted");
293+
} catch (IllegalArgumentException exc) {
294+
assertTrue("Exception message does not start with \"Size cannot be greater than Integer max value\"",
295+
exc.getMessage().startsWith("Size cannot be greater than Integer max value"));
296+
} finally {
297+
fin.close();
298+
}
299+
300+
}
301+
226302
public void testInputStreamToBufferedInputStream() throws Exception {
227303
FileInputStream fin = new FileInputStream(m_testFile);
228304
try {

0 commit comments

Comments
 (0)