Skip to content

Commit 106c87c

Browse files
committed
<action issue="IO-359" dev="ggregory" type="add" due-to="yukoba">Add IOUtils.skip and skipFully(ReadableByteChannel, long).</action>
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1415648 13f79535-47bb-0310-9956-ffa450edef68
1 parent 471b947 commit 106c87c

3 files changed

Lines changed: 92 additions & 0 deletions

File tree

src/changes/changes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ The <action> type attribute can be add,update,fix,remove.
4747
<body>
4848
<!-- The release date is the date RC is cut -->
4949
<release version="2.5" date="201?-??-??" description="New features and bug fixes.">
50+
<action issue="IO-359" dev="ggregory" type="add" due-to="yukoba">
51+
Add IOUtils.skip and skipFully(ReadableByteChannel, long).
52+
</action>
5053
<action issue="IO-358" dev="ggregory" type="add" due-to="yukoba">
5154
Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer).
5255
</action>

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,6 +2342,37 @@ public static long skip(InputStream input, long toSkip) throws IOException {
23422342
return toSkip - remain;
23432343
}
23442344

2345+
/**
2346+
* Skip bytes from a ReadableByteChannel.
2347+
* This implementation guarantees that it will read as many bytes
2348+
* as possible before giving up.
2349+
*
2350+
* @param input ReadableByteChannel to skip
2351+
* @param toSkip number of bytes to skip.
2352+
* @return number of bytes actually skipped.
2353+
*
2354+
* @throws IOException if there is a problem reading the ReadableByteChannel
2355+
* @throws IllegalArgumentException if toSkip is negative
2356+
* @since 2.5
2357+
*/
2358+
public static long skip(ReadableByteChannel input, long toSkip) throws IOException {
2359+
if (toSkip < 0) {
2360+
throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
2361+
}
2362+
ByteBuffer skipByteBuffer = ByteBuffer.allocate((int) Math.min(toSkip, SKIP_BUFFER_SIZE));
2363+
long remain = toSkip;
2364+
while (remain > 0) {
2365+
skipByteBuffer.position(0);
2366+
skipByteBuffer.limit((int) Math.min(remain, SKIP_BUFFER_SIZE));
2367+
int n = input.read(skipByteBuffer);
2368+
if (n == EOF) {
2369+
break;
2370+
}
2371+
remain -= n;
2372+
}
2373+
return toSkip - remain;
2374+
}
2375+
23452376
/**
23462377
* Skip characters from an input character stream.
23472378
* This implementation guarantees that it will read as many characters
@@ -2419,6 +2450,27 @@ public static void skipFully(InputStream input, long toSkip) throws IOException
24192450
}
24202451
}
24212452

2453+
/**
2454+
* Skip the requested number of bytes or fail if there are not enough left.
2455+
*
2456+
* @param input ReadableByteChannel to skip
2457+
* @param toSkip the number of bytes to skip
2458+
*
2459+
* @throws IOException if there is a problem reading the ReadableByteChannel
2460+
* @throws IllegalArgumentException if toSkip is negative
2461+
* @throws EOFException if the number of bytes skipped was incorrect
2462+
* @since 2.5
2463+
*/
2464+
public static void skipFully(ReadableByteChannel input, long toSkip) throws IOException {
2465+
if (toSkip < 0) {
2466+
throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
2467+
}
2468+
long skipped = skip(input, toSkip);
2469+
if (skipped != toSkip) {
2470+
throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
2471+
}
2472+
}
2473+
24222474
/**
24232475
* Skip the requested number of characters or fail if there are not enough left.
24242476
* <p>

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,19 @@ public void testSkip_InputStream() throws Exception {
739739
}
740740
}
741741

742+
public void testSkip_ReadableByteChannel() throws Exception {
743+
FileInputStream fileInputStream = new FileInputStream(m_testFile);
744+
FileChannel fileChannel = fileInputStream.getChannel();
745+
try {
746+
assertEquals(FILE_SIZE - 10, IOUtils.skip(fileChannel, FILE_SIZE - 10));
747+
assertEquals(10, IOUtils.skip(fileChannel, 20));
748+
assertEquals(0, IOUtils.skip(fileChannel, 10));
749+
} finally {
750+
IOUtils.closeQuietly(fileChannel);
751+
IOUtils.closeQuietly(fileInputStream);
752+
}
753+
}
754+
742755
public void testSkipFully_InputStream() throws Exception {
743756
final int size = 1027;
744757

@@ -761,6 +774,30 @@ public void testSkipFully_InputStream() throws Exception {
761774

762775
}
763776

777+
public void testSkipFully_ReadableByteChannel() throws Exception {
778+
FileInputStream fileInputStream = new FileInputStream(m_testFile);
779+
FileChannel fileChannel = fileInputStream.getChannel();
780+
try {
781+
try {
782+
IOUtils.skipFully(fileChannel, -1);
783+
fail("Should have failed with IllegalArgumentException");
784+
} catch (IllegalArgumentException expected) {
785+
// expected
786+
}
787+
IOUtils.skipFully(fileChannel, 0);
788+
IOUtils.skipFully(fileChannel, FILE_SIZE - 1);
789+
try {
790+
IOUtils.skipFully(fileChannel, 2);
791+
fail("Should have failed with IOException");
792+
} catch (IOException expected) {
793+
// expected
794+
}
795+
} finally {
796+
IOUtils.closeQuietly(fileChannel);
797+
IOUtils.closeQuietly(fileInputStream);
798+
}
799+
}
800+
764801
public void testSkipFully_Reader() throws Exception {
765802
final int size = 1027;
766803

0 commit comments

Comments
 (0)