Author: sebb
Date: Sat Mar 17 01:21:11 2012
New Revision: 1301851
URL: http://svn.apache.org/viewvc?rev=1301851&view=rev
Log:
IO-305: New copyLarge() method in IOUtils that takes additional offset, length
arguments
Modified:
commons/proper/io/trunk/RELEASE-NOTES.txt
commons/proper/io/trunk/src/changes/changes.xml
commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java
commons/proper/io/trunk/src/test/java/org/apache/commons/io/IOUtilsTestCase.java
Modified: commons/proper/io/trunk/RELEASE-NOTES.txt
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/RELEASE-NOTES.txt?rev=1301851&r1=1301850&r2=1301851&view=diff
==============================================================================
--- commons/proper/io/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/io/trunk/RELEASE-NOTES.txt Sat Mar 17 01:21:11 2012
@@ -24,6 +24,7 @@ $release.description.replaceAll(" ", "
Changes in this version include:
New features:
+o IO-305: New copyLarge() method in IOUtils that takes additional offset,
length arguments Thanks to Manoj Mokashi.
o IO-287: Use terabyte (TB) , petabyte (PB) and exabyte (EB) in
FileUtils.byteCountToDisplaySize(long size) Thanks to Ron Kuris, Gary Gregory.
o IO-173: FileUtils.listFiles() doesn't return directories Thanks to Marcos
VinÃcius da Silva.
o IO-297: CharSequenceInputStream to efficiently stream content of a
CharSequence Thanks to Oleg Kalnichevski.
Modified: commons/proper/io/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1301851&r1=1301850&r2=1301851&view=diff
==============================================================================
--- commons/proper/io/trunk/src/changes/changes.xml (original)
+++ commons/proper/io/trunk/src/changes/changes.xml Sat Mar 17 01:21:11 2012
@@ -40,6 +40,9 @@ The <action> type attribute can be add,u
<body>
<release version="2.2" date="TBA">
+ <action issue="IO-305" dev="sebb" type="add" due-to="Manoj Mokashi">
+ New copyLarge() method in IOUtils that takes additional offset, length
arguments
+ </action>
<action issue="IO-300" dev="sebb" type="fix">
FileUtils.moveDirectoryToDirectory removes source directory if
destination is a subdirectory
</action>
Modified:
commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java?rev=1301851&r1=1301850&r2=1301851&view=diff
==============================================================================
--- commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java
(original)
+++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java
Sat Mar 17 01:21:11 2012
@@ -1458,6 +1458,51 @@ public class IOUtils {
}
/**
+ * Copy some or all bytes from a large (over 2GB) <code>InputStream</code>
to an
+ * <code>OutputStream</code>, optionally skipping input bytes.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @param offset : number of bytes to skip from input before copying
+ * -ve values are ignored
+ * @param length : number of bytes to copy. -ve means all
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 2.2
+ */
+ public static long copyLarge(InputStream input, OutputStream output, final
long offset, final long length)
+ throws IOException {
+ if( offset > 0){
+ skipFully( input, offset);
+ }
+ if (length == 0) {
+ return 0;
+ }
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ int bytesToRead = buffer.length;
+ if (length > 0 && length < buffer.length) {
+ bytesToRead = (int) length;
+ }
+ int read;
+ long totalRead = 0;
+ while(bytesToRead > 0 && -1 != (read=input.read(buffer, 0,
bytesToRead))) {
+ output.write( buffer, 0, read);
+ totalRead += read;
+ if (length > 0) { // only adjust length if not reading to the end
+ // Note the cast must work because buffer.length is an integer
+ bytesToRead = (int) Math.min(length - totalRead,
buffer.length);
+ }
+ }
+ return totalRead;
+ }
+
+ /**
* Copy bytes from an <code>InputStream</code> to chars on a
* <code>Writer</code> using the default character encoding of the
platform.
* <p>
@@ -1562,6 +1607,51 @@ public class IOUtils {
}
/**
+ * Copy some or all chars from a large (over 2GB) <code>InputStream</code>
to an
+ * <code>OutputStream</code>, optionally skipping input chars.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedReader</code>.
+ * <p>
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ *
+ * @param input the <code>Reader</code> to read from
+ * @param output the <code>Writer</code> to write to
+ * @param offset : number of chars to skip from input before copying
+ * -ve values are ignored
+ * @param length : number of chars to copy. -ve means all
+ * @return the number of chars copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 2.2
+ */
+ public static long copyLarge(Reader input, Writer output, final long
offset, final long length)
+ throws IOException {
+ if( offset > 0){
+ skipFully( input, offset);
+ }
+ if (length == 0) {
+ return 0;
+ }
+ char[] buffer = new char[DEFAULT_BUFFER_SIZE];
+ int bytesToRead = buffer.length;
+ if (length > 0 && length < buffer.length) {
+ bytesToRead = (int) length;
+ }
+ int read;
+ long totalRead = 0;
+ while(bytesToRead > 0 && -1 != (read=input.read(buffer, 0,
bytesToRead))) {
+ output.write( buffer, 0, read);
+ totalRead += read;
+ if (length > 0) { // only adjust length if not reading to the end
+ // Note the cast must work because buffer.length is an integer
+ bytesToRead = (int) Math.min(length - totalRead,
buffer.length);
+ }
+ }
+ return totalRead;
+ }
+
+ /**
* Copy chars from a <code>Reader</code> to bytes on an
* <code>OutputStream</code> using the default character encoding of the
* platform, and calling flush.
Modified:
commons/proper/io/trunk/src/test/java/org/apache/commons/io/IOUtilsTestCase.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/IOUtilsTestCase.java?rev=1301851&r1=1301850&r2=1301851&view=diff
==============================================================================
---
commons/proper/io/trunk/src/test/java/org/apache/commons/io/IOUtilsTestCase.java
(original)
+++
commons/proper/io/trunk/src/test/java/org/apache/commons/io/IOUtilsTestCase.java
Sat Mar 17 01:21:11 2012
@@ -17,7 +17,9 @@
package org.apache.commons.io;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -73,10 +75,23 @@ public class IOUtilsTestCase extends Fil
throw new RuntimeException("Can't run this test because " +
"environment could not be built: "
+ ioe.getMessage());
}
+ // Create and init a byte array as input data
+ iarr = new byte[200];
+ Arrays.fill( iarr, (byte)-1);
+ for( int i=0; i< 80; i++){
+ iarr[i] = (byte) i;
+ }
+ carr = new char[200];
+ Arrays.fill( carr, (char)-1);
+ for( int i=0; i< 80; i++){
+ carr[i] = (char) i;
+ }
}
@Override
public void tearDown() {
+ carr = null;
+ iarr = null;
try {
FileUtils.deleteDirectory(getTestDirectory());
} catch (IOException ioe) {
@@ -718,4 +733,259 @@ public class IOUtilsTestCase extends Fil
IOUtils.closeQuietly(input);
}
+ // Tests from IO-305
+
+ private byte[] iarr = null;
+
+ public void testNoSkip() throws IOException {
+ ByteArrayInputStream is = null;
+ ByteArrayOutputStream os = null;
+ try {
+ // Create streams
+ is = new ByteArrayInputStream( iarr);
+ os = new ByteArrayOutputStream();
+
+ // Test our copy method
+ assertEquals(100, IOUtils.copyLarge( is, os, 0, 100));
+ byte[] oarr = os.toByteArray();
+
+ // check that output length is correct
+ assertEquals( 100, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals( -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testSkip() throws IOException {
+ ByteArrayInputStream is = null;
+ ByteArrayOutputStream os = null;
+ try {
+ // Create streams
+ is = new ByteArrayInputStream( iarr);
+ os = new ByteArrayOutputStream();
+
+ // Test our copy method
+ assertEquals(100, IOUtils.copyLarge( is, os, 10, 100));
+ byte[] oarr = os.toByteArray();
+
+ // check that output length is correct
+ assertEquals( 100, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 11, oarr[1] );
+ assertEquals( 79, oarr[69] );
+ assertEquals( -1, oarr[70] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testSkipInvalid() throws IOException {
+ ByteArrayInputStream is = null;
+ ByteArrayOutputStream os = null;
+ try {
+ // Create streams
+ is = new ByteArrayInputStream( iarr);
+ os = new ByteArrayOutputStream();
+
+ // Test our copy method
+ IOUtils.copyLarge( is, os, 1000, 100);
+ fail( "Should have thrown EOFException");
+ }
+ catch( EOFException eofe){
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testFullLength() throws IOException {
+ ByteArrayInputStream is = null;
+ ByteArrayOutputStream os = null;
+ try {
+ // Create streams
+ is = new ByteArrayInputStream( iarr);
+ os = new ByteArrayOutputStream();
+
+ // Test our copy method
+ assertEquals(200, IOUtils.copyLarge( is, os, 0, -1));
+ byte[] oarr = os.toByteArray();
+
+ // check that output length is correct
+ assertEquals( 200, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals( -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testExtraLength() throws IOException {
+ ByteArrayInputStream is = null;
+ ByteArrayOutputStream os = null;
+ try {
+ // Create streams
+ is = new ByteArrayInputStream( iarr);
+ os = new ByteArrayOutputStream();
+
+ // Test our copy method
+ // for extra length, it reads till EOF
+ assertEquals(200, IOUtils.copyLarge( is, os, 0, 2000));
+ byte[] oarr = os.toByteArray();
+
+ // check that output length is correct
+ assertEquals( 200, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals( -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ private char[] carr = null;
+
+ public void testCharNoSkip() throws IOException {
+ CharArrayReader is = null;
+ CharArrayWriter os = null;
+ try {
+ // Create streams
+ is = new CharArrayReader( carr);
+ os = new CharArrayWriter();
+
+ // Test our copy method
+ assertEquals(100, IOUtils.copyLarge( is, os, 0, 100));
+ char[] oarr = os.toCharArray();
+
+ // check that output length is correct
+ assertEquals( 100, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals((char) -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testCharSkip() throws IOException {
+ CharArrayReader is = null;
+ CharArrayWriter os = null;
+ try {
+ // Create streams
+ is = new CharArrayReader( carr);
+ os = new CharArrayWriter();
+
+ // Test our copy method
+ assertEquals(100, IOUtils.copyLarge( is, os, 10, 100));
+ char[] oarr = os.toCharArray();
+
+ // check that output length is correct
+ assertEquals( 100, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 11, oarr[1] );
+ assertEquals( 79, oarr[69] );
+ assertEquals((char) -1, oarr[70] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testCharSkipInvalid() throws IOException {
+ CharArrayReader is = null;
+ CharArrayWriter os = null;
+ try {
+ // Create streams
+ is = new CharArrayReader( carr);
+ os = new CharArrayWriter();
+
+ // Test our copy method
+ IOUtils.copyLarge( is, os, 1000, 100);
+ fail( "Should have thrown EOFException");
+ }
+ catch( EOFException eofe){
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testCharFullLength() throws IOException {
+ CharArrayReader is = null;
+ CharArrayWriter os = null;
+ try {
+ // Create streams
+ is = new CharArrayReader( carr);
+ os = new CharArrayWriter();
+
+ // Test our copy method
+ assertEquals(200, IOUtils.copyLarge( is, os, 0, -1));
+ char[] oarr = os.toCharArray();
+
+ // check that output length is correct
+ assertEquals( 200, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals((char) -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
+
+ public void testCharExtraLength() throws IOException {
+ CharArrayReader is = null;
+ CharArrayWriter os = null;
+ try {
+ // Create streams
+ is = new CharArrayReader( carr);
+ os = new CharArrayWriter();
+
+ // Test our copy method
+ // for extra length, it reads till EOF
+ assertEquals(200, IOUtils.copyLarge( is, os, 0, 2000));
+ char[] oarr = os.toCharArray();
+
+ // check that output length is correct
+ assertEquals( 200, oarr.length );
+ // check that output data corresponds to input data
+ assertEquals( 1, oarr[1] );
+ assertEquals( 79, oarr[79] );
+ assertEquals((char) -1, oarr[80] );
+
+ }
+ finally {
+ IOUtils.closeQuietly(is);
+ IOUtils.closeQuietly(os);
+ }
+ }
}