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 */ OutputStreamWriter(OutputStream out, Charset cs)124 public OutputStreamWriter(OutputStream out, Charset cs) { 125 super(out); 126 if (cs == null) 127 throw new NullPointerException("charset"); 128 se = StreamEncoder.forOutputStreamWriter(out, this, cs); 129 } 130 131 /** 132 * Creates an OutputStreamWriter that uses the given charset encoder. 133 * 134 * @param out 135 * An OutputStream 136 * 137 * @param enc 138 * A charset encoder 139 * 140 * @since 1.4 141 */ OutputStreamWriter(OutputStream out, CharsetEncoder enc)142 public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { 143 super(out); 144 if (enc == null) 145 throw new NullPointerException("charset encoder"); 146 se = StreamEncoder.forOutputStreamWriter(out, this, enc); 147 } 148 149 /** 150 * Returns the name of the character encoding being used by this stream. 151 * 152 * <p> If the encoding has an historical name then that name is returned; 153 * otherwise the encoding's canonical name is returned. 154 * 155 * <p> If this instance was created with the {@link 156 * #OutputStreamWriter(OutputStream, String)} constructor then the returned 157 * name, being unique for the encoding, may differ from the name passed to 158 * the constructor. This method may return {@code null} if the stream has 159 * been closed. </p> 160 * 161 * @return The historical name of this encoding, or possibly 162 * {@code null} if the stream has been closed 163 * 164 * @see java.nio.charset.Charset 165 * 166 * @revised 1.4 167 */ getEncoding()168 public String getEncoding() { 169 return se.getEncoding(); 170 } 171 172 /** 173 * Flushes the output buffer to the underlying byte stream, without flushing 174 * the byte stream itself. This method is non-private only so that it may 175 * be invoked by PrintStream. 176 */ flushBuffer()177 void flushBuffer() throws IOException { 178 se.flushBuffer(); 179 } 180 181 /** 182 * Writes a single character. 183 * 184 * @throws IOException If an I/O error occurs 185 */ write(int c)186 public void write(int c) throws IOException { 187 se.write(c); 188 } 189 190 /** 191 * Writes a portion of an array of characters. 192 * 193 * @param cbuf Buffer of characters 194 * @param off Offset from which to start writing characters 195 * @param len Number of characters to write 196 * 197 * @throws IndexOutOfBoundsException 198 * If {@code off} is negative, or {@code len} is negative, 199 * or {@code off + len} is negative or greater than the length 200 * of the given array 201 * 202 * @throws IOException If an I/O error occurs 203 */ write(char cbuf[], int off, int len)204 public void write(char cbuf[], int off, int len) throws IOException { 205 se.write(cbuf, off, len); 206 } 207 208 /** 209 * Writes a portion of a string. 210 * 211 * @param str A String 212 * @param off Offset from which to start writing characters 213 * @param len Number of characters to write 214 * 215 * @throws IndexOutOfBoundsException 216 * If {@code off} is negative, or {@code len} is negative, 217 * or {@code off + len} is negative or greater than the length 218 * of the given string 219 * 220 * @throws IOException If an I/O error occurs 221 */ write(String str, int off, int len)222 public void write(String str, int off, int len) throws IOException { 223 se.write(str, off, len); 224 } 225 226 @Override append(CharSequence csq, int start, int end)227 public Writer append(CharSequence csq, int start, int end) throws IOException { 228 if (csq == null) csq = "null"; 229 return append(csq.subSequence(start, end)); 230 } 231 232 @Override append(CharSequence csq)233 public Writer append(CharSequence csq) throws IOException { 234 if (csq instanceof CharBuffer) { 235 se.write((CharBuffer) csq); 236 } else { 237 se.write(String.valueOf(csq)); 238 } 239 return this; 240 } 241 242 /** 243 * Flushes the stream. 244 * 245 * @throws IOException If an I/O error occurs 246 */ flush()247 public void flush() throws IOException { 248 se.flush(); 249 } 250 close()251 public void close() throws IOException { 252 se.close(); 253 } 254 } 255