Skip to content

Commit e73aa1d

Browse files
authored
[IO-781] Make CharSequenceInputStream.available() more correct in the face of multibyte encodings (#525)
* Make available() more correct in the face of multibyte encodings * prefill byteBuf * detab * detab * checkstyle * checkstyle * detab
1 parent 2a0c2c4 commit e73aa1d

2 files changed

Lines changed: 22 additions & 7 deletions

File tree

src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ private CharSequenceInputStream(final CharSequence cs, final int bufferSize, fin
180180
this.cBuf = CharBuffer.wrap(cs);
181181
this.cBufMark = NO_MARK;
182182
this.bBufMark = NO_MARK;
183+
try {
184+
fillBuffer();
185+
} catch (CharacterCodingException ex) {
186+
// Reset everything without filling the buffer
187+
// so the same exception can be thrown again later.
188+
this.bBuf.clear();
189+
this.cBuf.rewind();
190+
}
183191
}
184192

185193
/**
@@ -210,18 +218,14 @@ public CharSequenceInputStream(final CharSequence cs, final String charset, fina
210218
}
211219

212220
/**
213-
* Return an estimate of the number of bytes remaining in the byte stream.
214-
* @return the count of bytes that can be read without blocking (or returning EOF).
221+
* Return a lower bound on the number of bytes remaining in the byte stream.
215222
*
223+
* @return the count of bytes that can be read without blocking (or returning EOF).
216224
* @throws IOException if an error occurs (probably not possible).
217225
*/
218226
@Override
219227
public int available() throws IOException {
220-
// The cached entries are in bBuf; since encoding always creates at least one byte
221-
// per character, we can add the two to get a better estimate (e.g. if bBuf is empty)
222-
// Note that the implementation in 2.4 could return zero even though there were
223-
// encoded bytes still available.
224-
return this.bBuf.remaining() + this.cBuf.remaining();
228+
return this.bBuf.remaining();
225229
}
226230

227231
@Override

src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,4 +511,15 @@ public void testSkip_RequiredCharsets(final String csName) throws Exception {
511511
assertEquals(-1, r.read(), csName);
512512
}
513513
}
514+
515+
@Test
516+
// IO-781 available() returns 2 but only 1 byte is read afterwards
517+
public void testAvailable() throws IOException {
518+
final Charset charset = Charset.forName("Big5");
519+
final CharSequenceInputStream in = new CharSequenceInputStream("\uD800\uDC00", charset);
520+
final int available = in.available();
521+
final byte[] data = new byte[available];
522+
final int bytesRead = in.read(data);
523+
assertEquals(available, bytesRead);
524+
}
514525
}

0 commit comments

Comments
 (0)