View Javadoc
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 static org.apache.commons.io.test.TestUtils.checkFile;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.io.File;
27  import java.io.FileWriter;
28  import java.io.IOException;
29  import java.io.OutputStreamWriter;
30  import java.io.Writer;
31  import java.nio.charset.Charset;
32  import java.nio.charset.CharsetEncoder;
33  import java.nio.charset.StandardCharsets;
34  import java.nio.file.Files;
35  
36  import org.junit.jupiter.api.BeforeEach;
37  import org.junit.jupiter.api.Test;
38  import org.junit.jupiter.api.io.TempDir;
39  
40  /**
41   * Tests {@link FileWriterWithEncoding}.
42   */
43  public class FileWriterWithEncodingTest {
44  
45      @TempDir
46      public File temporaryFolder;
47  
48      private String defaultEncoding;
49      private File file1;
50      private File file2;
51      private String textContent;
52      private final char[] anotherTestContent = {'f', 'z', 'x'};
53  
54      @BeforeEach
55      public void setUp() throws Exception {
56          final File encodingFinder = new File(temporaryFolder, "finder.txt");
57          try (OutputStreamWriter out = new OutputStreamWriter(Files.newOutputStream(encodingFinder.toPath()))) {
58              defaultEncoding = out.getEncoding();
59          }
60          file1 = new File(temporaryFolder, "testfile1.txt");
61          file2 = new File(temporaryFolder, "testfile2.txt");
62          final char[] arr = new char[1024];
63          final char[] chars = "ABCDEFGHIJKLMNOPQabcdefgihklmnopq".toCharArray();
64          for (int i = 0; i < arr.length; i++) {
65              arr[i] = chars[i % chars.length];
66          }
67          textContent = new String(arr);
68      }
69  
70      private void successfulRun(final FileWriterWithEncoding fw21) throws Exception {
71          try (FileWriter fw1 = new FileWriter(file1); // default encoding
72              FileWriterWithEncoding fw2 = fw21) {
73              writeTestPayload(fw1, fw2);
74              checkFile(file1, file2);
75          }
76          assertTrue(file1.exists());
77          assertTrue(file2.exists());
78      }
79  
80      @Test
81      public void testConstructor_File_directory() {
82          assertThrows(IOException.class, () -> {
83              try (Writer writer = new FileWriterWithEncoding(temporaryFolder, defaultEncoding)) {
84                  // empty
85              }
86          });
87          assertFalse(file1.exists());
88          assertThrows(IOException.class, () -> {
89              try (Writer writer = FileWriterWithEncoding.builder().setFile(temporaryFolder).setCharset(defaultEncoding).get()) {
90                  // empty
91              }
92          });
93          assertFalse(file1.exists());
94      }
95  
96      @Test
97      public void testConstructor_File_encoding_badEncoding() {
98          assertThrows(IOException.class, () -> {
99              try (Writer writer = new FileWriterWithEncoding(file1, "BAD-ENCODE")) {
100                 // empty
101             }
102         });
103         assertFalse(file1.exists());
104     }
105 
106     @Test
107     public void testConstructor_File_existingFile_withContent() throws Exception {
108         try (FileWriter fw1 = new FileWriter(file1);) {
109             fw1.write(textContent);
110             fw1.write(65);
111         }
112         assertEquals(1025, file1.length());
113 
114         try (FileWriterWithEncoding fw1 = new FileWriterWithEncoding(file1, defaultEncoding)) {
115             fw1.write("ABcd");
116         }
117 
118         assertEquals(4, file1.length());
119 
120         try (FileWriterWithEncoding fw1 = FileWriterWithEncoding.builder().setFile(file1).setCharset(defaultEncoding).get()) {
121             fw1.write("ABcd");
122         }
123 
124         assertEquals(4, file1.length());
125     }
126 
127     @Test
128     public void testConstructor_File_nullFile() {
129         assertThrows(NullPointerException.class, () -> {
130             try (Writer writer = new FileWriterWithEncoding((File) null, defaultEncoding)) {
131                 // empty
132             }
133         });
134         assertFalse(file1.exists());
135     }
136 
137     @Test
138     public void testConstructor_fileName_nullFile() {
139         assertThrows(NullPointerException.class, () -> {
140             try (Writer writer = new FileWriterWithEncoding((String) null, defaultEncoding)) {
141                 // empty
142             }
143         });
144         assertFalse(file1.exists());
145     }
146 
147     @Test
148     public void testConstructorAppend_File_existingFile_withContent() throws Exception {
149         try (FileWriter fw1 = new FileWriter(file1)) {
150             fw1.write("ABcd");
151         }
152         assertEquals(4, file1.length());
153 
154         try (FileWriterWithEncoding fw1 = new FileWriterWithEncoding(file1, defaultEncoding, true)) {
155             fw1.write("XyZ");
156         }
157 
158         assertEquals(7, file1.length());
159 
160         // @formatter:off
161         try (FileWriterWithEncoding fw1 = FileWriterWithEncoding.builder()
162                 .setFile(file1)
163                 .setCharset(defaultEncoding)
164                 .setAppend(true)
165                 .get()) {
166             fw1.write("XyZ");
167         }
168         // @formatter:on
169 
170         assertEquals(10, file1.length());
171     }
172 
173     @Test
174     public void testDifferentEncoding() throws Exception {
175         if (Charset.isSupported(StandardCharsets.UTF_16BE.name())) {
176             try (FileWriter fw1 = new FileWriter(file1); // default encoding
177                 FileWriterWithEncoding fw2 = new FileWriterWithEncoding(file2, defaultEncoding)) {
178                 writeTestPayload(fw1, fw2);
179                 try {
180                     checkFile(file1, file2);
181                     fail();
182                 } catch (final AssertionError ex) {
183                     // success
184                 }
185 
186             }
187             assertTrue(file1.exists());
188             assertTrue(file2.exists());
189         }
190         if (Charset.isSupported(StandardCharsets.UTF_16LE.name())) {
191             try (FileWriter fw1 = new FileWriter(file1); // default encoding
192                 FileWriterWithEncoding fw2 = new FileWriterWithEncoding(file2, defaultEncoding)) {
193                 writeTestPayload(fw1, fw2);
194                 try {
195                     checkFile(file1, file2);
196                     fail();
197                 } catch (final AssertionError ex) {
198                     // success
199                 }
200 
201             }
202             assertTrue(file1.exists());
203             assertTrue(file2.exists());
204         }
205     }
206 
207     @Test
208     public void testSameEncoding_Charset_constructor() throws Exception {
209         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, Charset.defaultCharset())) {
210             successfulRun(writer);
211         }
212         // @formatter:off
213         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder()
214                 .setFile(file2)
215                 .setCharset(Charset.defaultCharset())
216                 .get()) {
217             successfulRun(writer);
218         }
219         // @formatter:on
220     }
221 
222     @Test
223     public void testSameEncoding_CharsetEncoder_constructor() throws Exception {
224         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, Charset.defaultCharset().newEncoder())) {
225             successfulRun(writer);
226         }
227         // @formatter:off
228         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder()
229                 .setFile(file2)
230                 .setCharsetEncoder(Charset.defaultCharset().newEncoder())
231                 .get()) {
232             successfulRun(writer);
233         }
234         // @formatter:on
235     }
236 
237     @Test
238     public void testSameEncoding_null_Charset_constructor() throws Exception {
239         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, (Charset) null)) {
240             successfulRun(writer);
241         }
242     }
243 
244     @Test
245     public void testSameEncoding_null_CharsetEncoder_constructor() throws Exception {
246         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), (CharsetEncoder) null)) {
247             successfulRun(writer);
248         }
249         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder().setFile(file2.getPath()).get()) {
250             successfulRun(writer);
251         }
252         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder().setFile(file2.getPath()).setCharsetEncoder(null).get()) {
253             successfulRun(writer);
254         }
255     }
256 
257     @Test
258     public void testSameEncoding_null_CharsetName_constructor() throws Exception {
259         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), (String) null)) {
260             successfulRun(writer);
261         }
262     }
263 
264     @Test
265     public void testSameEncoding_string_Charset_constructor() throws Exception {
266         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), Charset.defaultCharset())) {
267             successfulRun(writer);
268         }
269         // @formatter:off
270         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder()
271                 .setFile(file2.getPath())
272                 .setCharset(Charset.defaultCharset())
273                 .get()) {
274             successfulRun(writer);
275         }
276         // @formatter:on
277     }
278 
279     @Test
280     public void testSameEncoding_string_CharsetEncoder_constructor() throws Exception {
281         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), Charset.defaultCharset().newEncoder())) {
282             successfulRun(writer);
283         }
284     }
285 
286     @Test
287     public void testSameEncoding_string_constructor() throws Exception {
288         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2, defaultEncoding)) {
289             successfulRun(writer);
290         }
291     }
292 
293     @Test
294     public void testSameEncoding_string_string_constructor() throws Exception {
295         try (FileWriterWithEncoding writer = new FileWriterWithEncoding(file2.getPath(), defaultEncoding)) {
296             successfulRun(writer);
297         }
298         // @formatter:off
299         try (FileWriterWithEncoding writer = FileWriterWithEncoding.builder()
300                 .setFile(file2.getPath())
301                 .setCharset(defaultEncoding)
302                 .get()) {
303             successfulRun(writer);
304         }
305         // @formatter:on
306     }
307 
308     private void writeTestPayload(final FileWriter fw1, final FileWriterWithEncoding fw2) throws IOException {
309         assertTrue(file1.exists());
310         assertTrue(file2.exists());
311 
312         fw1.write(textContent);
313         fw2.write(textContent);
314         fw1.write(65);
315         fw2.write(65);
316         fw1.write(anotherTestContent);
317         fw2.write(anotherTestContent);
318         fw1.write(anotherTestContent, 1, 2);
319         fw2.write(anotherTestContent, 1, 2);
320         fw1.write("CAFE", 1, 2);
321         fw2.write("CAFE", 1, 2);
322 
323         fw1.flush();
324         fw2.flush();
325     }
326 }