| /* | |
| * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package java.io; | |
| import java.nio.CharBuffer; | |
| import java.nio.charset.Charset; | |
| import java.nio.charset.CharsetEncoder; | |
| import sun.nio.cs.StreamEncoder; | |
| /** | |
| * An OutputStreamWriter is a bridge from character streams to byte streams: | |
| * Characters written to it are encoded into bytes using a specified {@link | |
| * Charset charset}. The charset that it uses | |
| * may be specified by name or may be given explicitly, or the | |
| * default charset may be accepted. | |
| * | |
| * <p> Each invocation of a write() method causes the encoding converter to be | |
| * invoked on the given character(s). The resulting bytes are accumulated in a | |
| * buffer before being written to the underlying output stream. Note that the | |
| * characters passed to the write() methods are not buffered. | |
| * | |
| * <p> For top efficiency, consider wrapping an OutputStreamWriter within a | |
| * BufferedWriter so as to avoid frequent converter invocations. For example: | |
| * | |
| * {@snippet lang=java : | |
| * Writer out = new BufferedWriter(new OutputStreamWriter(anOutputStream)); | |
| * } | |
| * | |
| * <p> A <i>surrogate pair</i> is a character represented by a sequence of two | |
| * {@code char} values: A <i>high</i> surrogate in the range '\uD800' to | |
| * '\uDBFF' followed by a <i>low</i> surrogate in the range '\uDC00' to | |
| * '\uDFFF'. | |
| * | |
| * <p> A <i>malformed surrogate element</i> is a high surrogate that is not | |
| * followed by a low surrogate or a low surrogate that is not preceded by a | |
| * high surrogate. | |
| * | |
| * <p> This class always replaces malformed surrogate elements and unmappable | |
| * character sequences with the charset's default <i>substitution sequence</i>. | |
| * The {@linkplain CharsetEncoder} class should be used when more | |
| * control over the encoding process is required. | |
| * | |
| * @see BufferedWriter | |
| * @see OutputStream | |
| * @see Charset | |
| * | |
| * @author Mark Reinhold | |
| * @since 1.1 | |
| */ | |
| public class OutputStreamWriter extends Writer { | |
| private final StreamEncoder se; | |
| /** | |
| * Creates an OutputStreamWriter that uses the named charset. | |
| * | |
| * @param out | |
| * An OutputStream | |
| * | |
| * @param charsetName | |
| * The name of a supported {@link Charset charset} | |
| * | |
| * @throws UnsupportedEncodingException | |
| * If the named encoding is not supported | |
| */ | |
| @SuppressWarnings("this-escape") | |
| public OutputStreamWriter(OutputStream out, String charsetName) | |
| throws UnsupportedEncodingException | |
| { | |
| super(out); | |
| if (charsetName == null) | |
| throw new NullPointerException("charsetName"); | |
| se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); | |
| } | |
| /** | |
| * Creates an OutputStreamWriter that uses the default character encoding, or | |
| * where {@code out} is a {@code PrintStream}, the charset used by the print | |
| * stream. | |
| * | |
| * @param out An OutputStream | |
| * @see Charset#defaultCharset() | |
| */ | |
| @SuppressWarnings("this-escape") | |
| public OutputStreamWriter(OutputStream out) { | |
| super(out); | |
| se = StreamEncoder.forOutputStreamWriter(out, this, | |
| out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset()); | |
| } | |
| /** | |
| * Creates an OutputStreamWriter that uses the given charset. | |
| * | |
| * @param out | |
| * An OutputStream | |
| * | |
| * @param cs | |
| * A charset | |
| * | |
| * @since 1.4 | |
| */ | |
| @SuppressWarnings("this-escape") | |
| public OutputStreamWriter(OutputStream out, Charset cs) { | |
| super(out); | |
| if (cs == null) | |
| throw new NullPointerException("charset"); | |
| se = StreamEncoder.forOutputStreamWriter(out, this, cs); | |
| } | |
| /** | |
| * Creates an OutputStreamWriter that uses the given charset encoder. | |
| * | |
| * @param out | |
| * An OutputStream | |
| * | |
| * @param enc | |
| * A charset encoder | |
| * | |
| * @since 1.4 | |
| */ | |
| @SuppressWarnings("this-escape") | |
| public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { | |
| super(out); | |
| if (enc == null) | |
| throw new NullPointerException("charset encoder"); | |
| se = StreamEncoder.forOutputStreamWriter(out, this, enc); | |
| } | |
| /** | |
| * Returns the name of the character encoding being used by this stream. | |
| * | |
| * <p> If the encoding has an historical name then that name is returned; | |
| * otherwise the encoding's canonical name is returned. | |
| * | |
| * <p> If this instance was created with the {@link | |
| * #OutputStreamWriter(OutputStream, String)} constructor then the returned | |
| * name, being unique for the encoding, may differ from the name passed to | |
| * the constructor. This method may return {@code null} if the stream has | |
| * been closed. </p> | |
| * | |
| * @return The historical name of this encoding, or possibly | |
| * {@code null} if the stream has been closed | |
| * | |
| * @see Charset | |
| */ | |
| public String getEncoding() { | |
| return se.getEncoding(); | |
| } | |
| /** | |
| * Flushes the output buffer to the underlying byte stream, without flushing | |
| * the byte stream itself. This method is non-private only so that it may | |
| * be invoked by PrintStream. | |
| */ | |
| void flushBuffer() throws IOException { | |
| se.flushBuffer(); | |
| } | |
| /** | |
| * Writes a single character. | |
| * | |
| * @throws IOException If an I/O error occurs | |
| */ | |
| public void write(int c) throws IOException { | |
| se.write(c); | |
| } | |
| /** | |
| * Writes a portion of an array of characters. | |
| * | |
| * @param cbuf Buffer of characters | |
| * @param off Offset from which to start writing characters | |
| * @param len Number of characters to write | |
| * | |
| * @throws IndexOutOfBoundsException | |
| * If {@code off} is negative, or {@code len} is negative, | |
| * or {@code off + len} is negative or greater than the length | |
| * of the given array | |
| * | |
| * @throws IOException If an I/O error occurs | |
| */ | |
| public void write(char[] cbuf, int off, int len) throws IOException { | |
| se.write(cbuf, off, len); | |
| } | |
| /** | |
| * Writes a portion of a string. | |
| * | |
| * @param str A String | |
| * @param off Offset from which to start writing characters | |
| * @param len Number of characters to write | |
| * | |
| * @throws IndexOutOfBoundsException | |
| * If {@code off} is negative, or {@code len} is negative, | |
| * or {@code off + len} is negative or greater than the length | |
| * of the given string | |
| * | |
| * @throws IOException If an I/O error occurs | |
| */ | |
| public void write(String str, int off, int len) throws IOException { | |
| se.write(str, off, len); | |
| } | |
| @Override | |
| public Writer append(CharSequence csq, int start, int end) throws IOException { | |
| if (csq == null) csq = "null"; | |
| return append(csq.subSequence(start, end)); | |
| } | |
| @Override | |
| public Writer append(CharSequence csq) throws IOException { | |
| if (csq instanceof CharBuffer) { | |
| se.write((CharBuffer) csq); | |
| } else { | |
| se.write(String.valueOf(csq)); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Flushes the stream. | |
| * | |
| * @throws IOException If an I/O error occurs | |
| */ | |
| public void flush() throws IOException { | |
| se.flush(); | |
| } | |
| public void close() throws IOException { | |
| se.close(); | |
| } | |
| } |