Files
GTSchoolShit/CS1322/p3/IOHelp.txt
2025-06-07 01:59:34 -04:00

134 lines
6.8 KiB
Plaintext

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.