Skip to content

Commit 1f4332a

Browse files
committed
[IO-887] WriterOutputStream fails on malformed input by default for
Cp850 input bytes.
1 parent 350a4bf commit 1f4332a

3 files changed

Lines changed: 34 additions & 15 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ The <action> type attribute can be add,update,fix,remove.
6161
<action type="fix" dev="ggregory" due-to="Kishor, Mashrur Mia" issue="IO-639">ReversedLinesFileReader does not read first line if its empty #829.</action>
6262
<action type="fix" dev="ggregory" due-to="Peter De Maeyer" issue="IO-886">Fixed incorrect regular expression in PathUtils.RelativeSortedPaths.extractKey(String, String).</action>
6363
<action type="fix" dev="ggregory" due-to="Martin Wiesner">Fix typos in Javadoc of FileUtils and related test classes #833.</action>
64+
<action type="fix" dev="ggregory" due-to="Daniel Vega, Gary Gregory" issue="IO-887">WriterOutputStream fails on malformed input by default for Cp850 input bytes.</action>
6465
<!-- ADD -->
6566
<action type="add" dev="ggregory" due-to="Gary Gregory, Piotr P. Karwasz">Add and use IOUtils.closeQuietlySuppress(Closeable, Throwable) #818.</action>
6667
<action type="add" dev="ggregory" due-to="Gary Gregory">Add ProxyWriter.setReference(Writer).</action>

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

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,14 @@ public WriterOutputStream get() throws IOException {
143143
@Override
144144
public Builder setCharset(final Charset charset) {
145145
super.setCharset(charset);
146-
this.charsetDecoder = getCharset().newDecoder();
146+
this.charsetDecoder = newDecoder(getCharset());
147147
return this;
148148
}
149149

150150
@Override
151151
public Builder setCharset(final String charset) {
152152
super.setCharset(charset);
153-
this.charsetDecoder = getCharset().newDecoder();
153+
this.charsetDecoder = newDecoder(getCharset());
154154
return this;
155155
}
156156

@@ -204,12 +204,12 @@ private static void checkIbmJdkWithBrokenUTF16(final Charset charset) {
204204
if (!StandardCharsets.UTF_16.name().equals(charset.name())) {
205205
return;
206206
}
207-
final String TEST_STRING_2 = "v\u00e9s";
208-
final byte[] bytes = TEST_STRING_2.getBytes(charset);
207+
final String testString = "v\u00e9s";
208+
final byte[] bytes = testString.getBytes(charset);
209209

210210
final CharsetDecoder charsetDecoder2 = charset.newDecoder();
211211
final ByteBuffer bb2 = ByteBuffer.allocate(16);
212-
final CharBuffer cb2 = CharBuffer.allocate(TEST_STRING_2.length());
212+
final CharBuffer cb2 = CharBuffer.allocate(testString.length());
213213
final int len = bytes.length;
214214
for (int i = 0; i < len; i++) {
215215
bb2.put(bytes[i]);
@@ -223,14 +223,24 @@ private static void checkIbmJdkWithBrokenUTF16(final Charset charset) {
223223
bb2.compact();
224224
}
225225
cb2.rewind();
226-
if (!TEST_STRING_2.equals(cb2.toString())) {
226+
if (!testString.equals(cb2.toString())) {
227227
throw new UnsupportedOperationException("UTF-16 requested when running on an IBM JDK with broken UTF-16 support. "
228228
+ "Please find a JDK that supports UTF-16 if you intend to use UF-16 with WriterOutputStream");
229229
}
230230

231231
}
232232

233+
private static CharsetDecoder newDecoder(final Charset charset) {
234+
// @formatter:off
235+
return Charsets.toCharset(charset).newDecoder()
236+
.onMalformedInput(CodingErrorAction.REPLACE)
237+
.onUnmappableCharacter(CodingErrorAction.REPLACE)
238+
.replaceWith("?");
239+
// @formatter:on
240+
}
241+
233242
private final Writer writer;
243+
234244
private final CharsetDecoder decoder;
235245

236246
private final boolean writeImmediately;
@@ -289,15 +299,7 @@ public WriterOutputStream(final Writer writer, final Charset charset) {
289299
*/
290300
@Deprecated
291301
public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize, final boolean writeImmediately) {
292-
// @formatter:off
293-
this(writer,
294-
Charsets.toCharset(charset).newDecoder()
295-
.onMalformedInput(CodingErrorAction.REPLACE)
296-
.onUnmappableCharacter(CodingErrorAction.REPLACE)
297-
.replaceWith("?"),
298-
bufferSize,
299-
writeImmediately);
300-
// @formatter:on
302+
this(writer, newDecoder(charset), bufferSize, writeImmediately);
301303
}
302304

303305
/**

src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ void testFlush() throws IOException {
5858
}
5959
}
6060

61+
@Test
62+
void testIO887() throws IOException {
63+
final StringWriter stringWriter1 = new StringWriter();
64+
final Charset charset = StandardCharsets.UTF_8;
65+
try (WriterOutputStream writerOutputStream = new WriterOutputStream(stringWriter1, charset)) {
66+
writerOutputStream.write("¿Cómo estás".getBytes("Cp850"));
67+
}
68+
final String expected = "?C?mo est?s";
69+
assertEquals(expected, stringWriter1.toString());
70+
final StringWriter stringWriter2 = new StringWriter();
71+
try (WriterOutputStream writerOutputStream = WriterOutputStream.builder().setWriter(stringWriter2).setCharset(charset).get()) {
72+
writerOutputStream.write("¿Cómo estás".getBytes("Cp850"));
73+
}
74+
assertEquals(expected, stringWriter2.toString());
75+
}
76+
6177
@Test
6278
void testLargeUTF8CharsetWithBufferedWrite() throws IOException {
6379
testWithBufferedWrite(LARGE_TEST_STRING, UTF_8);

0 commit comments

Comments
 (0)