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