/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.metamodel.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; /** * Writes Unicode text to an output stream. If the specified encoding is a * Unicode, then the text is preceeded by the proper Unicode BOM. If it is any * other encoding, this class behaves just like <code>OutputStreamWriter</code>. * This class is here because Java's <code>OutputStreamWriter</code> apparently * doesn't believe in writing BOMs. * <p> * * For optimum performance, it is recommended that you wrap all instances of * <code>UnicodeWriter</code> with a <code>java.io.BufferedWriter</code>. * * This file is an adaption of Rubert Futrell from FifeSoft UnicodeWriter (BSD * licensed). * * <pre> * UnicodeWriter.java - Writes Unicode output with the proper BOM. * Copyright (C) 2004 Robert Futrell * robert_futrell at users.sourceforge.net * http://fifesoft.com/rsyntaxtextarea * </pre> */ public class UnicodeWriter extends Writer { public static final byte[] UTF8_BOM = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; public static final byte[] UTF16LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE }; public static final byte[] UTF16BE_BOM = new byte[] { (byte) 0xFE, (byte) 0xFF }; public static final byte[] UTF32LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, (byte) 0x00 }; public static final byte[] UTF32BE_BOM = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, (byte) 0xFF }; /** * The writer actually doing the writing. */ private final OutputStreamWriter writer; /** * This is a utility constructor since the vast majority of the time, this * class will be used to write Unicode files. * * @param fileName * The file to which to write the Unicode output. * @param encoding * The encoding to use. * @throws UnsupportedEncodingException * If the specified encoding is not supported. * @throws IOException * If an IO exception occurs. */ public UnicodeWriter(String fileName, String encoding) throws UnsupportedEncodingException, IOException { this(new FileOutputStream(fileName), encoding); } /** * This is a utility constructor since the vast majority of the time, this * class will be used to write Unicode files. * * @param file * The file to which to write the Unicode output. * @param encoding * The encoding to use. * @throws UnsupportedEncodingException * If the specified encoding is not supported. * @throws IOException * If an IO exception occurs. */ public UnicodeWriter(File file, String encoding) throws UnsupportedEncodingException, IOException { this(new FileOutputStream(file), encoding); } /** * Creates a new writer. * * @param outputStream * The output stream to write. * @param encoding * The encoding to use. * @throws UnsupportedEncodingException * If the specified encoding is not supported. * @throws IOException * If an IO exception occurs. */ public UnicodeWriter(OutputStream outputStream, String encoding) throws UnsupportedEncodingException, IOException { writer = createWriter(outputStream, encoding); } /** * Closes this writer. * * @throws IOException * If an IO exception occurs. */ @Override public void close() throws IOException { writer.close(); } /** * Flushes the stream. * * @throws IOException * If an IO exception occurs. */ @Override public void flush() throws IOException { writer.flush(); } /** * Initializes the internal output stream and writes the BOM if the * specified encoding is a Unicode encoding. * * @param outputStream * The output stream we are writing. * @param encoding * The encoding in which to write. * @throws UnsupportedEncodingException * If the specified encoding isn't supported. * @throws IOException * If an I/O error occurs while writing a BOM. */ private OutputStreamWriter createWriter(OutputStream outputStream, String encoding) throws UnsupportedEncodingException, IOException { OutputStreamWriter writer = new OutputStreamWriter(outputStream, encoding); encoding = encoding.replaceAll("-", "").toUpperCase(); // Write the proper BOM if they specified a Unicode encoding. // NOTE: Creating an OutputStreamWriter with encoding "UTF-16" // DOES write out the BOM; "UTF-16LE", "UTF-16BE", "UTF-32", "UTF-32LE" // and "UTF-32BE" don't. if ("UTF8".equals(encoding)) { outputStream.write(UTF8_BOM, 0, UTF8_BOM.length); } else if ("UTF16LE".equals(encoding)) { outputStream.write(UTF16LE_BOM, 0, UTF16LE_BOM.length); } else if ("UTF16BE".equals(encoding)) { outputStream.write(UTF16BE_BOM, 0, UTF16BE_BOM.length); } else if ("UTF32LE".equals(encoding)) { outputStream.write(UTF32LE_BOM, 0, UTF32LE_BOM.length); } else if ("UTF32".equals(encoding) || "UTF32BE".equals(encoding)) { outputStream.write(UTF32BE_BOM, 0, UTF32BE_BOM.length); } return writer; } /** * Writes a portion of an array of characters. * * @param cbuf * The buffer of characters. * @param off * The offset from which to start writing characters. * @param len * The number of characters to write. * @throws IOException * If an I/O error occurs. */ @Override public void write(char[] cbuf, int off, int len) throws IOException { writer.write(cbuf, off, len); } /** * Writes a single character. * * @param c * An integer specifying the character to write. * @throws IOException * If an IO error occurs. */ @Override public void write(int c) throws IOException { writer.write(c); } /** * Writes a portion of a string. * * @param str * The string from which to write. * @param off * The offset from which to start writing characters. * @param len * The number of characters to write. * @throws IOException * If an IO error occurs. */ @Override public void write(String str, int off, int len) throws IOException { writer.write(str, off, len); } }