System.out
which is a static
object in the System
class. System.out
is used
to print output to the screen, and is actually an instance of the
PrintStream
class. The location the computer prints to when
using System.out
is referred to as standard out, and
is often abbreviated as stdout.
Another PrintStream
object given us is
System.err
(pronounced "System dot error"). This object is
used to print information to standard error (often abbreviated
stderr). Your computer differentiates between standard error and standard
out (System.out
), even though whatever you print to standard
error goes to the screen, just like standard out. Because
System.err
is a PrintStream
object just like
System.out
, you can use the same methods with it that you can
use with System.out
The System
class also gives us a stream for reading input
from the user. This stream is called System.in
and is often
referred to as "standard in" (stdin). System.in
is an
instance of
the InputStreamClass
. We discuss how to use standard in
next.
BufferedReader
System.out
and System.err
, it is not
possible to use System.in
directly. Instead, you must create
an object which uses standard in. This object you will use is an instance
of the BufferedReader
class, and is typically created like
this:
BufferedReader stdin = new BufferedReader(new
InputStreamReader(System.in));
The BufferedReader
is defined in the java.io
package, so you must remember to import
it before you use a
BufferedReader
.
What the declaration above is actually doing is creating a class capable
of reading from stdin in a convenient manner. System.in reads things from
the keyboard as a stream of bytes, which can be converted to something
more useful by the InputStreamReader
, which is then converted
to a String
by the BufferedReader
. You should
be familiar with working with String
s at this point.
Reading text with stdin
To actually read input from the keyboard, it is necessary to call the
readLine()
method defined in the BufferedReader
class. The readLine()
method returns a String
.
When this method is called by your Java program, the method does not
return until the user hits the "enter" key. When this happens, the
program can continue with the statements immediately following the call to
readLine()
.
Reading data from the keyboard is buffered (hence
BufferedReader
) this means that as you type things into
the keyboard, each keystroke you make is stored in a temporary place,
referred to as a buffer. When you hit enter, this buffer is cleaned
out and your program may continue. Because the input is buffered, it
is possible to correct mistakes. If you type something incorrectly,
you can fix your mistake using the backspace key. The buffer is
updated accordingly.
Dealing with Exceptions
If only reading from the stdin were that easy. It is possible for
there to be a problem with your stdin that would cause your readLine()
to fail. If that happens, Java will tell you about the problem in the
manner it always lists problems: by issuing an Exception. The type of
issue exception issued in this case is known as a
IOException
. This is a different kind of exception than
what we've seen before (like
ArrayIndexOutOfBoundsException
or
FishOutOfWaterException
. An IOException
is
known as a checked exception. This differs from the other
exceptions we have seen (unchecked exceptions), which we always
ignored and allowed to crash our program. Checked exceptions must be
dealt with at compile time. For now we will also ignore the
IOException, but we have to ignore it in a special way: we
have to include a "throws" clause in our method header. That is, if
we are using the
readLine()
method in a method we define,
we have to include the phrase throws IOException
as the
last part of our method header:
public static void main(String [] args) throws IOException {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
....
stdin.readLine();
....
}
When we ignore an exception, what we are actually doing is passing the
buck: we will let the method which called the method which caused the
exception deal with the exception. However, if we are ignoring a
checked exception, this calling method must also ignore the methods by
using a throws
clause. For example, we have
funcA()
which calls funcB()
, which calls
readLine()
:
void funcA() throws IOException { ... funcB(); ... } void funcB() throws IOException { ... stdin.readLine(); ... }
Exceptions will be discussed more later.
Example:Echo.java.
Converting String
s to primitive data
You can only use the readLine()
method to read in a
String
. Suppose, however, you wanted to read in a
number from the user. You may accomplish by using the wrapper
classes. A wrapper class is a class used to represent a specific
primitive data type. There are wrapper classes for all of the
primitive data types. The two most frequently used are
Integer
and Double
. These classes provide
static methods to convert a String
to the corresponding
primitive type. The two methods are summarized below:
int Integer.parseInt(String str) |
Converts str to its corresponding
int value. |
double Double.parseDouble(String str) |
Converts str to its corresponding
double value. |
Example:Donuts7.java
If the String
being converted is not truly a
String
representation of a number, Java complains by
issuing a NumberFormatException
, which is another
unchecked exception (there is no need for a throws
clause).
File
defined in
java.io.
. You then represent a file by creating an
instance of this class.
There are many useful methods in the File
class. A few
are summarized below:
File(String fileName) | Creates a new File object to represent a file on
your computer. The fileName is the name of the file
to be represented. |
boolean exists() |
Returns true if the file represented by this File
actually exists, false otherwise |
boolean isFile() |
Returns true if the File represents a file, false
otherwise (for instance, if the file does not exist, or this
File is actually a directory) |
boolean isDirectory() |
Returns true if this File object is representing
a directory, false otherwise. |
boolean canRead() |
Returns true if you have permission to read the file
represented by this File object, false
otherwise |
boolean canWrite() |
Returns true if you have permission to write the file
represented by this File object, false
otherwise |
BufferedReader
to do the reading. However, instead of an
InputStreamReader
a FileReader
is used. The
FileReader
class is defined in java.io
. The
FileReader
object also takes a parameter: the
File
object which is to be read from. Hence, creating an
object which can read a text file called "foo.txt" would look like this:
BufferedReader fin = new BufferedReader(new FileReader(new File("foo.txt")));
It is also possible to skip the process of creating a
File
object, and use the name of the file to initialize
the FileReader
:
BufferedReader fin = new BufferedReader(new FileReader("foo.txt"));
Once the BufferedReader
has been initialized, it is
possible to use readLine()
to read a line of text from
the file.
More exceptions
Creating the BufferedReader
as we did above may cause a checked exception to occur: if the file
does not exist, a FileNotFoundException
is issued.
Because this is a checked exception, it must be dealt with as well. We do so the same way we dealt with IOException
s: by specifying we are ignoring the exception in our throws
clause:
public static void main(String [] args) throws IOException, FileNotFoundException {
throws
clause, separating each by commas.
Actually, in this case, it is not necessary to specify types of
exceptions: a FileNotFoundException
is a sub-class of
IOException
, so ignoring the IOException
covers ignoring the FileNotFoundException
.
More BufferedReader
methods
Quite often when we perform file input, we want to process all of the
lines of the file. That is, we want to read over and over again.
That shouldn't be too hard to implement: just place your call to
readLine()
in a while
loop. Ah, but there
is a problem: how do we know when to terminate the loop? The
BufferedReader
class provides a method to tell us when
there is no more data to be read. This method is called
ready()
, and returns a boolean: true if there is more
lines of data in the file, false otherwise.
Another useful method provided by the BufferedReader
class is the close()
method, which closes our buffer when
we are done reading from it. We should always close the
BufferedReader
when we are finished with it: your
operating system can only have so many files open at a time. By
closing the buffer when finished, this may allow a different program
to open a file.
Both of the above methods may also issue an IOException
.
Example:DisplayFile.java
More about buffers
We discussed why using a buffer when reading from stdin was a good
thing. Why is it necessary for reading from a file? Consider this:
reading from a disk is a very time consuming process because of the
way disks are set up. It is possible for a read of a line of text
from on a disk to take several milliseconds. This may not seem to
time consuming, but when you consider it will likely take on the order
of microseconds to process that line of text, several milliseconds is
quite a long time!
Java takes advantage of the way disks work to help speed up the
process. The way hard disks are set up, it often takes roughly the
same amount of time to read 3 bytes from the disk as it takes to read
1 kb. Thus, when a call to readLine()
is made, several
lines of text are read and stored in a buffer, which is then stored in
your computer's main memory. Thus, subsequent calls to
readLine()
will read the data from this buffer (which is
much faster) rather than from the disk.
PrintWriter
object, which needs a FileWriter
object, which needs a File
object. That is, to write to a file called "foo.txt",
we would need the following:
PrintWriter fout = new PrintWriter(new FileWriter(new File("foo.txt")));
Note that it is also possible to pass the file name directly to the
FileWriter
object instead of first creating a File
object. Also, if there is already a file of the same name, the old
data in the file will be overwritten and lost. Finally, creating this
object could cause an IOException
, so you must remember
to have a throws
clause in your method header.
Now that a FileWriter
object has been created, it is
possible to write text information to it. The methods needed to write
information are print()
and println()
, which
are used the exact same way the are used with System.out
.
These methods take all data types, and converts them to text before
writing the information to a file.
When all of the data has been written to the file, it is also
necessary to call close()
on your file. This is to
insure that all data is written to the file: just like a
BufferedReader
used a buffer to speed things up, the
PrintWriter
uses a buffer as well. When a call to
println()
is made, the data to be written is stored in a
buffer to be written out later. Calling close()
causes
all of the data in the buffer to be written to disk.
Example:Copy.java