first commit
This commit is contained in:
134
CS1322/p3/IOHelp.txt
Normal file
134
CS1322/p3/IOHelp.txt
Normal file
@@ -0,0 +1,134 @@
|
||||
This is a walkthrough of how to use File I/O. It will give a walkthrough of
|
||||
how to read from standard in, and how to read from and write to files.
|
||||
|
||||
|
||||
WRITING AND READING TO FILES
|
||||
============================================================================
|
||||
|
||||
/O stands for "input and output." File I/O is reading from or writing to
|
||||
files on the disk. It should be noted that java treats network
|
||||
sockets like files as far as IO goes, like UNIX does. Although networking
|
||||
is not covered in this class, it is quite similar to accessing files on
|
||||
the disk. The standard input, standard error, and standard output are
|
||||
also very similar to files, and in fact the types for these three streams
|
||||
are found in java.io, along with the classes to perform other file operations.
|
||||
|
||||
There are many slight variations in what needs to be done to perform
|
||||
File IO depending on what type of file is being dealt with and what needs
|
||||
to be done with it. We will first focus our attention on reading lines from
|
||||
a text file. The first thing that we should do is open the file in a
|
||||
FileReader (Note that we are creating a FileReader object):
|
||||
|
||||
FileReader fr= new FileReader("myFile.txt");
|
||||
|
||||
The next thing that we should do is to wrap the FileReader in a
|
||||
BufferedReader:
|
||||
|
||||
BufferedReader br= new BufferedReader(fr);
|
||||
|
||||
This code creates a BufferedReader which will ask fr what is in the file
|
||||
and return it to the program line by line.
|
||||
|
||||
The designers of Java decided to use this wrapper class concept to allow a
|
||||
lot of flexibility without having to create hundreds of different classes.
|
||||
Sometimes people will accomplish the above in one statement where perhaps
|
||||
the "wrapper" idea will be more obvious:
|
||||
|
||||
BufferedReader has, among other methods, the method
|
||||
|
||||
String readLine()
|
||||
|
||||
which returns the next line of text from the file without the '\n' on the
|
||||
end- this method also automatically goes to the next line, so the next
|
||||
call to readLine() will give the next line, not the same one. When
|
||||
the program is done reading from the file, it should call the close method
|
||||
on the BufferedReader (which will close the underlying FileReader) so
|
||||
that the associated file resources may be freed (note that while
|
||||
memory is garbage collected, other resources, such as file descriptors
|
||||
are not). The above code, must of course have the exceptions dealt with
|
||||
properly, but that will be discussed in a minute.
|
||||
|
||||
The other major operation that we will concern ourselves with is writing
|
||||
lines of text to a file. This can be accomplished similarly via the
|
||||
use of the FileWriter and PrintWriter classes:
|
||||
|
||||
FileWriter fr=new FileWriter("output.txt");
|
||||
PrintWriter pr= new PrintWriter(fr);
|
||||
|
||||
The PrintWriter class has print() and println() methods which are overloaded
|
||||
to accept just about any paramter type and write it to the underlying
|
||||
FileWriter. It should be noted that print and println do NOT throw
|
||||
exceptions if a problem occurs while writing to the underlying file-
|
||||
instead, they just set an error variable in the PrintWriter instance,
|
||||
which may be checked with the checkError() method. The FileWriter class,
|
||||
may throw an exception when created, as described later. The PrintWriter
|
||||
must also be closed when the program is finished with it. If an output
|
||||
stream in not closed, then not only will the resources not be freed,
|
||||
but also, the data will never actually be written out to the disk,
|
||||
as it is buffered in memory, and flushed only when a certain amount
|
||||
is present, or the close() or flush() method gets called.
|
||||
|
||||
So why do we need to deal with these extra classes? Why can't we
|
||||
just have one class to do it all? And how do these classes interact?
|
||||
|
||||
Each class does a specific job and provides a certain ammount of modularity
|
||||
and abstraction. Lets look at the FileReader and BufferedReader:
|
||||
|
||||
FileReader- has the job of reading characters from a file and
|
||||
assumes that the characters use default encoding.
|
||||
|
||||
BufferedReader- has the job of reading text from a character-input stream,
|
||||
buffering characters so as to provide for the efficient
|
||||
reading of characters, arrays, and lines.
|
||||
|
||||
there are other classes that could be put into a BufferedReader, for example,
|
||||
an InputStreamReader- which basically reads from a byte stream and converts
|
||||
to a character stream, using some encoding scheme, which may be specified.
|
||||
So for example, if the file that you wanted to read used a different Unicode
|
||||
encoding scheme than the default for your system (maybe you are writing
|
||||
some international buisness software), then you would instead need to
|
||||
make a FileInputStream, wrap that in an InputStreamReader, then wrap that
|
||||
in a BufferedReader. In general, "Stream" deals with bytes, whereas
|
||||
"Reader" deals with characters.
|
||||
|
||||
This abstraction gives the input classes more flexibility, in that
|
||||
they can also be used to allow for reading from other input streams
|
||||
than those avaiable from files on the disk- a network connection
|
||||
provides an instance of InputStream to read incoming data from
|
||||
the connection- InputStreams (as just mentioned) deal with bytes-
|
||||
if the program wants to read lines of text, for example, the same
|
||||
wrapping can be performed with the same classes to get a BufferedReader
|
||||
to give lines of text at a time from the network
|
||||
|
||||
|
||||
|
||||
WRITING AND READING OBJECTS TO FILES
|
||||
============================================================================
|
||||
Writing and reading java objects to a file are slightly different than writing
|
||||
and reading Strings to file. First off, in order for a java Object to be able
|
||||
to be written to a file, it must implement Serializable. Only classes which
|
||||
implement the Serializable interface can be written to a file as an Object.
|
||||
|
||||
To write an object to a file, you first need to create the Streams.
|
||||
The reason that you cannot use PrintWriter as you used before is because
|
||||
PrintWriter only can write Strings to a file.
|
||||
The two streams that need to be created are
|
||||
FileOutputStream and ObjectOutputStream.
|
||||
|
||||
|
||||
The constructor to FileOutputStream takes in the name of the file to write to as
|
||||
a String. If the file does not exist, it creates one.
|
||||
The constructor to ObjectOutputStream takes in the newly created
|
||||
FileOutputStream.
|
||||
After creating them, you can write the object to the ObjectOutputStream.
|
||||
If the ObjectOutputStream was called oos, then oos.writeObject(theObject);
|
||||
would write the object to file.
|
||||
After writing all object, make sure to flush the ObjectOutputStream and close
|
||||
the FileOutputStream.
|
||||
|
||||
To read objects from a file, you need to create an ObjectInputStream and a
|
||||
FileInputStream. The constructors for these work similar to the writer.
|
||||
To actually read an object, do ois.readObject(). This will need to be casted
|
||||
to the actuall object that it is. If the file does not exist, it will throw
|
||||
a FileNotFoundException. When the end of the file is reached, it throws
|
||||
an EndOfFileException.
|
||||
Reference in New Issue
Block a user