Skip to content

Commit 43c87ac

Browse files
committed
<action issue="IO-358" dev="ggregory" type="add" due-to="yukoba">Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer).</action>
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1415223 13f79535-47bb-0310-9956-ffa450edef68
1 parent 3789b1a commit 43c87ac

3 files changed

Lines changed: 101 additions & 1 deletion

File tree

src/changes/changes.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ 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-358" dev="ggregory" type="fix" due-to="mortenh">
50+
<action issue="IO-358" dev="ggregory" type="add" due-to="yukoba">
51+
Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer).
52+
</action>
53+
<action issue="IO-357" dev="ggregory" type="fix" due-to="mortenh">
5154
[Tailer] InterruptedException while the thead is sleeping is silently ignored
5255
</action>
5356
<action issue="IO-353" dev="ggregory" type="add" due-to="ggregory">

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import java.net.URI;
3939
import java.net.URL;
4040
import java.net.URLConnection;
41+
import java.nio.ByteBuffer;
42+
import java.nio.channels.ReadableByteChannel;
4143
import java.nio.channels.Selector;
4244
import java.nio.charset.Charset;
4345
import java.nio.charset.UnsupportedCharsetException;
@@ -2537,6 +2539,30 @@ public static int read(InputStream input, byte[] buffer) throws IOException {
25372539
return read(input, buffer, 0, buffer.length);
25382540
}
25392541

2542+
/**
2543+
* Reads bytes from a ReadableByteChannel.
2544+
* <p>
2545+
* This implementation guarantees that it will read as many bytes
2546+
* as possible before giving up; this may not always be the case for
2547+
* subclasses of {@link ReadableByteChannel}.
2548+
*
2549+
* @param input the byte channel to read
2550+
* @param buffer byte buffer destination
2551+
* @return the actual length read; may be less than requested if EOF was reached
2552+
* @throws IOException if a read error occurs
2553+
* @since 2.5
2554+
*/
2555+
public static int read(ReadableByteChannel input, ByteBuffer buffer) throws IOException {
2556+
int length = buffer.remaining();
2557+
while (buffer.remaining() > 0) {
2558+
int count = input.read(buffer);
2559+
if (EOF == count) { // EOF
2560+
break;
2561+
}
2562+
}
2563+
return length - buffer.remaining();
2564+
}
2565+
25402566
/**
25412567
* Read the requested number of characters or fail if there are not enough left.
25422568
* <p>
@@ -2618,4 +2644,25 @@ public static void readFully(InputStream input, byte[] buffer, int offset, int l
26182644
public static void readFully(InputStream input, byte[] buffer) throws IOException {
26192645
readFully(input, buffer, 0, buffer.length);
26202646
}
2647+
2648+
/**
2649+
* Reads the requested number of bytes or fail if there are not enough left.
2650+
* <p>
2651+
* This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may
2652+
* not read as many bytes as requested (most likely because of reaching EOF).
2653+
*
2654+
* @param input the byte channel to read
2655+
* @param buffer byte buffer destination
2656+
*
2657+
* @throws IOException if there is a problem reading the file
2658+
* @throws EOFException if the number of bytes read was incorrect
2659+
* @since 2.5
2660+
*/
2661+
public static void readFully(ReadableByteChannel input, ByteBuffer buffer) throws IOException {
2662+
int expected = buffer.remaining();
2663+
int actual = read(input, buffer);
2664+
if (actual != expected) {
2665+
throw new EOFException("Length to read: " + expected + " actual: " + actual);
2666+
}
2667+
}
26212668
}

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import java.net.URI;
3939
import java.net.URL;
4040
import java.net.URLConnection;
41+
import java.nio.ByteBuffer;
42+
import java.nio.channels.FileChannel;
4143
import java.nio.channels.Selector;
4244
import java.util.Arrays;
4345
import java.util.List;
@@ -791,6 +793,54 @@ public void testReadStream() throws Exception {
791793

792794
}
793795

796+
public void testRead_ReadableByteChannel() throws Exception {
797+
ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
798+
final FileInputStream fileInputStream = new FileInputStream(m_testFile);
799+
FileChannel input = fileInputStream.getChannel();
800+
try {
801+
assertEquals(FILE_SIZE, IOUtils.read(input, buffer));
802+
assertEquals(0, IOUtils.read(input, buffer));
803+
assertEquals(0, buffer.remaining());
804+
assertEquals(0, input.read(buffer));
805+
buffer.clear();
806+
try {
807+
IOUtils.readFully(input, buffer);
808+
fail("Should have failed with EOFxception");
809+
} catch (EOFException expected) {
810+
// expected
811+
}
812+
} finally {
813+
IOUtils.closeQuietly(input);
814+
IOUtils.closeQuietly(fileInputStream);
815+
}}
816+
817+
public void testReadFully_ReadableByteChannel() throws Exception {
818+
ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
819+
final FileInputStream fileInputStream = new FileInputStream(m_testFile);
820+
FileChannel input = fileInputStream.getChannel();
821+
try {
822+
IOUtils.readFully(input, buffer);
823+
assertEquals(FILE_SIZE, buffer.position());
824+
assertEquals(0, buffer.remaining());
825+
assertEquals(0, input.read(buffer));
826+
IOUtils.readFully(input, buffer);
827+
assertEquals(FILE_SIZE, buffer.position());
828+
assertEquals(0, buffer.remaining());
829+
assertEquals(0, input.read(buffer));
830+
IOUtils.readFully(input, buffer);
831+
buffer.clear();
832+
try {
833+
IOUtils.readFully(input, buffer);
834+
fail("Should have failed with EOFxception");
835+
} catch (EOFException expected) {
836+
// expected
837+
}
838+
} finally {
839+
IOUtils.closeQuietly(input);
840+
IOUtils.closeQuietly(fileInputStream);
841+
}
842+
}
843+
794844
public void testReadReader() throws Exception {
795845
final int size = 1027;
796846

0 commit comments

Comments
 (0)