Skip to content

Commit 2e11ed7

Browse files
author
Niall Pemberton
committed
IO-277 ReaderInputStream enters infinite loop when it encounters an unmappable character - thanks to Mike Thomas
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1165453 13f79535-47bb-0310-9956-ffa450edef68
1 parent 6ada743 commit 2e11ed7

3 files changed

Lines changed: 70 additions & 10 deletions

File tree

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

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.nio.charset.Charset;
2525
import java.nio.charset.CharsetEncoder;
2626
import java.nio.charset.CoderResult;
27+
import java.nio.charset.CodingErrorAction;
2728

2829
/**
2930
* {@link InputStream} implementation that reads a character stream from a {@link Reader}
@@ -100,16 +101,43 @@ public class ReaderInputStream extends InputStream {
100101
* Construct a new {@link ReaderInputStream}.
101102
*
102103
* @param reader the target {@link Reader}
103-
* @param charset the charset encoding
104+
* @param encoder the charset encoder
105+
* @since Commons IO 2.1
106+
*/
107+
public ReaderInputStream(Reader reader, CharsetEncoder encoder) {
108+
this(reader, encoder, DEFAULT_BUFFER_SIZE);
109+
}
110+
111+
/**
112+
* Construct a new {@link ReaderInputStream}.
113+
*
114+
* @param reader the target {@link Reader}
115+
* @param encoder the charset encoder
104116
* @param bufferSize the size of the input buffer in number of characters
117+
* @since Commons IO 2.1
105118
*/
106-
public ReaderInputStream(Reader reader, Charset charset, int bufferSize) {
119+
public ReaderInputStream(Reader reader, CharsetEncoder encoder, int bufferSize) {
107120
this.reader = reader;
108-
encoder = charset.newEncoder();
121+
this.encoder = encoder;
109122
encoderIn = CharBuffer.allocate(bufferSize);
110123
encoderIn.flip();
111124
}
112125

126+
/**
127+
* Construct a new {@link ReaderInputStream}.
128+
*
129+
* @param reader the target {@link Reader}
130+
* @param charset the charset encoding
131+
* @param bufferSize the size of the input buffer in number of characters
132+
*/
133+
public ReaderInputStream(Reader reader, Charset charset, int bufferSize) {
134+
this(reader,
135+
charset.newEncoder()
136+
.onMalformedInput(CodingErrorAction.REPLACE)
137+
.onUnmappableCharacter(CodingErrorAction.REPLACE),
138+
bufferSize);
139+
}
140+
113141
/**
114142
* Construct a new {@link ReaderInputStream} with a default input buffer size of
115143
* 1024 characters.

src/main/java/org/apache/commons/io/output/WriterOutputStream.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,28 +92,61 @@ public class WriterOutputStream extends OutputStream {
9292
*/
9393
private final CharBuffer decoderOut;
9494

95+
/**
96+
* Constructs a new {@link WriterOutputStream} with a default output buffer size of
97+
* 1024 characters. The output buffer will only be flushed when it overflows or when
98+
* {@link #flush()} or {@link #close()} is called.
99+
*
100+
* @param writer the target {@link Writer}
101+
* @param decoder the charset decoder
102+
* @since Commons IO 2.1
103+
*/
104+
public WriterOutputStream(Writer writer, CharsetDecoder decoder) {
105+
this(writer, decoder, DEFAULT_BUFFER_SIZE, false);
106+
}
107+
95108
/**
96109
* Constructs a new {@link WriterOutputStream}.
97110
*
98111
* @param writer the target {@link Writer}
99-
* @param charset the charset encoding
112+
* @param decoder the charset decoder
100113
* @param bufferSize the size of the output buffer in number of characters
101114
* @param writeImmediately If <tt>true</tt> the output buffer will be flushed after each
102115
* write operation, i.e. all available data will be written to the
103116
* underlying {@link Writer} immediately. If <tt>false</tt>, the
104117
* output buffer will only be flushed when it overflows or when
105118
* {@link #flush()} or {@link #close()} is called.
119+
* @since Commons IO 2.1
106120
*/
107-
public WriterOutputStream(Writer writer, Charset charset, int bufferSize, boolean writeImmediately) {
121+
public WriterOutputStream(Writer writer, CharsetDecoder decoder, int bufferSize, boolean writeImmediately) {
108122
this.writer = writer;
109-
decoder = charset.newDecoder();
110-
decoder.onMalformedInput(CodingErrorAction.REPLACE);
111-
decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
112-
decoder.replaceWith("?");
123+
this.decoder = decoder;
113124
this.writeImmediately = writeImmediately;
114125
decoderOut = CharBuffer.allocate(bufferSize);
115126
}
116127

128+
/**
129+
* Constructs a new {@link WriterOutputStream}.
130+
*
131+
* @param writer the target {@link Writer}
132+
* @param charset the charset encoding
133+
* @param bufferSize the size of the output buffer in number of characters
134+
* @param writeImmediately If <tt>true</tt> the output buffer will be flushed after each
135+
* write operation, i.e. all available data will be written to the
136+
* underlying {@link Writer} immediately. If <tt>false</tt>, the
137+
* output buffer will only be flushed when it overflows or when
138+
* {@link #flush()} or {@link #close()} is called.
139+
*/
140+
public WriterOutputStream(Writer writer, Charset charset, int bufferSize, boolean writeImmediately) {
141+
this(writer,
142+
charset.newDecoder()
143+
.onMalformedInput(CodingErrorAction.REPLACE)
144+
.onUnmappableCharacter(CodingErrorAction.REPLACE)
145+
.replaceWith("?"),
146+
bufferSize,
147+
writeImmediately);
148+
}
149+
117150
/**
118151
* Constructs a new {@link WriterOutputStream} with a default output buffer size of
119152
* 1024 characters. The output buffer will only be flushed when it overflows or when

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ public void testReadZero() throws Exception {
117117
* @throws IOException
118118
*/
119119
@Test
120-
@Ignore
121120
public void testCharsetMismatchInfiniteLoop() throws IOException {
122121
// Input is UTF-8 bytes: 0xE0 0xB2 0xA0
123122
char[] inputChars = new char[] { (char) 0xE0, (char) 0xB2, (char) 0xA0 };

0 commit comments

Comments
 (0)