• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.io.output;
18 
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.OutputStreamWriter;
24 import java.io.Writer;
25 import java.nio.charset.Charset;
26 import java.nio.charset.CharsetEncoder;
27 
28 import org.apache.commons.io.FileUtils;
29 import org.apache.commons.io.IOUtils;
30 
31 /**
32  * Writer of files that allows the encoding to be set.
33  * <p>
34  * This class provides a simple alternative to <code>FileWriter</code>
35  * that allows an encoding to be set. Unfortunately, it cannot subclass
36  * <code>FileWriter</code>.
37  * <p>
38  * By default, the file will be overwritten, but this may be changed to append.
39  * <p>
40  * The encoding must be specified using either the name of the {@link Charset},
41  * the {@link Charset}, or a {@link CharsetEncoder}. If the default encoding
42  * is required then use the {@link java.io.FileWriter} directly, rather than
43  * this implementation.
44  * <p>
45  *
46  *
47  * @since Commons IO 1.4
48  * @version $Id: FileWriterWithEncoding.java 611634 2008-01-13 20:35:00Z niallp $
49  */
50 public class FileWriterWithEncoding extends Writer {
51     // Cannot extend ProxyWriter, as requires writer to be
52     // known when super() is called
53 
54     /** The writer to decorate. */
55     private final Writer out;
56 
57     /**
58      * Constructs a FileWriterWithEncoding with a file encoding.
59      *
60      * @param filename  the name of the file to write to, not null
61      * @param encoding  the encoding to use, not null
62      * @throws NullPointerException if the file name or encoding is null
63      * @throws IOException in case of an I/O error
64      */
FileWriterWithEncoding(String filename, String encoding)65     public FileWriterWithEncoding(String filename, String encoding) throws IOException {
66         this(new File(filename), encoding, false);
67     }
68 
69     /**
70      * Constructs a FileWriterWithEncoding with a file encoding.
71      *
72      * @param filename  the name of the file to write to, not null
73      * @param encoding  the encoding to use, not null
74      * @param append  true if content should be appended, false to overwrite
75      * @throws NullPointerException if the file name or encoding is null
76      * @throws IOException in case of an I/O error
77      */
FileWriterWithEncoding(String filename, String encoding, boolean append)78     public FileWriterWithEncoding(String filename, String encoding, boolean append) throws IOException {
79         this(new File(filename), encoding, append);
80     }
81 
82     /**
83      * Constructs a FileWriterWithEncoding with a file encoding.
84      *
85      * @param filename  the name of the file to write to, not null
86      * @param encoding  the encoding to use, not null
87      * @throws NullPointerException if the file name or encoding is null
88      * @throws IOException in case of an I/O error
89      */
FileWriterWithEncoding(String filename, Charset encoding)90     public FileWriterWithEncoding(String filename, Charset encoding) throws IOException {
91         this(new File(filename), encoding, false);
92     }
93 
94     /**
95      * Constructs a FileWriterWithEncoding with a file encoding.
96      *
97      * @param filename  the name of the file to write to, not null
98      * @param encoding  the encoding to use, not null
99      * @param append  true if content should be appended, false to overwrite
100      * @throws NullPointerException if the file name or encoding is null
101      * @throws IOException in case of an I/O error
102      */
FileWriterWithEncoding(String filename, Charset encoding, boolean append)103     public FileWriterWithEncoding(String filename, Charset encoding, boolean append) throws IOException {
104         this(new File(filename), encoding, append);
105     }
106 
107     /**
108      * Constructs a FileWriterWithEncoding with a file encoding.
109      *
110      * @param filename  the name of the file to write to, not null
111      * @param encoding  the encoding to use, not null
112      * @throws NullPointerException if the file name or encoding is null
113      * @throws IOException in case of an I/O error
114      */
FileWriterWithEncoding(String filename, CharsetEncoder encoding)115     public FileWriterWithEncoding(String filename, CharsetEncoder encoding) throws IOException {
116         this(new File(filename), encoding, false);
117     }
118 
119     /**
120      * Constructs a FileWriterWithEncoding with a file encoding.
121      *
122      * @param filename  the name of the file to write to, not null
123      * @param encoding  the encoding to use, not null
124      * @param append  true if content should be appended, false to overwrite
125      * @throws NullPointerException if the file name or encoding is null
126      * @throws IOException in case of an I/O error
127      */
FileWriterWithEncoding(String filename, CharsetEncoder encoding, boolean append)128     public FileWriterWithEncoding(String filename, CharsetEncoder encoding, boolean append) throws IOException {
129         this(new File(filename), encoding, append);
130     }
131 
132     /**
133      * Constructs a FileWriterWithEncoding with a file encoding.
134      *
135      * @param file  the file to write to, not null
136      * @param encoding  the encoding to use, not null
137      * @throws NullPointerException if the file or encoding is null
138      * @throws IOException in case of an I/O error
139      */
FileWriterWithEncoding(File file, String encoding)140     public FileWriterWithEncoding(File file, String encoding) throws IOException {
141         this(file, encoding, false);
142     }
143 
144     /**
145      * Constructs a FileWriterWithEncoding with a file encoding.
146      *
147      * @param file  the file to write to, not null
148      * @param encoding  the encoding to use, not null
149      * @param append  true if content should be appended, false to overwrite
150      * @throws NullPointerException if the file or encoding is null
151      * @throws IOException in case of an I/O error
152      */
FileWriterWithEncoding(File file, String encoding, boolean append)153     public FileWriterWithEncoding(File file, String encoding, boolean append) throws IOException {
154         super();
155         this.out = initWriter(file, encoding, append);
156     }
157 
158     /**
159      * Constructs a FileWriterWithEncoding with a file encoding.
160      *
161      * @param file  the file to write to, not null
162      * @param encoding  the encoding to use, not null
163      * @throws NullPointerException if the file or encoding is null
164      * @throws IOException in case of an I/O error
165      */
FileWriterWithEncoding(File file, Charset encoding)166     public FileWriterWithEncoding(File file, Charset encoding) throws IOException {
167         this(file, encoding, false);
168     }
169 
170     /**
171      * Constructs a FileWriterWithEncoding with a file encoding.
172      *
173      * @param file  the file to write to, not null
174      * @param encoding  the encoding to use, not null
175      * @param append  true if content should be appended, false to overwrite
176      * @throws NullPointerException if the file or encoding is null
177      * @throws IOException in case of an I/O error
178      */
FileWriterWithEncoding(File file, Charset encoding, boolean append)179     public FileWriterWithEncoding(File file, Charset encoding, boolean append) throws IOException {
180         super();
181         this.out = initWriter(file, encoding, append);
182     }
183 
184     /**
185      * Constructs a FileWriterWithEncoding with a file encoding.
186      *
187      * @param file  the file to write to, not null
188      * @param encoding  the encoding to use, not null
189      * @throws NullPointerException if the file or encoding is null
190      * @throws IOException in case of an I/O error
191      */
FileWriterWithEncoding(File file, CharsetEncoder encoding)192     public FileWriterWithEncoding(File file, CharsetEncoder encoding) throws IOException {
193         this(file, encoding, false);
194     }
195 
196     /**
197      * Constructs a FileWriterWithEncoding with a file encoding.
198      *
199      * @param file  the file to write to, not null
200      * @param encoding  the encoding to use, not null
201      * @param append  true if content should be appended, false to overwrite
202      * @throws NullPointerException if the file or encoding is null
203      * @throws IOException in case of an I/O error
204      */
FileWriterWithEncoding(File file, CharsetEncoder encoding, boolean append)205     public FileWriterWithEncoding(File file, CharsetEncoder encoding, boolean append) throws IOException {
206         super();
207         this.out = initWriter(file, encoding, append);
208     }
209 
210     //-----------------------------------------------------------------------
211     /**
212      * Initialise the wrapped file writer.
213      * Ensure that a cleanup occurs if the writer creation fails.
214      *
215      * @param file  the file to be accessed
216      * @param encoding  the encoding to use - may be Charset, CharsetEncoder or String
217      * @param append  true to append
218      * @return the initialised writer
219      * @throws NullPointerException if the file or encoding is null
220      * @throws IOException if an error occurs
221      */
initWriter(File file, Object encoding, boolean append)222      private static Writer initWriter(File file, Object encoding, boolean append) throws IOException {
223         if (file == null) {
224             throw new NullPointerException("File is missing");
225         }
226         if (encoding == null) {
227             throw new NullPointerException("Encoding is missing");
228         }
229         boolean fileExistedAlready = file.exists();
230         OutputStream stream = null;
231         Writer writer = null;
232         try {
233             stream = new FileOutputStream(file, append);
234             if (encoding instanceof Charset) {
235                 writer = new OutputStreamWriter(stream, (Charset)encoding);
236             } else if (encoding instanceof CharsetEncoder) {
237                 writer = new OutputStreamWriter(stream, (CharsetEncoder)encoding);
238             } else {
239                 writer = new OutputStreamWriter(stream, (String)encoding);
240             }
241         } catch (IOException ex) {
242             IOUtils.closeQuietly(writer);
243             IOUtils.closeQuietly(stream);
244             if (fileExistedAlready == false) {
245                 FileUtils.deleteQuietly(file);
246             }
247             throw ex;
248         } catch (RuntimeException ex) {
249             IOUtils.closeQuietly(writer);
250             IOUtils.closeQuietly(stream);
251             if (fileExistedAlready == false) {
252                 FileUtils.deleteQuietly(file);
253             }
254             throw ex;
255         }
256         return writer;
257     }
258 
259     //-----------------------------------------------------------------------
260     /**
261      * Write a character.
262      * @param idx the character to write
263      * @throws IOException if an I/O error occurs
264      */
write(int idx)265     public void write(int idx) throws IOException {
266         out.write(idx);
267     }
268 
269     /**
270      * Write the characters from an array.
271      * @param chr the characters to write
272      * @throws IOException if an I/O error occurs
273      */
write(char[] chr)274     public void write(char[] chr) throws IOException {
275         out.write(chr);
276     }
277 
278     /**
279      * Write the specified characters from an array.
280      * @param chr the characters to write
281      * @param st The start offset
282      * @param end The number of characters to write
283      * @throws IOException if an I/O error occurs
284      */
write(char[] chr, int st, int end)285     public void write(char[] chr, int st, int end) throws IOException {
286         out.write(chr, st, end);
287     }
288 
289     /**
290      * Write the characters from a string.
291      * @param str the string to write
292      * @throws IOException if an I/O error occurs
293      */
write(String str)294     public void write(String str) throws IOException {
295         out.write(str);
296     }
297 
298     /**
299      * Write the specified characters from a string.
300      * @param str the string to write
301      * @param st The start offset
302      * @param end The number of characters to write
303      * @throws IOException if an I/O error occurs
304      */
write(String str, int st, int end)305     public void write(String str, int st, int end) throws IOException {
306         out.write(str, st, end);
307     }
308 
309     /**
310      * Flush the stream.
311      * @throws IOException if an I/O error occurs
312      */
flush()313     public void flush() throws IOException {
314         out.flush();
315     }
316 
317     /**
318      * Close the stream.
319      * @throws IOException if an I/O error occurs
320      */
close()321     public void close() throws IOException {
322         out.close();
323     }
324 }
325