Skip to content

Commit 231fb61

Browse files
committed
8276970: Default charset for PrintWriter that wraps PrintStream
Reviewed-by: rriggs, alanb
1 parent 29e552c commit 231fb61

File tree

4 files changed

+133
-9
lines changed

4 files changed

+133
-9
lines changed

src/java.base/share/classes/java/io/OutputStreamWriter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,17 @@ public OutputStreamWriter(OutputStream out, String charsetName)
9999
}
100100

101101
/**
102-
* Creates an OutputStreamWriter that uses the default character encoding.
102+
* Creates an OutputStreamWriter that uses the default character encoding, or
103+
* where {@code out} is a {@code PrintStream}, the charset used by the print
104+
* stream.
103105
*
104106
* @param out An OutputStream
105107
* @see Charset#defaultCharset()
106108
*/
107109
public OutputStreamWriter(OutputStream out) {
108110
super(out);
109111
se = StreamEncoder.forOutputStreamWriter(out, this,
110-
Charset.defaultCharset());
112+
out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
111113
}
112114

113115
/**

src/java.base/share/classes/java/io/PrintStream.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public class PrintStream extends FilterOutputStream
6868
private final boolean autoFlush;
6969
private boolean trouble = false;
7070
private Formatter formatter;
71+
private final Charset charset;
7172

7273
/**
7374
* Track both the text- and character-output streams, so that their buffers
@@ -108,7 +109,8 @@ private static Charset toCharset(String csn)
108109
private PrintStream(boolean autoFlush, OutputStream out) {
109110
super(out);
110111
this.autoFlush = autoFlush;
111-
this.charOut = new OutputStreamWriter(this);
112+
this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset();
113+
this.charOut = new OutputStreamWriter(this, charset);
112114
this.textOut = new BufferedWriter(charOut);
113115
}
114116

@@ -124,7 +126,8 @@ private PrintStream(boolean autoFlush, Charset charset, OutputStream out) {
124126
/**
125127
* Creates a new print stream, without automatic line flushing, with the
126128
* specified OutputStream. Characters written to the stream are converted
127-
* to bytes using the default charset.
129+
* to bytes using the default charset, or where {@code out} is a
130+
* {@code PrintStream}, the charset used by the print stream.
128131
*
129132
* @param out The output stream to which values and objects will be
130133
* printed
@@ -139,7 +142,8 @@ public PrintStream(OutputStream out) {
139142
/**
140143
* Creates a new print stream, with the specified OutputStream and line
141144
* flushing. Characters written to the stream are converted to bytes using
142-
* the default charset.
145+
* the default charset, or where {@code out} is a {@code PrintStream},
146+
* the charset used by the print stream.
143147
*
144148
* @param out The output stream to which values and objects will be
145149
* printed
@@ -201,6 +205,7 @@ public PrintStream(OutputStream out, boolean autoFlush, Charset charset) {
201205
this.autoFlush = autoFlush;
202206
this.charOut = new OutputStreamWriter(this, charset);
203207
this.textOut = new BufferedWriter(charOut);
208+
this.charset = charset;
204209
}
205210

206211
/**
@@ -1374,4 +1379,12 @@ public PrintStream append(char c) {
13741379
return this;
13751380
}
13761381

1382+
/**
1383+
* {@return the charset used in this {@code PrintStream} instance}
1384+
*
1385+
* @since 18
1386+
*/
1387+
public Charset charset() {
1388+
return charset;
1389+
}
13771390
}

src/java.base/share/classes/java/io/PrintWriter.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ public PrintWriter(Writer out,
118118
* Creates a new PrintWriter, without automatic line flushing, from an
119119
* existing OutputStream. This convenience constructor creates the
120120
* necessary intermediate OutputStreamWriter, which will convert characters
121-
* into bytes using the default charset.
121+
* into bytes using the default charset, or where {@code out} is a
122+
* {@code PrintStream}, the charset used by the print stream.
122123
*
123124
* @param out An output stream
124125
*
@@ -132,8 +133,9 @@ public PrintWriter(OutputStream out) {
132133
/**
133134
* Creates a new PrintWriter from an existing OutputStream. This
134135
* convenience constructor creates the necessary intermediate
135-
* OutputStreamWriter, which will convert characters into bytes using the
136-
* default charset.
136+
* OutputStreamWriter, which will convert characters into bytes using
137+
* the default charset, or where {@code out} is a {@code PrintStream},
138+
* the charset used by the print stream.
137139
*
138140
* @param out An output stream
139141
* @param autoFlush A boolean; if true, the {@code println},
@@ -144,7 +146,7 @@ public PrintWriter(OutputStream out) {
144146
* @see Charset#defaultCharset()
145147
*/
146148
public PrintWriter(OutputStream out, boolean autoFlush) {
147-
this(out, autoFlush, Charset.defaultCharset());
149+
this(out, autoFlush, out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
148150
}
149151

150152
/**
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import org.testng.annotations.DataProvider;
25+
import org.testng.annotations.Test;
26+
import static org.testng.Assert.assertEquals;
27+
28+
import java.io.ByteArrayOutputStream;
29+
import java.io.IOException;
30+
import java.io.OutputStreamWriter;
31+
import java.io.PrintStream;
32+
import java.io.PrintWriter;
33+
import java.nio.charset.Charset;
34+
import java.nio.charset.StandardCharsets;
35+
36+
/**
37+
* @test
38+
* @bug 8276970
39+
* @summary Test to verify the charset in PrintStream is inherited
40+
* in the OutputStreamWriter/PrintWriter
41+
* @run testng InheritEncodingTest
42+
*/
43+
@Test
44+
public class InheritEncodingTest {
45+
46+
private static final String testString = "\u00e9\u3042"; // "éあ"
47+
48+
@DataProvider
49+
public Object[][] encodings() {
50+
return new Object[][]{
51+
{StandardCharsets.ISO_8859_1},
52+
{StandardCharsets.US_ASCII},
53+
{StandardCharsets.UTF_8},
54+
{StandardCharsets.UTF_16},
55+
{StandardCharsets.UTF_16BE},
56+
{StandardCharsets.UTF_16LE},
57+
};
58+
}
59+
60+
@Test (dataProvider = "encodings")
61+
public void testOutputStreamWriter(Charset stdCharset) throws IOException {
62+
var ba = new ByteArrayOutputStream();
63+
var ps = new PrintStream(ba, true, stdCharset);
64+
var expected = new String(testString.getBytes(stdCharset), stdCharset);
65+
66+
// tests OutputStreamWriter's encoding explicitly
67+
var osw = new OutputStreamWriter(ps);
68+
assertEquals(Charset.forName(osw.getEncoding()), stdCharset);
69+
70+
// tests roundtrip result
71+
osw.write(testString);
72+
osw.flush();
73+
var result = ba.toString(stdCharset);
74+
assertEquals(result, expected);
75+
}
76+
77+
@Test (dataProvider = "encodings")
78+
public void testPrintWriter(Charset stdCharset) throws IOException {
79+
var ba = new ByteArrayOutputStream();
80+
var ps = new PrintStream(ba, true, stdCharset);
81+
var expected = new String(testString.getBytes(stdCharset), stdCharset);
82+
83+
// tests roundtrip result
84+
var pw = new PrintWriter(ps);
85+
pw.write(testString);
86+
pw.flush();
87+
var result = ba.toString(stdCharset);
88+
assertEquals(result, expected);
89+
}
90+
91+
@Test (dataProvider = "encodings")
92+
public void testPrintStream(Charset stdCharset) throws IOException {
93+
var ba = new ByteArrayOutputStream();
94+
var ps = new PrintStream(ba, true, stdCharset);
95+
var expected = new String(testString.getBytes(stdCharset), stdCharset);
96+
97+
// tests PrintStream's charset explicitly
98+
var psWrapper = new PrintStream(ps);
99+
assertEquals(psWrapper.charset(), stdCharset);
100+
101+
// tests roundtrip result
102+
psWrapper.print(testString);
103+
psWrapper.flush();
104+
var result = ba.toString(stdCharset);
105+
assertEquals(result, expected);
106+
}
107+
}

0 commit comments

Comments
 (0)