Author: niallp Date: Mon Sep 5 23:34:43 2011 New Revision: 1165453 URL: http://svn.apache.org/viewvc?rev=1165453&view=rev Log: IO-277 ReaderInputStream enters infinite loop when it encounters an unmappable character - thanks to Mike Thomas
Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/ReaderInputStream.java commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/WriterOutputStream.java commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/ReaderInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/ReaderInputStream.java?rev=1165453&r1=1165452&r2=1165453&view=diff ============================================================================== --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/ReaderInputStream.java (original) +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/ReaderInputStream.java Mon Sep 5 23:34:43 2011 @@ -24,6 +24,7 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** * {@link InputStream} implementation that reads a character stream from a {@link Reader} @@ -100,17 +101,44 @@ public class ReaderInputStream extends I * Construct a new {@link ReaderInputStream}. * * @param reader the target {@link Reader} - * @param charset the charset encoding + * @param encoder the charset encoder + * @since Commons IO 2.1 + */ + public ReaderInputStream(Reader reader, CharsetEncoder encoder) { + this(reader, encoder, DEFAULT_BUFFER_SIZE); + } + + /** + * Construct a new {@link ReaderInputStream}. + * + * @param reader the target {@link Reader} + * @param encoder the charset encoder * @param bufferSize the size of the input buffer in number of characters + * @since Commons IO 2.1 */ - public ReaderInputStream(Reader reader, Charset charset, int bufferSize) { + public ReaderInputStream(Reader reader, CharsetEncoder encoder, int bufferSize) { this.reader = reader; - encoder = charset.newEncoder(); + this.encoder = encoder; encoderIn = CharBuffer.allocate(bufferSize); encoderIn.flip(); } /** + * Construct a new {@link ReaderInputStream}. + * + * @param reader the target {@link Reader} + * @param charset the charset encoding + * @param bufferSize the size of the input buffer in number of characters + */ + public ReaderInputStream(Reader reader, Charset charset, int bufferSize) { + this(reader, + charset.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE), + bufferSize); + } + + /** * Construct a new {@link ReaderInputStream} with a default input buffer size of * 1024 characters. * Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/WriterOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/WriterOutputStream.java?rev=1165453&r1=1165452&r2=1165453&view=diff ============================================================================== --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/WriterOutputStream.java (original) +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/WriterOutputStream.java Mon Sep 5 23:34:43 2011 @@ -93,28 +93,61 @@ public class WriterOutputStream extends private final CharBuffer decoderOut; /** + * Constructs a new {@link WriterOutputStream} with a default output buffer size of + * 1024 characters. The output buffer will only be flushed when it overflows or when + * {@link #flush()} or {@link #close()} is called. + * + * @param writer the target {@link Writer} + * @param decoder the charset decoder + * @since Commons IO 2.1 + */ + public WriterOutputStream(Writer writer, CharsetDecoder decoder) { + this(writer, decoder, DEFAULT_BUFFER_SIZE, false); + } + + /** * Constructs a new {@link WriterOutputStream}. * * @param writer the target {@link Writer} - * @param charset the charset encoding + * @param decoder the charset decoder * @param bufferSize the size of the output buffer in number of characters * @param writeImmediately If <tt>true</tt> the output buffer will be flushed after each * write operation, i.e. all available data will be written to the * underlying {@link Writer} immediately. If <tt>false</tt>, the * output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. + * @since Commons IO 2.1 */ - public WriterOutputStream(Writer writer, Charset charset, int bufferSize, boolean writeImmediately) { + public WriterOutputStream(Writer writer, CharsetDecoder decoder, int bufferSize, boolean writeImmediately) { this.writer = writer; - decoder = charset.newDecoder(); - decoder.onMalformedInput(CodingErrorAction.REPLACE); - decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); - decoder.replaceWith("?"); + this.decoder = decoder; this.writeImmediately = writeImmediately; decoderOut = CharBuffer.allocate(bufferSize); } /** + * Constructs a new {@link WriterOutputStream}. + * + * @param writer the target {@link Writer} + * @param charset the charset encoding + * @param bufferSize the size of the output buffer in number of characters + * @param writeImmediately If <tt>true</tt> the output buffer will be flushed after each + * write operation, i.e. all available data will be written to the + * underlying {@link Writer} immediately. If <tt>false</tt>, the + * output buffer will only be flushed when it overflows or when + * {@link #flush()} or {@link #close()} is called. + */ + public WriterOutputStream(Writer writer, Charset charset, int bufferSize, boolean writeImmediately) { + this(writer, + charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE) + .replaceWith("?"), + bufferSize, + writeImmediately); + } + + /** * Constructs a new {@link WriterOutputStream} with a default output buffer size of * 1024 characters. The output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java?rev=1165453&r1=1165452&r2=1165453&view=diff ============================================================================== --- commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java (original) +++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java Mon Sep 5 23:34:43 2011 @@ -117,7 +117,6 @@ public class ReaderInputStreamTest { * @throws IOException */ @Test - @Ignore public void testCharsetMismatchInfiniteLoop() throws IOException { // Input is UTF-8 bytes: 0xE0 0xB2 0xA0 char[] inputChars = new char[] { (char) 0xE0, (char) 0xB2, (char) 0xA0 };