Reputation: 2019
There are many different classes in the IO package, some seems to only have suble differences. If you are to write some Strings to a text file, and read them for later use. Which classes would you use for each of those two purposes and why?
Upvotes: 5
Views: 1680
Reputation:
It all depends on what you want to do.
Output Streams
In case you want to write byte data, you would use some subclass of OutputStream
that is used to write bytes in destination defined by concrete subclass.
For example FileOutputStream
is used to write data in file byte by byte (or bunch of bytes).
BufferedOutputStream
is an optimized extension of FileOutputStream
to write blocks of bytes to minimize number of disk operations. So when you call write, actually it may or may not be written in file - depends on buffer's state whether it is full or not. If buffer reaches it's max capacity, all bytes are flushed to file at once.
ByteArrayOutputStream
is using just block of memory as a destination instead of file. Current stream content is obtained via toByteArray()
method (why would you need such a stream will be explained later).
ObjectOutputStream
is used to write objects (class instances) in some destination defined by the underlying OutputStream
. For example, ObjectOutputStream(FileOutputStream)
would write an objects in file, while ObjectOutputStream(ByteArrayOutputStream)
would write an objects in memory. The last option allows you to serialize objects in byte buffer (array of bytes) which can be then send somewhere via network.
Note, that any object you want to write somewhere via ObjectOutputStream
has to implement Serializable
interface. Since object may contain references to another objects, all the objects that are accessible from the object to be serialized also has to implement Serializable
interface as serialization, by default, is process of writting of full graph of objects - assuming you are not using transient
keyword to exclude class field from serialization, or you are not defining at object's class a special methods writeObject/readObject
that overrides default serialization behaviour. These methods are designed to implement custom serialization i. e. you can define on your own how to write/read class field in/from ObjectOutputStream/ObjectInputStream
. Suppose class A
for which you are implementing custom serialization contains an object of class B
. Instead of writting object b
as a full graph, i. e. instead of calling oos.writeObject(b)
, where oos
is an argument of the writeObject
method being implemented in class A
, you would write in stream only some fields of class B
e. g. oos.writeBoolean(b.isEnabled)
, oos.writeInt(b.value)
. As long as object b
is not written via oos.writeObject(b)
, it does not have to implement Serializable
interface. For more details see Serializable
documentation.
DataOutputStream
is used to write primitives like boolean, char, int, long, float, double. Since any object can be decomposed to primitives e. g. class A { int i = 0; B b = new B();}
, class B {double d = 0.0;}
can be written simply as int a, double d
, you can use DataOutputStream
to serialize objects in compressed way unlike serialization which writes much more data e. g. class path, class version, ... so ClassLoader
can identify a given class in runtime, instantiate this class and finally load data to this empty object. Note that instantiating class by it's name + initialising object in this way is much slower than instantiating class on your own and initializing it's fields on your own from "raw" DataOutputStream
(that's why OS Android prefers custom Parcelable
interface over standard serialization, which works as writting/reading to/from DataOutputStream/DataInputStream
).
In case you want to write string data, you would use OutputStreamWriter
a higher level of output-stream which writes characters/Strings in destination defined by OutputStream
(in case of writting in file, you would pass FileOutputStream
, in case of writtin in memory you would pass ByteArrayOutputStream
).
FileWriter
is an extension of OutputStreamWriter
designed for writting in file.
BufferedWriter
works the same as BufferedOutputStream
except it is designed for work with strings and characters.
CharArrayWriter
works the same as ByteArrayOutputStream
except characters are stored in char[]
which is obtained by calling getCharArray()
.
StringWriter
is similar to CharArrayWriter
except it allows you to write strings which are stored in StringBuffer
that is obtained by calling getBuffer()
.
PrintWriter
allows you to write formatted strings in specified destination defined by OutputStream
(this writer is designed for easy logging).
Input Streams
The same concept is applied to input-streams (readers) associated with given output-streams (writers) mentioned above.
Upvotes: 6
Reputation: 25524
So for your specific case you want to write text to a file, the most obvious candidate is a FileWriter:
Writer out = new FileWriter(
new File("foo.txt")
);
If you want better performance for making many small writes to it, you could wrap it in a buffer:
Writer out = new BufferedWriter(
new FileWriter(
new File("foo.txt")
)
);
The FileWriter assumes the default character encoding when writing text. If you want to choose the encoding, or ensure that it is consistent on all platforms, you could create the writer from an OutputStream specifying the encoding explicitly:
Writer out = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File("foo.txt")
), "UTF-8"
)
);
Upvotes: 4