Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / java / io / OutputStreamWriter.java
blob29fb631faf413ef20b50c5e38241594ea1500712
1 /* OutputStreamWriter.java -- Writer that converts chars to bytes
2 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.io;
41 import gnu.java.nio.charset.EncodingHelper;
43 import java.nio.ByteBuffer;
44 import java.nio.CharBuffer;
45 import java.nio.charset.CharacterCodingException;
46 import java.nio.charset.Charset;
47 import java.nio.charset.CharsetEncoder;
48 import java.nio.charset.CodingErrorAction;
49 import java.nio.charset.MalformedInputException;
51 /**
52 * This class writes characters to an output stream that is byte oriented
53 * It converts the chars that are written to bytes using an encoding layer,
54 * which is specific to a particular encoding standard. The desired
55 * encoding can either be specified by name, or if no encoding is specified,
56 * the system default encoding will be used. The system default encoding
57 * name is determined from the system property <code>file.encoding</code>.
58 * The only encodings that are guaranteed to be available are "8859_1"
59 * (the Latin-1 character set) and "UTF8". Unfortunately, Java does not
60 * provide a mechanism for listing the encodings that are supported in
61 * a given implementation.
62 * <p>
63 * Here is a list of standard encoding names that may be available:
64 * <p>
65 * <ul>
66 * <li>8859_1 (ISO-8859-1/Latin-1)
67 * <li>8859_2 (ISO-8859-2/Latin-2)
68 * <li>8859_3 (ISO-8859-3/Latin-3)
69 * <li>8859_4 (ISO-8859-4/Latin-4)
70 * <li>8859_5 (ISO-8859-5/Latin-5)
71 * <li>8859_6 (ISO-8859-6/Latin-6)
72 * <li>8859_7 (ISO-8859-7/Latin-7)
73 * <li>8859_8 (ISO-8859-8/Latin-8)
74 * <li>8859_9 (ISO-8859-9/Latin-9)
75 * <li>ASCII (7-bit ASCII)
76 * <li>UTF8 (UCS Transformation Format-8)
77 * <li>More Later
78 * </ul>
80 * @author Aaron M. Renn (arenn@urbanophile.com)
81 * @author Per Bothner (bothner@cygnus.com)
82 * @date April 17, 1998.
84 public class OutputStreamWriter extends Writer
86 /**
87 * The output stream.
89 private OutputStream out;
91 /**
92 * The charset encoder.
94 private CharsetEncoder encoder;
96 /**
97 * java.io canonical name of the encoding.
99 private String encodingName;
102 * Buffer output before character conversion as it has costly overhead.
104 private CharBuffer outputBuffer;
105 private final static int BUFFER_SIZE = 1024;
108 * This method initializes a new instance of <code>OutputStreamWriter</code>
109 * to write to the specified stream using a caller supplied character
110 * encoding scheme. Note that due to a deficiency in the Java language
111 * design, there is no way to determine which encodings are supported.
113 * @param out The <code>OutputStream</code> to write to
114 * @param encoding_scheme The name of the encoding scheme to use for
115 * character to byte translation
117 * @exception UnsupportedEncodingException If the named encoding is
118 * not available.
120 public OutputStreamWriter (OutputStream out, String encoding_scheme)
121 throws UnsupportedEncodingException
123 this.out = out;
124 try
126 // Don't use NIO if avoidable
127 if(EncodingHelper.isISOLatin1(encoding_scheme))
129 encodingName = "ISO8859_1";
130 encoder = null;
131 return;
135 * Workraround for encodings with a byte-order-mark.
136 * We only want to write it once per stream.
138 try
140 if(encoding_scheme.equalsIgnoreCase("UnicodeBig") ||
141 encoding_scheme.equalsIgnoreCase("UTF-16") ||
142 encoding_scheme.equalsIgnoreCase("UTF16"))
144 encoding_scheme = "UTF-16BE";
145 out.write((byte)0xFE);
146 out.write((byte)0xFF);
148 else if(encoding_scheme.equalsIgnoreCase("UnicodeLittle")){
149 encoding_scheme = "UTF-16LE";
150 out.write((byte)0xFF);
151 out.write((byte)0xFE);
154 catch(IOException ioe)
158 outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
160 Charset cs = EncodingHelper.getCharset(encoding_scheme);
161 if(cs == null)
162 throw new UnsupportedEncodingException("Encoding "+encoding_scheme+
163 " unknown");
164 encoder = cs.newEncoder();
165 encodingName = EncodingHelper.getOldCanonical(cs.name());
167 encoder.onMalformedInput(CodingErrorAction.REPLACE);
168 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
170 catch(RuntimeException e)
172 // Default to ISO Latin-1, will happen if this is called, for instance,
173 // before the NIO provider is loadable.
174 encoder = null;
175 encodingName = "ISO8859_1";
180 * This method initializes a new instance of <code>OutputStreamWriter</code>
181 * to write to the specified stream using the default encoding.
183 * @param out The <code>OutputStream</code> to write to
185 public OutputStreamWriter (OutputStream out)
187 this.out = out;
188 outputBuffer = null;
189 try
191 String encoding = System.getProperty("file.encoding");
192 Charset cs = Charset.forName(encoding);
193 encoder = cs.newEncoder();
194 encodingName = EncodingHelper.getOldCanonical(cs.name());
196 catch(RuntimeException e)
198 encoder = null;
199 encodingName = "ISO8859_1";
202 if(encoder != null)
204 encoder.onMalformedInput(CodingErrorAction.REPLACE);
205 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
206 outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
211 * This method initializes a new instance of <code>OutputStreamWriter</code>
212 * to write to the specified stream using a given <code>Charset</code>.
214 * @param out The <code>OutputStream</code> to write to
215 * @param cs The <code>Charset</code> of the encoding to use
217 public OutputStreamWriter(OutputStream out, Charset cs)
219 this.out = out;
220 encoder = cs.newEncoder();
221 encoder.onMalformedInput(CodingErrorAction.REPLACE);
222 encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
223 outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
227 * This method initializes a new instance of <code>OutputStreamWriter</code>
228 * to write to the specified stream using a given
229 * <code>CharsetEncoder</code>.
231 * @param out The <code>OutputStream</code> to write to
232 * @param enc The <code>CharsetEncoder</code> to encode the output with
234 public OutputStreamWriter(OutputStream out, CharsetEncoder enc)
236 this.out = out;
237 encoder = enc;
238 outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
242 * This method closes this stream, and the underlying
243 * <code>OutputStream</code>
245 * @exception IOException If an error occurs
247 public void close () throws IOException
249 if(out == null)
250 return;
251 flush();
252 out.close ();
253 out = null;
257 * This method returns the name of the character encoding scheme currently
258 * in use by this stream. If the stream has been closed, then this method
259 * may return <code>null</code>.
261 * @return The encoding scheme name
263 public String getEncoding ()
265 return out != null ? encodingName : null;
269 * This method flushes any buffered bytes to the underlying output sink.
271 * @exception IOException If an error occurs
273 public void flush () throws IOException
275 if(out != null){
276 if(outputBuffer != null){
277 char[] buf = new char[outputBuffer.position()];
278 if(buf.length > 0){
279 outputBuffer.flip();
280 outputBuffer.get(buf);
281 writeConvert(buf, 0, buf.length);
282 outputBuffer.clear();
285 out.flush ();
290 * This method writes <code>count</code> characters from the specified
291 * array to the output stream starting at position <code>offset</code>
292 * into the array.
294 * @param buf The array of character to write from
295 * @param offset The offset into the array to start writing chars from
296 * @param count The number of chars to write.
298 * @exception IOException If an error occurs
300 public void write (char[] buf, int offset, int count) throws IOException
302 if(out == null)
303 throw new IOException("Stream is closed.");
304 if(buf == null)
305 throw new IOException("Buffer is null.");
307 if(outputBuffer != null)
309 if(count >= outputBuffer.remaining())
311 int r = outputBuffer.remaining();
312 outputBuffer.put(buf, offset, r);
313 writeConvert(outputBuffer.array(), 0, BUFFER_SIZE);
314 outputBuffer.clear();
315 offset += r;
316 count -= r;
317 // if the remaining bytes is larger than the whole buffer,
318 // just don't buffer.
319 if(count >= outputBuffer.remaining()){
320 writeConvert(buf, offset, count);
321 return;
324 outputBuffer.put(buf, offset, count);
325 } else writeConvert(buf, offset, count);
329 * Converts and writes characters.
331 private void writeConvert (char[] buf, int offset, int count)
332 throws IOException
334 if(encoder == null)
336 byte[] b = new byte[count];
337 for(int i=0;i<count;i++)
338 b[i] = (byte)((buf[offset+i] <= 0xFF)?buf[offset+i]:'?');
339 out.write(b);
340 } else {
341 try {
342 ByteBuffer output = encoder.encode(CharBuffer.wrap(buf,offset,count));
343 encoder.reset();
344 if(output.hasArray())
345 out.write(output.array());
346 else
348 byte[] outbytes = new byte[output.remaining()];
349 output.get(outbytes);
350 out.write(outbytes);
352 } catch(IllegalStateException e) {
353 throw new IOException("Internal error.");
354 } catch(MalformedInputException e) {
355 throw new IOException("Invalid character sequence.");
356 } catch(CharacterCodingException e) {
357 throw new IOException("Unmappable character.");
363 * This method writes <code>count</code> bytes from the specified
364 * <code>String</code> starting at position <code>offset</code> into the
365 * <code>String</code>.
367 * @param str The <code>String</code> to write chars from
368 * @param offset The position in the <code>String</code> to start
369 * writing chars from
370 * @param count The number of chars to write
372 * @exception IOException If an error occurs
374 public void write (String str, int offset, int count) throws IOException
376 if(str == null)
377 throw new IOException("String is null.");
379 write(str.toCharArray(), offset, count);
383 * This method writes a single character to the output stream.
385 * @param ch The char to write, passed as an int.
387 * @exception IOException If an error occurs
389 public void write (int ch) throws IOException
391 write(new char[]{ (char)ch }, 0, 1);
393 } // class OutputStreamWriter