System, but they may not be reproduced for publication



Yüklə 83 Mb.
Pdf görüntüsü
səhifə48/82
tarix19.04.2023
ölçüsü83 Mb.
#106251
1   ...   44   45   46   47   48   49   50   51   ...   82
Java A Beginner’s Guide, Eighth Edition ( PDFDrive )

inputStream.
Next, using the object produced by InputStreamReader, construct a
BufferedReader using the constructor shown here:
BufferedReader(Reader inputReader)
Here, inputReader is the stream that is linked to the instance of BufferedReader
being created. Putting it all together, the following line of code creates a
BufferedReader that is connected to the keyboard.
After this statement executes, br will be a character­based stream that is linked to the
console through System.in.
Reading Characters
Characters can be read from System.in using the read( ) method defined by
BufferedReader in much the same way as they were read using byte streams. Here
are three versions of read( ) supported by BufferedReader.
int read( ) throws IOException
int read(char data[ ]) throws IOException
int read(char data[ ], int start, int max) throws IOException
The first version of read( ) reads a single Unicode character. It returns –1 when an
attempt is made to read at the end of the stream. The second version reads characters
from the input stream and puts them into data until either the array is full, the end of
stream is reached, or an error occurs. It returns the number of characters read or –1
when an attempt is made to read at the end of the stream. The third version reads input
into data beginning at the location specified by start. Up to max characters are stored.
It returns the number of characters read or –1 when an attempt is made to read at the
end of the stream. All throw an IOException on error.
The following program demonstrates read( ) by reading characters from the console
until the user types a period. Notice that any I/O exceptions that might be generated
are simply thrown out of main( ). As mentioned earlier in this chapter, such an


approach is common when reading from the console. Of course, you can handle these
types of errors under program control, if you choose.
Here is a sample run:
Reading Strings
To read a string from the keyboard, use the version of readLine( ) that is a member of
the BufferedReader class. Its general form is shown here:
String readLine( ) throws IOException
It returns a String object that contains the characters read. It returns null if an


attempt is made to read when at the end of the stream.
The following program demonstrates BufferedReader and the readLine( ) method.
The program reads and displays lines of text until you enter the word “stop”.
Console Output Using Character Streams
While it is still permissible to use System.out to write to the console under Java, its
use is recommended mostly for debugging purposes or for sample programs such as
those found in this book. For real­world programs, the preferred method of writing to
the console when using Java is through a PrintWriter stream. PrintWriter is one of
the character­based classes. As explained, using a character­based class for console
output makes it easier to internationalize your program.
PrintWriter defines several constructors. The one we will use is shown here:
PrintWriter(OutputStream outputStream, boolean flushingOn)
Here, outputStream is an object of type OutputStream and flushingOn controls
whether Java flushes the output stream every time a println( ) method (among
others) is called. If flushingOn is true, flushing automatically takes place. If false,
flushing is not automatic.


PrintWriter supports the print( ) and println( ) methods for all types including
Object. Thus, you can use these methods in just the same way as they have been used
with System.out. If an argument is not a primitive type, the PrintWriter methods
will call the object’s toString( ) method and then print out the result.
To write to the console using a PrintWriter, specify System.out for the output
stream and flush the stream after each call to println( ). For example, this line of code
creates a PrintWriter that is connected to console output.
The following application illustrates using a PrintWriter to handle console output.
The output from this program is
Remember that there is nothing wrong with using System.out to write simple text
output to the console when you are learning Java or debugging your programs.
However, using a PrintWriter will make your real­world applications easier to
internationalize. Since no advantage is to be gained by using a PrintWriter in the
sample programs shown in this book, for convenience we will continue to use
System.out to write to the console.
FILE I/O USING CHARACTER STREAMS


FILE I/O USING CHARACTER STREAMS
Although byte­oriented file handling is often the most common, it is possible to use
character­based streams for this purpose. The advantage to the character streams is
that they operate directly on Unicode characters. Thus, if you want to store Unicode
text, the character streams are certainly your best option. In general, to perform
character­based file I/O, you will use the FileReader and FileWriter classes.
Using a FileWriter
FileWriter creates a Writer that you can use to write to a file. Two commonly used
constructors are shown here:
FileWriter(String fileName) throws IOException
FileWriter(String fileName, boolean append) throws IOException
Here, fileName is the full path name of a file. If append is true, then output is
appended to the end of the file. Otherwise, the file is overwritten. Either throws an
IOException on failure. FileWriter is derived from OutputStreamWriter and
Writer. Thus, it has access to the methods defined by these classes.
Here is a simple key­to­disk utility that reads lines of text entered at the keyboard and
writes them to a file called "test.txt". Text is read until the user enters the word "stop".
It uses a FileWriter to output to the file.


Using a FileReader
The FileReader class creates a Reader that you can use to read the contents of a file.
A commonly used constructor is shown here:
FileReader(String fileName) throws FileNotFoundException
Here, fileName is the full path name of a file. It throws a FileNotFoundException if
the file does not exist. FileReader is derived from InputStreamReader and
Reader. Thus, it has access to the methods defined by these classes.
The following program creates a simple disk­to­screen utility that reads a text file called
"test.txt" and displays its contents on the screen. Thus, it is the complement of the key­
to­disk utility shown in the previous section.


In this example, notice that the FileReader is wrapped in a BufferedReader. This
gives it access to readLine( ). Also, closing the BufferedReader, br in this case,
automatically closes the file.
Ask the Expert
Q
: I have heard about another I/O package called NIO. Can you tell me
about it?
A
: Originally called New I/O, NIO was added to Java by JDK 1.4. It supports a
channel­based approach to I/O operations. The NIO classes are contained in
java.nio and its subordinate packages, such as java.nio.channels and
java.nio.charset.
NIO is built on two foundational items: buffers and channels. A buffer holds data.
A channel represents an open connection to an I/O device, such as a file or a
socket. In general, to use the new I/O system, you obtain a channel to an I/O
device and a buffer to hold data. You then operate on the buffer, inputting or
outputting data as needed.
Two other entities used by NIO are charsets and selectors. A charset defines the
way that bytes are mapped to characters. You can encode a sequence of characters
into bytes using an encoder. You can decode a sequence of bytes into characters
using a decoder. A selector supports key­based, non­blocking, multiplexed I/O. In
other words, selectors enable you to perform I/O through multiple channels.


Selectors are most applicable to socket­backed channels.
Beginning with JDK 7, NIO was substantially enhanced, so much so that the term
NIO.2 is often used. The improvements included three new packages
(java.nio.file, java.nio.file.attribute, and java.nio.file.spi); several new
classes, interfaces, and methods; and direct support for stream­based I/O. The
additions greatly expanded the ways in which NIO can be used, especially with
files.
It is important to understand that NIO does not replace the I/O classes found in
java.io, which are discussed in this chapter. Instead, the NIO classes are designed
to supplement the standard I/O system, offering an alternative approach, which
can be beneficial in some circumstances.
USING JAVA’S TYPE WRAPPERS TO CONVERT
NUMERIC STRINGS
Before leaving the topic of I/O, we will examine a technique useful when reading
numeric strings. As you know, Java’s println( ) method provides a convenient way to
output various types of data to the console, including numeric values of the built­in
types, such as int and double. Thus, println( ) automatically converts numeric values
into their human­readable form. However, methods like read( ) do not provide a
parallel functionality that reads and converts a string containing a numeric value into
its internal, binary format. For example, there is no version of read( ) that reads a
string such as "100" and then automatically converts it into its corresponding binary
value that is able to be stored in an int variable. Instead, Java provides various other
ways to accomplish this task. Perhaps the easiest is to use one of Java’s type wrappers.
Java’s type wrappers are classes that encapsulate, or wrap, the primitive types. Type
wrappers are needed because the primitive types are not objects. This limits their use to
some extent. For example, a primitive type cannot be passed by reference. To address
this kind of need, Java provides classes that correspond to each of the primitive types.
The type wrappers are Double, Float, Long, Integer, Short, Byte, Character, and
Boolean. These classes offer a wide array of methods that allow you to fully integrate
the primitive types into Java’s object hierarchy. As a side benefit, the numeric wrappers
also define methods that convert a numeric string into its corresponding binary
equivalent. Several of these conversion methods are shown here. Each returns a binary


value that corresponds to the string.
The integer wrappers also offer a second parsing method that allows you to specify the
radix.
The parsing methods give us an easy way to convert a numeric value, read as a string
from the keyboard or a text file, into its proper internal format. For example, the
following program demonstrates parseInt( ) and parseDouble( ). It averages a list
of numbers entered by the user. It first asks the user for the number of values to be
averaged. It then reads that number using readLine( ) and uses parseInt( ) to
convert the string into an integer. Next, it inputs the values, using parseDouble( ) to
convert the strings into their double equivalents.


Here is a sample run:


Ask the Expert
Q
: What else can the primitive type wrapper classes do?
A
: The primitive type wrappers provide a number of methods that help integrate
the primitive types into the object hierarchy. For example, various storage
mechanisms provided by the Java library, including maps, lists, and sets, work
only with objects. Thus, to store an int, for example, in a list, it must be wrapped in
an object. Also, all type wrappers have a method called compareTo( ), which
compares the value contained within the wrapper; equals( ), which tests two
values for equality; and methods that return the value of the object in various
forms. The topic of type wrappers is taken up again in 
Chapter 12
, when
autoboxing is discussed.
Try This 10­2
Creating a Disk­Based Help System
In 
Try This 4­1
, you created a Help class that displayed information about Java’s
control statements. In that implementation, the help information was stored within the
class itself, and the user selected help from a menu of numbered options.
Although this approach was fully functional, it is certainly not the ideal way of creating
a Help system. For example, to add to or change the help information, the source code
of the program needed to be modified. Also, the selection of the topic by number rather
than by name is tedious, and is not suitable for long lists of topics. Here, we will
remedy these shortcomings by creating a disk­based Help system.
The disk­based Help system stores help information in a help file. The help file is a


standard text file that can be changed or expanded at will, without changing the Help
program. The user obtains help about a topic by typing in its name. The Help system
searches the help file for the topic. If it is found, information about the topic is
displayed.
1. Create the help file that will be used by the Help system. The help file is a standard
text file that is organized like this:
#topic­name1
topic info
#topic­name2
topic info
.
.
.
#topic­nameN
topic info
The name of each topic must be preceded by a #, and the topic name must be on a line
of its own. Preceding each topic name with a # allows the program to quickly find the
start of each topic. After the topic name are any number of information lines about the
topic. However, there must be a blank line between the end of one topic’s information
and the start of the next topic. Also, there must be no trailing spaces at the end of any
help­topic lines.
Here is a simple help file that you can use to try the disk­based Help system. It stores
information about Java’s control statements.


Call this file helpfile.txt.
2. Create a file called FileHelp.java.
3. Begin creating the new Help class with these lines of code.
The name of the help file is passed to the Help constructor and stored in the instance
variable helpfile. Since each instance of Help will have its own copy of helpfile, each


instance can use a different file. Thus, you can create different sets of help files for
different sets of topics.
4. Add the helpOn( ) method shown here to the Help class. This method retrieves
help on the specified topic.
The first thing to notice is that helpOn( ) handles all possible I/O exceptions itself and
does not include a throws clause. By handling its own exceptions, it prevents this
burden from being passed on to all code that uses it. Thus, other code can simply call
helpOn( ) without having to wrap that call in a try/catch block.


The help file is opened using a FileReader that is wrapped in a BufferedReader.
Since the help file contains text, using a character stream allows the Help system to be
more efficiently internationalized.
The helpOn( ) method works like this. A string containing the name of the topic is
passed in the what parameter. The help file is then opened. Then, the file is searched,
looking for a match between what and a topic in the file. Remember, in the file, each
topic is preceded by a #, so the search loop scans the file for #s. When it finds one, it
then checks to see if the topic following that # matches the one passed in what. If it
does, the information associated with that topic is displayed. If a match is found,
helpOn( ) returns true. Otherwise, it returns false.
5. The Help class also provides a method called getSelection( ). It prompts the user
for a topic and returns the topic string entered by the user.
This method creates a BufferedReader attached to System.in. It then prompts for
the name of a topic, reads the topic, and returns it to the caller.
6. The entire disk­based Help system is shown here:




Ask the Expert
Q
: In addition to the parse methods defined by the primitive type
wrappers, is there another easy way to convert a numeric string
entered at the keyboard into its equivalent binary format?
A
: Yes! Another way to convert a numeric string into its internal, binary format is
to use one of the methods defined by the Scanner class, packaged in java.util.
Scanner reads formatted (that is, human­readable) input and converts it into its
binary form. Scanner can be used to read input from a variety of sources,
including the console and files. Therefore, you can use Scanner to read a numeric
string entered at the keyboard and assign its value to a variable. Although
Scanner contains far too many features to describe in detail, the following
illustrates its basic usage.
To use Scanner to read from the keyboard, you must first create a Scanner
linked to console input. To do this, you will use the following constructor:
Scanner(InputStream from)
This creates a Scanner that uses the stream specified by from as a source for
input. You can use this constructor to create a Scanner linked to console input, as
shown here:
This works because System.in is an object of type InputStream. After this line
executes, conin can be used to read input from the keyboard.
Once you have created a Scanner, it is a simple matter to use it to read numeric
input. Here is the general procedure:
1. Determine if a specific type of input is available by calling one of Scanner’s
hasNextX methods, where X is the type of data desired.
2. If input is available, read it by calling one of Scanner’s nextX methods.
As the preceding indicates, Scanner defines two sets of methods that enable you
to read input. The first are the hasNext methods. These include methods such as
hasNextInt( ) and hasNextDouble( ), for example. Each of the hasNext


methods returns true if the desired data type is the next available item in the data
stream, and false otherwise. For example, calling hasNextInt( ) returns true
only if the next item in the stream is the human­readable form of an integer. If the
desired data is available, you can read it by calling one of Scanner’s next
methods, such as nextInt( ) or nextDouble( ). These methods convert the
human­readable form of the data into its internal, binary representation and
return the result. For example, to read an integer, call nextInt( ).
The following sequence shows how to read an integer from the keyboard.
Using this code, if you enter the number 123 on the keyboard, then i will contain
the value 123.
Technically, you can call a next method without first calling a hasNext method.
However, doing so is not usually a good idea. If a next method cannot find the
type of data it is looking for, it throws an InputMismatchException. For this
reason, it is best to first confirm that the desired type of data is available by calling
a hasNext method before calling its corresponding next method.

Yüklə 83 Mb.

Dostları ilə paylaş:
1   ...   44   45   46   47   48   49   50   51   ...   82




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə