1 /* 2 * Copyright (c) 1996, 2019, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.io; 27 28 import java.nio.CharBuffer; 29 import java.nio.charset.Charset; 30 import java.nio.charset.CharsetEncoder; 31 import sun.nio.cs.StreamEncoder; 32 33 34 /** 35 * An OutputStreamWriter is a bridge from character streams to byte streams: 36 * Characters written to it are encoded into bytes using a specified {@link 37 * java.nio.charset.Charset charset}. The charset that it uses 38 * may be specified by name or may be given explicitly, or the platform's 39 * default charset may be accepted. 40 * 41 * <p> Each invocation of a write() method causes the encoding converter to be 42 * invoked on the given character(s). The resulting bytes are accumulated in a 43 * buffer before being written to the underlying output stream. Note that the 44 * characters passed to the write() methods are not buffered. 45 * 46 * <p> For top efficiency, consider wrapping an OutputStreamWriter within a 47 * BufferedWriter so as to avoid frequent converter invocations. For example: 48 * 49 * <pre> 50 * Writer out 51 * = new BufferedWriter(new OutputStreamWriter(System.out)); 52 * </pre> 53 * 54 * <p> A <i>surrogate pair</i> is a character represented by a sequence of two 55 * {@code char} values: A <i>high</i> surrogate in the range '\uD800' to 56 * '\uDBFF' followed by a <i>low</i> surrogate in the range '\uDC00' to 57 * '\uDFFF'. 58 * 59 * <p> A <i>malformed surrogate element</i> is a high surrogate that is not 60 * followed by a low surrogate or a low surrogate that is not preceded by a 61 * high surrogate. 62 * 63 * <p> This class always replaces malformed surrogate elements and unmappable 64 * character sequences with the charset's default <i>substitution sequence</i>. 65 * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more 66 * control over the encoding process is required. 67 * 68 * @see BufferedWriter 69 * @see OutputStream 70 * @see java.nio.charset.Charset 71 * 72 * @author Mark Reinhold 73 * @since 1.1 74 */ 75 76 public class OutputStreamWriter extends Writer { 77 78 private final StreamEncoder se; 79 80 /** 81 * Creates an OutputStreamWriter that uses the named charset. 82 * 83 * @param out 84 * An OutputStream 85 * 86 * @param charsetName 87 * The name of a supported 88 * {@link java.nio.charset.Charset charset} 89 * 90 * @throws UnsupportedEncodingException 91 * If the named encoding is not supported 92 */ OutputStreamWriter(OutputStream out, String charsetName)93 public OutputStreamWriter(OutputStream out, String charsetName) 94 throws UnsupportedEncodingException 95 { 96 super(out); 97 if (charsetName == null) 98 throw new NullPointerException("charsetName"); 99 se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); 100 } 101 102 /** 103 * Creates an OutputStreamWriter that uses the default character encoding. 104 * 105 * @param out An OutputStream 106 */ OutputStreamWriter(OutputStream out)107 public OutputStreamWriter(OutputStream out) { 108 super(out); 109 se = StreamEncoder.forOutputStreamWriter(out, this, 110 Charset.defaultCharset()); 111 } 112 113 /** 114 * Creates an OutputStreamWriter that uses the given charset. 115 * 116 * @param out 117 * An OutputStream 118 * 119 * @param cs 120 * A charset 121 * 122 * @since 1.4 123 * @spec JSR-51 124 */ OutputStreamWriter(OutputStream out, Charset cs)125 public OutputStreamWriter(OutputStream out, Charset cs) { 126 super(out); 127 if (cs == null) 128 throw new NullPointerException("charset"); 129 se = StreamEncoder.forOutputStreamWriter(out, this, cs); 130 } 131 132 /** 133 * Creates an OutputStreamWriter that uses the given charset encoder. 134 * 135 * @param out 136 * An OutputStream 137 * 138 * @param enc 139 * A charset encoder 140 * 141 * @since 1.4 142 * @spec JSR-51 143 */ OutputStreamWriter(OutputStream out, CharsetEncoder enc)144 public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { 145 super(out); 146 if (enc == null) 147 throw new NullPointerException("charset encoder"); 148 se = StreamEncoder.forOutputStreamWriter(out, this, enc); 149 } 150 151 /** 152 * Returns the name of the character encoding being used by this stream. 153 * 154 * <p> If the encoding has an historical name then that name is returned; 155 * otherwise the encoding's canonical name is returned. 156 * 157 * <p> If this instance was created with the {@link 158 * #OutputStreamWriter(OutputStream, String)} constructor then the returned 159 * name, being unique for the encoding, may differ from the name passed to 160 * the constructor. This method may return {@code null} if the stream has 161 * been closed. </p> 162 * 163 * @return The historical name of this encoding, or possibly 164 * {@code null} if the stream has been closed 165 * 166 * @see java.nio.charset.Charset 167 * 168 * @revised 1.4 169 * @spec JSR-51 170 */ getEncoding()171 public String getEncoding() { 172 return se.getEncoding(); 173 } 174 175 /** 176 * Flushes the output buffer to the underlying byte stream, without flushing 177 * the byte stream itself. This method is non-private only so that it may 178 * be invoked by PrintStream. 179 */ flushBuffer()180 void flushBuffer() throws IOException { 181 se.flushBuffer(); 182 } 183 184 /** 185 * Writes a single character. 186 * 187 * @throws IOException If an I/O error occurs 188 */ write(int c)189 public void write(int c) throws IOException { 190 se.write(c); 191 } 192 193 /** 194 * Writes a portion of an array of characters. 195 * 196 * @param cbuf Buffer of characters 197 * @param off Offset from which to start writing characters 198 * @param len Number of characters to write 199 * 200 * @throws IndexOutOfBoundsException 201 * If {@code off} is negative, or {@code len} is negative, 202 * or {@code off + len} is negative or greater than the length 203 * of the given array 204 * 205 * @throws IOException If an I/O error occurs 206 */ write(char cbuf[], int off, int len)207 public void write(char cbuf[], int off, int len) throws IOException { 208 se.write(cbuf, off, len); 209 } 210 211 /** 212 * Writes a portion of a string. 213 * 214 * @param str A String 215 * @param off Offset from which to start writing characters 216 * @param len Number of characters to write 217 * 218 * @throws IndexOutOfBoundsException 219 * If {@code off} is negative, or {@code len} is negative, 220 * or {@code off + len} is negative or greater than the length 221 * of the given string 222 * 223 * @throws IOException If an I/O error occurs 224 */ write(String str, int off, int len)225 public void write(String str, int off, int len) throws IOException { 226 se.write(str, off, len); 227 } 228 229 @Override append(CharSequence csq, int start, int end)230 public Writer append(CharSequence csq, int start, int end) throws IOException { 231 if (csq == null) csq = "null"; 232 return append(csq.subSequence(start, end)); 233 } 234 235 @Override append(CharSequence csq)236 public Writer append(CharSequence csq) throws IOException { 237 if (csq instanceof CharBuffer) { 238 se.write((CharBuffer) csq); 239 } else { 240 se.write(String.valueOf(csq)); 241 } 242 return this; 243 } 244 245 /** 246 * Flushes the stream. 247 * 248 * @throws IOException If an I/O error occurs 249 */ flush()250 public void flush() throws IOException { 251 se.flush(); 252 } 253 close()254 public void close() throws IOException { 255 se.close(); 256 } 257 } 258