1 /* 2 * Copyright (c) 1996, 2016, 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. The size of 44 * this buffer may be specified, but by default it is large enough for most 45 * purposes. Note that the characters passed to the write() methods are not 46 * buffered. 47 * 48 * <p> For top efficiency, consider wrapping an OutputStreamWriter within a 49 * BufferedWriter so as to avoid frequent converter invocations. For example: 50 * 51 * <pre> 52 * Writer out 53 * = new BufferedWriter(new OutputStreamWriter(System.out)); 54 * </pre> 55 * 56 * <p> A <i>surrogate pair</i> is a character represented by a sequence of two 57 * {@code char} values: A <i>high</i> surrogate in the range '\uD800' to 58 * '\uDBFF' followed by a <i>low</i> surrogate in the range '\uDC00' to 59 * '\uDFFF'. 60 * 61 * <p> A <i>malformed surrogate element</i> is a high surrogate that is not 62 * followed by a low surrogate or a low surrogate that is not preceded by a 63 * high surrogate. 64 * 65 * <p> This class always replaces malformed surrogate elements and unmappable 66 * character sequences with the charset's default <i>substitution sequence</i>. 67 * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more 68 * control over the encoding process is required. 69 * 70 * @see BufferedWriter 71 * @see OutputStream 72 * @see java.nio.charset.Charset 73 * 74 * @author Mark Reinhold 75 * @since 1.1 76 */ 77 78 public class OutputStreamWriter extends Writer { 79 80 private final StreamEncoder se; 81 82 /** 83 * Creates an OutputStreamWriter that uses the named charset. 84 * 85 * @param out 86 * An OutputStream 87 * 88 * @param charsetName 89 * The name of a supported 90 * {@link java.nio.charset.Charset charset} 91 * 92 * @exception UnsupportedEncodingException 93 * If the named encoding is not supported 94 */ 95 public OutputStreamWriter(OutputStream out, String charsetName) 96 throws UnsupportedEncodingException 97 { 98 super(out); 99 if (charsetName == null) 100 throw new NullPointerException("charsetName"); 101 se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); 102 } 103 104 /** 105 * Creates an OutputStreamWriter that uses the default character encoding. 106 * 107 * @param out An OutputStream 108 */ 109 public OutputStreamWriter(OutputStream out) { 110 super(out); 111 try { 112 se = StreamEncoder.forOutputStreamWriter(out, this, (String)null); 113 } catch (UnsupportedEncodingException e) { 114 throw new Error(e); 115 } 116 } 117 118 /** 119 * Creates an OutputStreamWriter that uses the given charset. 120 * 121 * @param out 122 * An OutputStream 123 * 124 * @param cs 125 * A charset 126 * 127 * @since 1.4 128 * @spec JSR-51 129 */ 130 public OutputStreamWriter(OutputStream out, Charset cs) { 131 super(out); 132 if (cs == null) 133 throw new NullPointerException("charset"); 134 se = StreamEncoder.forOutputStreamWriter(out, this, cs); 135 } 136 137 /** 138 * Creates an OutputStreamWriter that uses the given charset encoder. 139 * 140 * @param out 141 * An OutputStream 142 * 143 * @param enc 144 * A charset encoder 145 * 146 * @since 1.4 147 * @spec JSR-51 148 */ 149 public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { 150 super(out); 151 if (enc == null) 152 throw new NullPointerException("charset encoder"); 153 se = StreamEncoder.forOutputStreamWriter(out, this, enc); 154 } 155 156 /** 157 * Returns the name of the character encoding being used by this stream. 158 * 159 * <p> If the encoding has an historical name then that name is returned; 160 * otherwise the encoding's canonical name is returned. 161 * 162 * <p> If this instance was created with the {@link 163 * #OutputStreamWriter(OutputStream, String)} constructor then the returned 164 * name, being unique for the encoding, may differ from the name passed to 165 * the constructor. This method may return {@code null} if the stream has 166 * been closed. </p> 167 * 168 * @return The historical name of this encoding, or possibly 169 * <code>null</code> if the stream has been closed 170 * 171 * @see java.nio.charset.Charset 172 * 173 * @revised 1.4 174 * @spec JSR-51 175 */ 176 public String getEncoding() { 177 return se.getEncoding(); 178 } 179 180 /** 181 * Flushes the output buffer to the underlying byte stream, without flushing 182 * the byte stream itself. This method is non-private only so that it may 183 * be invoked by PrintStream. 184 */ 185 void flushBuffer() throws IOException { 186 se.flushBuffer(); 187 } 188 189 /** 190 * Writes a single character. 191 * 192 * @exception IOException If an I/O error occurs 193 */ 194 public void write(int c) throws IOException { 195 se.write(c); 196 } 197 198 /** 199 * Writes a portion of an array of characters. 200 * 201 * @param cbuf Buffer of characters 202 * @param off Offset from which to start writing characters 203 * @param len Number of characters to write 204 * 205 * @throws IndexOutOfBoundsException 206 * If {@code off} is negative, or {@code len} is negative, 207 * or {@code off + len} is negative or greater than the length 208 * of the given array 209 * 210 * @throws IOException If an I/O error occurs 211 */ 212 public void write(char cbuf[], int off, int len) throws IOException { 213 se.write(cbuf, off, len); 214 } 215 216 /** 217 * Writes a portion of a string. 218 * 219 * @param str A String 220 * @param off Offset from which to start writing characters 221 * @param len Number of characters to write 222 * 223 * @throws IndexOutOfBoundsException 224 * If {@code off} is negative, or {@code len} is negative, 225 * or {@code off + len} is negative or greater than the length 226 * of the given string 227 * 228 * @throws IOException If an I/O error occurs 229 */ 230 public void write(String str, int off, int len) throws IOException { 231 se.write(str, off, len); 232 } 233 234 @Override 235 public Writer append(CharSequence csq, int start, int end) throws IOException { 236 if (csq == null) { 237 write("null".subSequence(start, end).toString()); 238 return this; 239 } else { 240 return append(csq.subSequence(start, end)); 241 } 242 } 243 244 @Override 245 public Writer append(CharSequence csq) throws IOException { 246 if (csq == null) { 247 se.write("null"); 248 } else if (csq instanceof CharBuffer) { 249 se.write((CharBuffer) csq); 250 } else { 251 se.write(csq.toString()); 252 } 253 return this; 254 } 255 256 /** 257 * Flushes the stream. 258 * 259 * @exception IOException If an I/O error occurs 260 */ 261 public void flush() throws IOException { 262 se.flush(); 263 } 264 265 public void close() throws IOException { 266 se.close(); 267 } 268 }