Author: niallp
Date: Mon Jan 7 20:20:00 2008
New Revision: 609864
URL: http://svn.apache.org/viewvc?rev=609864&view=rev
Log:
IO-153 Add a FileWriter that accepts an encoding - patch from Stephen Colebourne
Added:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
(with props)
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
(with props)
Modified:
commons/proper/io/trunk/RELEASE-NOTES.txt
commons/proper/io/trunk/build-check-jdk13.xml
commons/proper/io/trunk/src/test/org/apache/commons/io/output/PackageTestSuite.java
Modified: commons/proper/io/trunk/RELEASE-NOTES.txt
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/RELEASE-NOTES.txt?rev=609864&r1=609863&r2=609864&view=diff
==============================================================================
--- commons/proper/io/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/io/trunk/RELEASE-NOTES.txt Mon Jan 7 20:20:00 2008
@@ -24,9 +24,9 @@
Semantic compatible - Yes
Check the bug fixes section for semantic bug fixes
-Commons IO 1.4 introduces some new implementations which depend on JDK 1.4
-features (CharSequenceReader, IOExceptionWithCause and RegexFileFilter). It has
-been built with the JDK source and target options set to JDK 1.3 and, except
for
+Commons IO 1.4 introduces four new implementations which depend on JDK 1.4
features
+(CharSequenceReader, FileWriterWithEncoding, IOExceptionWithCause and
RegexFileFilter).
+It has been built with the JDK source and target options set to JDK 1.3 and,
except for
those implementations, can be used with JDK 1.3 (see IO IO-127).
@@ -52,6 +52,9 @@
- TeeInputStream [IO-129]
- Add new Tee input stream implementation
+
+- FileWriterWithEncoding [IO-153]
+ - Add new File Writer implementation that accepts an encoding
- CharSequenceReader [IO-138]
- Add new Reader implementation that handles any CharSequence (String,
Modified: commons/proper/io/trunk/build-check-jdk13.xml
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/build-check-jdk13.xml?rev=609864&r1=609863&r2=609864&view=diff
==============================================================================
--- commons/proper/io/trunk/build-check-jdk13.xml (original)
+++ commons/proper/io/trunk/build-check-jdk13.xml Mon Jan 7 20:20:00 2008
@@ -64,6 +64,7 @@
<exclude name="**/CharSequenceReader.java"/>
<exclude name="**/IOExceptionWithCause.java"/>
<exclude name="**/RegexFileFilter.java"/>
+ <exclude name="**/FileWriterWithEncoding.java"/>
</javac>
Added:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java?rev=609864&view=auto
==============================================================================
---
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
(added)
+++
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
Mon Jan 7 20:20:00 2008
@@ -0,0 +1,288 @@
+/*
+ * 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.commons.io.output;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Writer of files that allows the encoding to be set.
+ * <p>
+ * This class provides a simple alternative to <code>FileWriter</code>
+ * that allows an encoding to be set. Unfortunately, it cannot subclass
+ * <code>FileWriter</code>.
+ * <p>
+ * By default, the file will be overwritten, but this may be changed to append.
+ * The encoding may also be specified, and defaults to the platform default.
+ *
+ * @since Commons IO 1.4
+ * @version $Id$
+ */
+public class FileWriterWithEncoding extends Writer {
+ // Cannot extend ProxyWriter, as requires writer to be
+ // known when super() is called
+
+ /** The writer to decorate. */
+ private final Writer out;
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, String encoding) throws
IOException {
+ this(new File(filename), encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, String encoding, boolean
append) throws IOException {
+ this(new File(filename), encoding, append);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, Charset encoding) throws
IOException {
+ this(new File(filename), encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, Charset encoding, boolean
append) throws IOException {
+ this(new File(filename), encoding, append);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, CharsetEncoder encoding)
throws IOException {
+ this(new File(filename), encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param filename the name of the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file name or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(String filename, CharsetEncoder encoding,
boolean append) throws IOException {
+ this(new File(filename), encoding, append);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, String encoding) throws
IOException {
+ this(file, encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, String encoding, boolean append)
throws IOException {
+ super();
+ this.out = initWriter(file, encoding, append);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, Charset encoding) throws
IOException {
+ this(file, encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, Charset encoding, boolean append)
throws IOException {
+ super();
+ this.out = initWriter(file, encoding, append);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, CharsetEncoder encoding) throws
IOException {
+ this(file, encoding, false);
+ }
+
+ /**
+ * Constructs a FileWriterWithEncoding with a file encoding.
+ *
+ * @param file the file to write to, not null
+ * @param encoding the encoding to use, not null
+ * @param append true if content should be appended, false to overwrite
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException in case of an I/O error
+ */
+ public FileWriterWithEncoding(File file, CharsetEncoder encoding, boolean
append) throws IOException {
+ super();
+ this.out = initWriter(file, encoding, append);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Initialise the wrapped file writer.
+ * Ensure that a cleanup occurs if the writer creation fails.
+ *
+ * @param file the file to be accessed
+ * @param encoding the encoding to use - may be Charset, CharsetEncoder
or String
+ * @param append true to append
+ * @return the initialised writer
+ * @throws NullPointerException if the file or encoding is null
+ * @throws IOException if an error occurs
+ */
+ private static Writer initWriter(File file, Object encoding, boolean
append) throws IOException {
+ if (file == null) {
+ throw new NullPointerException("File is missing");
+ }
+ if (encoding == null) {
+ throw new NullPointerException("Encoding is missing");
+ }
+ boolean fileExistedAlready = file.exists();
+ OutputStream stream = null;
+ Writer writer = null;
+ try {
+ stream = new FileOutputStream(file, append);
+ if (encoding instanceof Charset) {
+ writer = new OutputStreamWriter(stream, (Charset)encoding);
+ } else if (encoding instanceof CharsetEncoder) {
+ writer = new OutputStreamWriter(stream,
(CharsetEncoder)encoding);
+ } else {
+ writer = new OutputStreamWriter(stream, (String)encoding);
+ }
+ } catch (IOException ex) {
+ IOUtils.closeQuietly(writer);
+ IOUtils.closeQuietly(stream);
+ if (fileExistedAlready == false) {
+ FileUtils.deleteQuietly(file);
+ }
+ throw ex;
+ } catch (RuntimeException ex) {
+ IOUtils.closeQuietly(writer);
+ IOUtils.closeQuietly(stream);
+ if (fileExistedAlready == false) {
+ FileUtils.deleteQuietly(file);
+ }
+ throw ex;
+ }
+ return writer;
+ }
+
+ //-----------------------------------------------------------------------
+ /** @see java.io.Writer#write(int) */
+ public void write(int idx) throws IOException {
+ out.write(idx);
+ }
+
+ /** @see java.io.Writer#write(char[]) */
+ public void write(char[] chr) throws IOException {
+ out.write(chr);
+ }
+
+ /** @see java.io.Writer#write(char[], int, int) */
+ public void write(char[] chr, int st, int end) throws IOException {
+ out.write(chr, st, end);
+ }
+
+ /** @see java.io.Writer#write(String) */
+ public void write(String str) throws IOException {
+ out.write(str);
+ }
+
+ /** @see java.io.Writer#write(String, int, int) */
+ public void write(String str, int st, int end) throws IOException {
+ out.write(str, st, end);
+ }
+
+ /** @see java.io.Writer#flush() */
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /** @see java.io.Writer#close() */
+ public void close() throws IOException {
+ out.close();
+ }
+}
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/FileWriterWithEncoding.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java?rev=609864&view=auto
==============================================================================
---
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
(added)
+++
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
Mon Jan 7 20:20:00 2008
@@ -0,0 +1,221 @@
+/*
+ * 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.commons.io.output;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.testtools.FileBasedTestCase;
+
+/**
+ * Tests that the encoding is actually set and used.
+ *
+ * @version $Revision$ $Date$
+ */
+public class FileWriterWithEncodingTest extends FileBasedTestCase {
+
+ private String defaultEncoding;
+ private File file1;
+ private File file2;
+ private String textContent;
+
+ public FileWriterWithEncodingTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ File encodingFinder = new File(getTestDirectory(), "finder.txt");
+ OutputStreamWriter out = null;
+ try {
+ out = new OutputStreamWriter(new FileOutputStream(encodingFinder));
+ defaultEncoding = out.getEncoding();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex.getMessage());
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
+ file1 = new File(getTestDirectory(), "testfile1.txt");
+ file2 = new File(getTestDirectory(), "testfile2.txt");
+ char[] arr = new char[1024];
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = (char) i;
+ }
+ textContent = new String(arr);
+ }
+
+ public void tearDown() {
+ defaultEncoding = null;
+ file1.delete();
+ file2.delete();
+ textContent = null;
+ }
+
+ //-----------------------------------------------------------------------
+ public void testSameEncoding() throws Exception {
+ FileWriter fw1 = null;
+ FileWriterWithEncoding fw2 = null;
+ try {
+ fw1 = new FileWriter(file1); // default encoding
+ fw2 = new FileWriterWithEncoding(file2, defaultEncoding);
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+
+ fw1.write(textContent);
+ fw2.write(textContent);
+
+ fw1.flush();
+ fw2.flush();
+ checkFile(file1, file2);
+
+ } finally {
+ IOUtils.closeQuietly(fw1);
+ IOUtils.closeQuietly(fw2);
+ }
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+ }
+
+ public void testDifferentEncoding() throws Exception {
+ Map map = Charset.availableCharsets();
+ if (map.containsKey("UTF-16BE")) {
+ FileWriter fw1 = null;
+ FileWriterWithEncoding fw2 = null;
+ try {
+ fw1 = new FileWriter(file1); // default encoding
+ fw2 = new FileWriterWithEncoding(file2, defaultEncoding);
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+
+ fw1.write(textContent);
+ fw2.write(textContent);
+
+ fw1.flush();
+ fw2.flush();
+ try {
+ checkFile(file1, file2);
+ fail();
+ } catch (AssertionFailedError ex) {
+ // success
+ }
+
+ } finally {
+ IOUtils.closeQuietly(fw1);
+ IOUtils.closeQuietly(fw2);
+ }
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+ }
+ if (map.containsKey("UTF-16LE")) {
+ FileWriter fw1 = null;
+ FileWriterWithEncoding fw2 = null;
+ try {
+ fw1 = new FileWriter(file1); // default encoding
+ fw2 = new FileWriterWithEncoding(file2, defaultEncoding);
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+
+ fw1.write(textContent);
+ fw2.write(textContent);
+
+ fw1.flush();
+ fw2.flush();
+ try {
+ checkFile(file1, file2);
+ fail();
+ } catch (AssertionFailedError ex) {
+ // success
+ }
+
+ } finally {
+ IOUtils.closeQuietly(fw1);
+ IOUtils.closeQuietly(fw2);
+ }
+ assertEquals(true, file1.exists());
+ assertEquals(true, file2.exists());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testConstructor_File_encoding_badEncoding() throws IOException
{
+ Writer writer = null;
+ try {
+ writer = new FileWriterWithEncoding(file1, "BAD-ENCODE");
+ fail();
+ } catch (IOException ex) {
+ // expected
+ assertEquals(false, file1.exists());
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ assertEquals(false, file1.exists());
+ }
+
+ //-----------------------------------------------------------------------
+ public void testConstructor_File_directory() throws IOException {
+ Writer writer = null;
+ try {
+ writer = new FileWriterWithEncoding(getTestDirectory(),
defaultEncoding);
+ fail();
+ } catch (IOException ex) {
+ // expected
+ assertEquals(false, file1.exists());
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ assertEquals(false, file1.exists());
+ }
+
+ //-----------------------------------------------------------------------
+ public void testConstructor_File_nullFile() throws IOException {
+ Writer writer = null;
+ try {
+ writer = new FileWriterWithEncoding((File) null, defaultEncoding);
+ fail();
+ } catch (NullPointerException ex) {
+ // expected
+ assertEquals(false, file1.exists());
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ assertEquals(false, file1.exists());
+ }
+
+ //-----------------------------------------------------------------------
+ public void testConstructor_fileName_nullFile() throws IOException {
+ Writer writer = null;
+ try {
+ writer = new FileWriterWithEncoding((String) null,
defaultEncoding);
+ fail();
+ } catch (NullPointerException ex) {
+ // expected
+ assertEquals(false, file1.exists());
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ assertEquals(false, file1.exists());
+ }
+
+}
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/FileWriterWithEncodingTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/PackageTestSuite.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/output/PackageTestSuite.java?rev=609864&r1=609863&r2=609864&view=diff
==============================================================================
---
commons/proper/io/trunk/src/test/org/apache/commons/io/output/PackageTestSuite.java
(original)
+++
commons/proper/io/trunk/src/test/org/apache/commons/io/output/PackageTestSuite.java
Mon Jan 7 20:20:00 2008
@@ -38,6 +38,7 @@
suite.addTest(new TestSuite(CloseShieldOutputStreamTest.class));
suite.addTest(new TestSuite(CountingOutputStreamTest.class));
suite.addTest(new TestSuite(DeferredFileOutputStreamTest.class));
+ suite.addTest(new TestSuite(FileWriterWithEncodingTest.class));
suite.addTest(new TestSuite(LockableFileWriterTest.class));
suite.addTest(new TestSuite(NullOutputStreamTest.class));
suite.addTest(new TestSuite(NullWriterTest.class));