Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

AhmadLang / Java, How To Program, 2004

.pdf
Скачиваний:
630
Добавлен:
31.05.2015
Размер:
51.82 Mб
Скачать

(This item is displayed on page 676 in the print version)

[View full size image]

To facilitate the retrieval of specific records from a file, at least one field in each record is chosen as a record key. A record key identifies a record as belonging to a particular person or entity and is unique to each record. This field typically is used to search and sort records. In the payroll record described previously, the employee identification number normally would be chosen as the record key.

There are many ways to organize records in a file. The most common is called a sequential file, in which records are stored in order by the record-key field. In a payroll file, records are placed in ascending order by employee identification number.

Most businesses store data in many different files. For example, companies might have payroll files, accounts receivable files (listing money due from clients), accounts payable files (listing money due to suppliers), inventory files (listing facts about all the items handled by the business) and many others. Often, a group of related files is called a database. A collection of programs designed to create and manage databases is called a database management system (DBMS). We discuss this topic in Chapter 25, Accessing Databases with JDBC

[Page 675 (continued)]

14.3. Files and Streams

Java views each file as a sequential stream of bytes (Fig. 14.2). Every operating system provides a mechanism to determine the end of a file, such as an end-of-file marker or a count of the total bytes in the file that is recorded in a system-maintained administrative data structure. A Java program processing a stream of bytes simply receives an indication from the operating system when the program reaches the end of the streamthe program does not need to know how the underlying platform represents files or streams. In some cases, the end-of-file indication occurs as an exception. In other cases, the indication is a return value from a method invoked on a stream-processing object.

[Page 676]

Figure 14.2. Java's view of a file of n bytes.

[View full size image]

File streams can be used to input and output data as either characters or bytes. Streams that input and output bytes to files are known as byte-based streams, storing data in its binary format. Streams that input and output characters to files are known as character-based streams, storing data as a sequence of characters. For instance, if the value 5 were being stored using a byte-based stream, it would be stored in the binary format of the numeric value 5, or 101. If the value 5 were being stored using a character-based stream, it would be stored in the binary format of the character 5, or 00000000 00110101 (this is the binary for the numeric value 53, which indicates the character 5 in the Unicode character sets). The difference between the numeric value 5 and the character 5 is that the numeric value can be used as an integer, whereas the character 5 is simply a character that can be used in a string of text, as in "Sarah Miller is 15 years old". Files that are created using byte-based streams are referred to as binary files, while files created using character-based streams are referred to as text files. Text files can be read by text editors, while binary files are read by a program that converts the data to a human-readable format.

[Page 677]

A Java program opens a file by creating an object and associating a stream of bytes or characters with it. The classes used to create these objects are discussed shortly. Java can also associate streams with different devices. In fact, Java creates three stream objects that are associated with devices when a Java program begins executingSystem.in, System.out and System.err. Object System.in (the standard input stream object) normally enables a program to input bytes from the keyboard; object System.out (the standard output stream object) normally enables a program to output data to the screen; and object System.err (the standard error stream object) normally enables a program to output error messages to the screen. Each of these streams can be redirected. For System.in, this capability enables the program to read bytes from a different source. For System.out and System.err, this capability enables the output to be sent to a different location, such as a file on disk. Class System provides methods setIn, setOut and setErr to redirect the standard input, output and error streams, respectively.

Java programs perform file processing by using classes from package java.io. This package includes definitions for stream classes, such as FileInputStream (for byte-based input from a file),

FileOutputStream (for byte-based output to a file), FileReader (for character-based input from a file) and FileWriter (for character-based output to a file). Files are opened by creating

objects of these stream classes, which inherit from classes InputStream, OutputStream, Reader and

Writer, respectively (these classes will be discussed later in this chapter). Thus, the methods of these stream classes can all be applied to file streams as well.

Java contains classes that enable the programmer to perform input and output of objects or variables of primitive data types. The data will still be stored as bytes or characters behind the scenes, allowing the programmer to read or write data in the form of integers, strings, or other data types without having to worry about the details of converting such values to byte-format. To perform such input and output, objects of classes ObjectInputStream and ObjectOutputStream can be used together with the byte-based file stream classes FileInputStream and FileOutputStream (these classes will be discussed in more detail shortly). The complete hierarchy of classes in package java.io can be viewed in the online documentation at

java.sun.com/j2se/5.0/docs/api/java/io/package-tree.html

Each indentation level in the hierarchy indicates that the indented class extends the class under which it is indented. For example, class InputStream is a subclass of Object. Click a class's name in the hierarchy to view the details of the class.

As you can see in the hierarchy, Java offers many classes for performing input/output operations. We use several of these classes in this chapter to implement file-processing programs that create and manipulate sequential-access files and random-access files (discussed in Section 14.7). We also include a detailed example on class File, which is useful for obtaining information about files and directories. In Chapter 24, Networking, we use stream classes extensively to implement networking applications. Several other classes in the java.io package that we do not use in this chapter are discussed briefly in Section 14.8.

[Page 678]

In addition to the classes in this package, character-based input and output can be performed with classes Scanner and Formatter. Class Scanner is used extensively to input data from the keyboard. As we will see, this class can also read data from a file. Class Formatter enables formatted data to be output to the screen or to a file in a manner similar to System.out.printf. Chapter 28, Formatted Output, presents the details of formatted output with System.out.printf. All these features can be used to format text files as well.

[Page 678 (continued)]

14.4. Class File

This section presents class File, which is particularly useful for retrieving information about files or directories from disk. Objects of class File do not open files or provide any file-processing capabilities. However, File objects are used frequently with objects of other java.io classes to specify files or directories to manipulate.

Creating File Objects

Class File provides four constructors. The constructor public File( String name )

specifies the name of a file or directory to associate with the File object. The name can contain path information as well as a file or directory name. A file or directory's path specifies its location on disk. The path includes some or all of the directories leading to the file or directory. An absolute path contains all the directories, starting with the root directory, that lead to a specific file or directory. Every file or directory on a particular disk drive has the same root directory in its path. A relative path normally starts from the directory in which the application began executing, and is therefore a path that is "relative" to the current directory.

The constructor

public File( String pathToName, String name )

uses argument pathToName (an absolute or relative path) to locate the file or directory specified by name.

The constructor

public File( File directory, String name )

uses an existing File object directory (an absolute or relative path) to locate the file or directory specified by name. Figure 14.3 lists some common File methods. The complete list can be viewed at java.sun.com/j2se/5.0/docs/api/java/io/File.html.

 

Figure 14.3. File methods.

 

(This item is displayed on page 679 in the print version)

Method

Description

 

 

boolean canRead()

Returns true if a file is readable by the current application; false

 

otherwise.

boolean canWrite()

boolean exists()

boolean isFile()

boolean isDirectory()

Returns true if a file is writable by the current application; false otherwise.

Returns TRue if the name specified as the argument to the File constructor is a file or directory in the specified path; false otherwise.

Returns true if the name specified as the argument to the File constructor is a file; false otherwise.

Returns true if the name specified as the argument to the File constructor is a directory; false otherwise.

boolean

isAbsolute()

Returns TRue if the arguments specified to the File constructor indicate

 

 

 

an absolute path to a file or directory; false otherwise.

String

 

Returns a string with the absolute path of the file or directory.

getAbsolutePath()

 

String getName()

Returns a string with the name of the file or directory.

String

getPath()

Returns a string with the path of the file or directory.

String

getParent()

Returns a string with the parent directory of the file or directory (i.e., the

 

 

 

directory in which the file or directory can be found).

long

length()

Returns the length of the file, in bytes. If the File object represents a

 

 

 

directory, 0 is returned.

long

lastModified()

Returns a platform-dependent representation of the time at which the file

 

 

 

or directory was last modified. The value returned is useful only for

 

 

 

comparison with other values returned by this method.

String[] list()

Returns an array of strings representing the contents of a directory.

 

 

 

Returns null if the File object does not represent a directory.

 

 

 

 

The constructor

public File( URI uri )

[Page 679]

uses the given URI object to locate the file. A Uniform Resource Identifier (URI) is a more general form of the Uniform Resource Locators (URLs) that are used to locate Web sites. For example, http://www.deitel.com/ is the URL for the Deitel & Associates' Web site. URIs for locating files vary across operating systems. On Windows platforms, the URI

file:/C:/data.txt

identifies the file data.txt stored in the root directory of the C: drive. On UNIX/Linux platforms, the URI

file:/home/student/data.txt

identifies the file data.txt stored in the home directory of the user student.

[Page 680]

Error-Prevention Tip 14.1

Use File method isFile to determine whether a File object represents a file (not a directory) before attempting to open the file.

Demonstrating Class File

Figure 14.4Fig. 14.5 demonstrate class File. The application prompts the user to enter a file name or directory name, then outputs information about the file name or directory name input.

Figure 14.4. File class used to obtain file and directory information.

1// Fig. 14.4: FileDemonstration.java

2// Demonstrating the File class.

3import java.io.File;

4

5public class FileDemonstration

6{

7 // display information about file user specifies

8public void analyzePath( String path )

9{

10// create File object based on user input

11File name = new File( path );

12

13 if ( name.exists() ) // if name exists, output information about it

14{

15// display file (or directory) information

16System.out.printf(

17

%s%s\n%s\n%s\n%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s",

18

name.getName() " exists",

 

 

19

( name.isFile() ? "is a file" : "is not a

file" ),

20

( name.isDirectory() ? "is a directory" :

 

21

"is not a directory" ),

 

 

22

( name.isAbsolute() ? "is

absolute path"

:

23

"is not absolute path"

), "Last modified: ",

24

name.lastModified(), "Length: ", name.length(),

25

"Path: ", name.getPath(),

"Absolute path: ",

26

name.getAbsolutePath(), "Parent: ", name.getParent() );

27

 

 

 

28if ( name.isDirectory() ) // output directory listing

29{

30

String directory[] = name.list();

31

System.out.println( "\n\nDirectory contents:\n" );

32

 

33

for ( String directoryName : directory )

34

System.out.printf( "%s\n", directoryName );

35} // end else

36} // end outer if

37else // not file or directory, output error message

38{

39System.out.printf( "%s %s", path, "does not exist." );

40} // end else

41} // end method analyzePath

42} // end class FileDemonstration

Figure 14.5. Testing class FileDemonstration.

(This item is displayed on page 681 in the print version)

1// Fig. 14.5: FileDemonstrationTest.java

2// Testing the FileDemonstration class.

3import java.util.Scanner;

4

5public class FileDemonstrationTest

6{

7public static void main( String args[] )

8{

9Scanner input = new Scanner( System.in );

10FileDemonstration application = new FileDemonstration();

12System.out.print( "Enter file or directory name here: " );

13application.analyzePath( input.nextLine() );

14} // end main

15 } // end class FileDemonstrationTest

Enter file or directory name here: C:\Program Files\Java\jdk1.5.0\demo\jfc jfc exists

is not a file is a directory

is absolute path

Last modified: 1083938776645 Length: 0

Path: C:\Program Files\Java\jdk1.5.0\demo\jfc

Absolute path: C:\Program Files\Java\jdk1.5.0\demo\jfc Parent: C:\Program Files\Java\jdk1.5.0\demo

Directory contents:

CodePointIM

FileChooserDemo

Font2DTest

Java2D

Metalworks

Notepad

SampleTree

Stylepad

SwingApplet

SwingSet2

TableExample

Enter file or directory name here:

C:\Program Files\Java\jdk1.5.0\demo\jfc\Java2D\readme.txt readme.txt exists

is a file

is not a directory is absolute path

Last modified: 1083938778347 Length: 7501

Path: C:\Program Files\Java\jdk1.5.0\demo\jfc\Java2D\readme.txt

Absolute path: C:\Program Files\Java\jdk1.5.0\demo\jfc\Java2D\readme.txt Parent: C:\Program Files\Java\jdk1.5.0\demo\jfc\Java2D

[Page 682]

The program begins by prompting the user for a file or directory (line 12 of Fig. 14.5). Line 13 inputs the file name or directory name and passes it to method analyzePath (lines 841 of Fig. 14.4). The method creates a new File object (line 11) and assigns its reference to name. Line 13 invokes File method exists to determine whether the name input by the user exists (either as a file or as a directory) on the disk. If the name input by the user does not exist, control proceeds to lines 3740 and displays a message to the screen containing the name the user typed, followed by "does not exist." Otherwise, the body of the if statement (lines 1336) executes. The program outputs the name of the file or directory (line 18), followed by the results of testing the File object with isFile (line 19), isDirectory (line 20) and isAbsolute (line 22). Next, the program displays the values returned by lastModified (line 24), length (line 24), getPath (line 25), getAbsolutePath (line 26) and getParent (line 26). If the File object represents a directory (line 28), the program obtains a list of the directory's contents as an array of Strings by using File method list (line 30) and displays the list on the screen.

The first output of this program demonstrates a File object associated with the jfc directory from the

Java 2 Software Development Kit. The second output demonstrates a File object associated with the readme.txt file from the Java 2D example that comes with the Java 2 Software Development Kit. In both cases, we specified an absolute path on our personal computer.

A separator character is used to separate directories and files in the path. On a Windows computer, the separator character is a backslash (\) character. On a UNIX workstation, it is a forward slash (/) character. Java processes both characters identically in a path name. For example, if we were to use the path

c:\Program Files\Java\jdk1.5.0\demo/jfc

which employs each separator character, Java still processes the path properly. When building strings that represent path information, use File.pathSeparator to obtain the local computer's proper separator character rather than explicitly using / or \. This constant returns a String consisting of one characterthe proper separator for the system.

Common Programming Error 14.1

Using \ as a directory separator rather than \\ in a string literal is a logic error. A single \ indicates that the \ followed by the next character represents an escape sequence. Use \\ to insert a \ in a string literal.

[Page 682 (continued)]

14.5. Sequential-Access Text Files

In this section, we create and manipulate sequential-access files. As mentioned earlier, these are files in which records are stored in order by the record-key field. We first demonstrate sequential-access files using text files, allowing the reader to quickly create and edit human-readable files. In the subsections of this chapter we discuss creating, writing data to, reading data from and updating sequential-access text files. We also include a credit-inquiry program that retrieves specific data from a file.

14.5.1. Creating a Sequential-Access Text File

Java imposes no structure on a filenotions such as a record do not exist as part of the Java language. Therefore, the programmer must structure files to meet the requirements of the intended application. In the following example, we see how to impose a record structure on a file.

[Page 683]

The program in Fig. 14.6Fig. 14.7 and Fig. 14.9 creates a simple sequential-access file that might be used in an accounts receivable system to help keep track of the amounts owed to a company by its credit clients. For each client, the program obtains from the user an account number, the client's name and the client's balance (i.e., the amount the client owes the company for goods and services received). The data obtained for each client constitutes a "record" for that client. The account number is used as the record key in this applicationthe file will be created and maintained in account number order. The program assumes that the user enters the records in account number order. In a comprehensive accounts receivable system (based on sequential-access files), a sorting capability would be provided so that the user could enter the records in any order. The records would then be sorted and written to the file.

Figure 14.6. AccountRecord maintains information for one account.

(This item is displayed on pages 683 - 684 in the print version)

1

//

Fig.

14

.6: AccountRecord.java

2

//

A class

that represents one

record of information.

3

package

com.deitel.jhtp6.ch14;

// packaged for reuse

4

 

 

 

 

 

5public class AccountRecord

6{

7private int account;

8private String firstName;

9private String lastName;

10private double balance;

12// no-argument constructor calls other constructor with default values

13public AccountRecord()

14

{

 

 

 

15

 

this (

0, "", "",

0.0 ); // call four-argument constructor

16

}

// end

no-argument

AccountRecord constructor

17

 

 

 

 

18// initialize a record

19public AccountRecord( int acct, String first, String last, double bal )

20{

21setAccount( acct );

22setFirstName( first );

23setLastName( last );

24setBalance( bal );

25} // end four-argument AccountRecord constructor

26

27// set account number

28public void setAccount( int acct )

29{

30account = acct;

31} // end method setAccount

32

33// get account number

34public int getAccount()

35{

36return account;

37} // end method getAccount

39// set first name

40public void setFirstName( String first )

41{

42firstName = first;

43} // end method setFirstName

45// get first name

46public String getFirstName()

47{

48return firstName;

49} // end method getFirstName

51// set last name

52public void setLastName( String last )

53{

54lastName = last;

55} // end method setLastName

57// get last name

58public String getLastName()

59{

60return lastName;

61} // end method getLastName

63// set balance

64public void setBalance( double bal )

65{

66balance = bal;

67} // end method setBalance

69// get balance

70public double getBalance()

71{

72return balance;

73} // end method getBalance

74} // end class AccountRecord

Figure 14.7. Creating a sequential text file.

(This item is displayed on pages 686 - 687 in the print version)

1 // Fig. 14.7: CreateTextFile.java

2 // Writing data to a text file with class Formatter.

3import java.io.FileNotFoundException;

4import java.lang.SecurityException;

5import java.util.Formatter;

6import java.util.FormatterClosedException;

7import java.util.NoSuchElementException;

8import java.util.Scanner;

9

10 import com.deitel.jhtp6.ch14.AccountRecord; 11

12public class CreateTextFile

13{

14private Formatter output; // object used to output text to file

16// enable user to open file

17public void openFile()

18{

19try

20{

21output = new Formatter( "clients.txt" );

22} // end try

23catch ( SecurityException securityException )

24{