41

I have the following code and I want to make the outputstream use utf-8. Basically I have characters like é that appear as é so it looks like an encoding issue.

I've seen lots of examples that use...

OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(path),"UTF-8");

My current code though is...

BufferedWriter out = new 
BufferedWriter(new FileWriter(DatabaseProps.fileLocation + "Output.xml"));

Is it possible to define this object as UTF-8 without having to use the OutputStreamWriter?

Thanks,

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
David
  • 19,577
  • 28
  • 108
  • 128

4 Answers4

148

No. FileWriter doesn't let you specify the encoding, which is extremely annoying. It always uses the system default encoding. Just suck it up and use OutputStreamWriter wrapping a FileOutputStream. You can still wrap the OutputStreamWriter in a BufferedWriter of course:

BufferedWriter out = new BufferedWriter
    (new OutputStreamWriter(new FileOutputStream(path), StandardCharsets.UTF_8));

Or as of Java 8:

BufferedWriter out = Files.newBufferedWriter(Paths.of(path));

(Of course you could change your system default encoding to UTF-8, but that seems a bit of an extreme measure.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Hmm, I did that but I still get é for é. Does that mean the issue is earlier in the stack? In the db it's stored as é but when I connect with jdbc:sqlserver://...... it writes the found field as é in my file. The string is not intentionally being changed in anyway. – David Aug 09 '11 at 15:52
  • @david99world: It's not clear what you mean, but nothing in the code you've shown is going to be creating XML/HTML entities for you. It does indeed sound like the problem is somewhere else. I'm sure you'll already have the `é` in your string before you write it to the buffered writer. – Jon Skeet Aug 09 '11 at 16:07
  • 2
    The problem might that the program you are using to read your file is not configured for utf-8. – toto2 Aug 09 '11 at 16:09
  • 2
    Ah, thank you very much, I wasn't aware this had to be configured at read as well as write, thank you :) – David Aug 09 '11 at 19:07
  • For future readers, Apache Commons IO [FileWriterWithEncoding](https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/output/FileWriterWithEncoding.html) is also an option – Chris Riddell Jun 01 '15 at 23:17
  • 6
    @Chris: Well these days I'd just use Files.newBufferedWriter - no need for a third party lib. – Jon Skeet Jun 02 '15 at 05:22
5

You can use improved FileWriter, improved by me.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;

/**
 * Created with IntelliJ IDEA.
 * User: Eugene Chipachenko
 * Date: 20.09.13
 * Time: 10:21
 */
public class BufferedFileWriter extends OutputStreamWriter
{
  public BufferedFileWriter( String fileName ) throws IOException
  {
    super( new FileOutputStream( fileName ), Charset.forName( "UTF-8" ) );
  }

  public BufferedFileWriter( String fileName, boolean append ) throws IOException
  {
    super( new FileOutputStream( fileName, append ), Charset.forName( "UTF-8" ) );
  }

  public BufferedFileWriter( String fileName, String charsetName, boolean append ) throws IOException
  {
    super( new FileOutputStream( fileName, append ), Charset.forName( charsetName ) );
  }

  public BufferedFileWriter( File file ) throws IOException
  {
    super( new FileOutputStream( file ), Charset.forName( "UTF-8" ) );
  }

  public BufferedFileWriter( File file, boolean append ) throws IOException
  {
    super( new FileOutputStream( file, append ), Charset.forName( "UTF-8" ) );
  }

  public BufferedFileWriter( File file, String charsetName, boolean append ) throws IOException
  {
    super( new FileOutputStream( file, append ), Charset.forName( charsetName ) );
  }
}
3

As the documentation for FileWriter explains,

The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.

There's no reason you can't construct your BufferedWriter on top of the OutputStreamWriter though.

Richard Campbell
  • 3,591
  • 23
  • 18
1

Use the method, Files.newBufferedWriter(Path path, Charset cs, OpenOption... options)

As requested by Toby, here is the sample code.

String errorFileName = (String) exchange.getIn().getHeader(HeaderKey.ERROR_FILE_NAME.getKey());
        String errorPathAndFile = dir + "/" + errorFileName;
        writer = Files.newBufferedWriter(Paths.get(errorPathAndFile),  StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW);
        try {
            writer.write(MESSAGE_HEADER + "\n");
        } finally {
            writer.close();
        }
Pijush
  • 417
  • 5
  • 3
  • While this might be a valuable hint to solve the problem, a good answer also demonstrates the solution. Please [edit] to provide example code to show what you mean. Alternatively, consider writing this as a comment instead. – Toby Speight Jul 04 '18 at 12:34