i'mhungry
i'mhungry

Reputation: 649

OutputStreamWriter vs FileWriter

I don't understand the difference between these two classes. When would you use one over the one? I know that FileWriter can output characters to a file but so can OutputStreamWriter as far as i know. Here is some code that i tested and they seem to work the same, i'm not adding the exception handling stuff but lets just assume its there.

FileWriter writer = new FileWriter("C:\\Users\\owner\\Desktop\\demo.txt");
writer.write("hello");
writer.close();

I also tried this code:

File file = new File("C:\\Users\\owner\\Desktop\\demo.txt");
os = new OutputStreamWriter(new FileOutputStream(file));
os.write("hello");
os.close();

Both of these seem to work the same for me. The only time something strange happens is when i try to put an int value in the write() method. For the FileWriter example, my demo.txt is completely empty. For the OutputStreamWriter example i get some weird symbols in my text file. I am reading a java book and the only explanation i get for OutputStreamWriter is that it "converts a stream of characters to a stream of bytes" so shouldn't i be seeing some bytes in my text file in the second example?

Some clarification would be greatly appreciated.

Upvotes: 31

Views: 62790

Answers (4)

user949300
user949300

Reputation: 15729

XXXInputStream and XXXOutputStream (where XXX varies, there's a lot of options) deal with 8-bit bytes. For example, OutputStream.write(byte[] c);

XXXWriter or XXXReader deal with 16-bit chars. For example, Reader.read(char[] cbuf).

OutputStreamWriter converts an OutputStream to a Writer. As you may have guessed, InputStreamReader converts from an InputStream to a Reader. I am unaware of any classes that do the reverse, i.e. convert a Reader to an InputStream.

FileWriter is a Writer that talks to files. Since a Java String internally uses chars (16 bit so they can handle Unicode), FileWriter is the natural class for use with Unicode Strings.

FileOutputStream is an OutputStream for writing bytes to a file. OutputStreams do not accept chars (or Strings). By wrapping it in an OutputStreamWriter you now have a Writer, which does accept Strings.

Now, the real question, is when do you use a Reader/Writer and when a Stream? I've used Java for years and sometimes I get confused too. I believe the following to be correct:

Handy Guide - How to Decide Which to use:

  1. If you are dealing with binary data (e.g. an image) use Streams.
  2. If you are using non-ASCII Unicode characters, e.g. Chinese, use Readers/Writers.
  3. If you are using ordinary ASCII text (the traditional 0-127 characters) you can (usually) use either.

Some other links:

inputstream and reader in Java IO

InputStream vs InputStreamReader

Upvotes: 52

kisp
kisp

Reputation: 6552

If you want to change the encoding, use OutputStreamWriter instead of a FileOutputStream. FileOutputStream is a convinient class for writing character files. It uses default encoding.

Force encoding to UTF-8 as the following:

OutputStreamWriter osw = new OutputStreamWriter(
    new FileOutputStream(exportPath),
    Charset.forName("UTF-8").newEncoder() 
);

Upvotes: 2

oxc
oxc

Reputation: 687

There is actually no difference per se, FileWriter is just a convenience class. It extends OutputStreamWriter and creates the needed FileOutputStream itself.

Regarding write(int): that method writes a single character with the specified codepoint to the stream, it does not write a textual representation of the numeric value.

As for the empty file, note that you should always flush the buffer when you want the things you've written flushed to the underlying store (be it a file or a network stream or whatever you can think of). Simply call os.flush() after writing, that should do it.
EDIT: As Thilo has correctly mentioned, closing the stream should already flush it (and all underlying streams).

And last but not least, you should nearly always explicitly specify the charset/encoding you want your Writer to write in. Writers write characters, while OutputStreams write bytes, so you have to specify how those characters should be encoded into bytes. If you don't specify an encoding, the system default gets used, which may not be what you want.

Upvotes: 14

Lalith
Lalith

Reputation: 365

This is from here

In java.io you either do byte IO or character IO. Byte IO can be used for any form of data without any interpretation of what that data represents. Character IO is meant for, well, information that is represented as sequences of characters.

For byte IO we have various types of InputStream/OutputStream classes like the FileOutputStream from your example 1). For character data whe have various forms of Reader/Writer classes like the FileWriter from your example. Buffering can be done in both cases, hence the BufferedWriter and BufferedOutputStream classes.

To do character IO characters will at some point have to be converted to byte data using some form of encoding. FileWriter does that for you, which is why it has a constructor that takes the encoding along with the file name. Common encodings include UTF-8, UTF-16 and US-ASCII.

OutputStreamWriter is a class that only does the encoding of characters. That is why it is a Writer and its constructor takes an OutputStream as parameter with an optional encoding parameter.

If you omit the explicit encoding specifications both FileWriter and ByteArrayOutputStream will use the default encoding for your platform. This is something to be very careful with since it will vary among different JVMs.

Upvotes: 3

Related Questions