Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
14 Files and Streams I can only assume that a “Do Not File” document is filed in a “Do Not File” file. —Senator Frank Church Senate Intelligence Subcommittee Hearing, 1975 Consciousness … does not appear to itself chopped up in bits. … A “river” or a “stream” are the metaphors by which it is most naturally described. —William James OBJECTIVES In this chapter you will learn: ■ ■ To create, read, write and update files. To use class File to retrieve information about files and directories. ■ The Java input/output stream class hierarchy. I read part of it all the way through. ■ The differences between text files and binary files. ■ Sequential-access file processing. —Samuel Goldwyn ■ A great memory does not make a philosopher, any more than a dictionary can be called grammar. —John Henry, Cardinal Newman ■ ■ ■ To use classes Scanner and Formatter to process text files. To use the FileInputStream and FileOutputStream classes. To use a JFileChooser dialog. To use the ObjectInputStream and ObjectOutputStream classes. © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 2 Chapter 14 Files and Streams Self-Review Exercises 14.1 Fill in the blanks in each of the following statements: a) Ultimately, all data items processed by a computer are reduced to combinations of and . ANS: ones, zeros. b) The smallest data item a computer can process is called a(n) . ANS: bit. can sometimes be viewed as a group of related records. c) A(n) ANS: file. d) Digits, letters and special symbols are referred to as . ANS: characters. e) A database is a group of related . ANS: files. f) Object normally enables a program to output error messages to the screen. ANS: System.err. 14.2 why. Determine which of the following statements are true and which are false. If false, explain 14.3 a) The programmer must explicitly create the stream objects System.in, System.out and System.err. ANS: False. These three streams are created for the programmer when a Java application begins executing. b) When reading data from a file using class Scanner, if the programmer wishes to read data in the file multiple times, the file must be closed and reopened to read from the beginning of the file. This moves the file-position pointer back to the beginning of the file. ANS: True. c) Method exists of class File returns true if the name specified as the argument to the File constructor is a file or directory in the specified path. ANS: True. d) Binary files are human readable. ANS: False. Text files are human readable. e) An absolute path contains all the directories, starting with the root directory, that lead to a specific file or directory. ANS: True. f) Class Formatter contains method printf, which enables formatted data to be output to the screen or to a file. ANS: False. Class Formatter contains method format, which enables formatted data to be output to the screen or to a file. Complete the following tasks, assuming that each applies to the same program: a) Write a statement that opens file "oldmast.txt" for input—use Scanner variable inOldMaster. ANS: Scanner inOldMaster = new Scanner( new File ( "oldmast.txt" ) ); b) Write a statement that opens file "trans.txt" for input—use Scanner variable inTransaction. ANS: Scanner inTransaction = new Scanner( new File( "trans.txt" ) ); c) Write a statement that opens file "newmast.txt" for output (and creation)—use formatter variable outNewMaster. ANS: Formatter outNewMaster = new Formatter( "newmast.txt" ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Self-Review Exercises 3 d) Write the statements needed to read a record from the file "oldmast.txt". The data read should be used to create an object of class AccountRecord—use Scanner variable inOldMaster. Assume that class AccountRecord is the same as the AccountRecord class in Fig. 14.6 ANS: AccountRecord account = new AccountRecord(); account.setAccount( inOldMaster.nextInt() ); account.setFirstName( inOldMaster.next() ); account.setLastName( inOldMaster.next() ); account.setBalance( inOldMaster.nextDouble() ); e) Write the statements needed to read a record from the file "trans.txt". The record is an object of class TransactionRecord—use Scanner variable inTransaction. Assume that class TransactionRecord contains method setAccount (which takes an int) to set the account number and method setAmount (which takes a double) to set the amount of the transaction. ANS: TransactionRecord transaction = new Transaction(); transaction.setAccount( inTransaction.nextInt() ); transaction.setAmount( inTransaction.nextDouble() ); f) Write a statement that outputs a record to the file "newmast.txt". The record is an object of type AccountRecord—use Formatter variable outNewMaster. ANS: outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); 14.4 Complete the following tasks, assuming that each applies to the same program: a) Write a statement that opens file "oldmast.ser" for input—use ObjectInputStream variable inOldMaster to wrap a FileInputStream object. ANS: ObjectInputStream inOldMaster = new ObjectInputStream( new FileInputStream( "oldmast.ser" ) ); b) Write a statement that opens file "trans.ser" for input—use ObjectInputStream variable inTransaction to wrap a FileInputStream object. ANS: ObjectInputStream inTransaction = new ObjectInputStream( new FileInputStream( "trans.ser" ) ); c) Write a statement that opens file "newmast.ser" for output (and creation)—use jectOutputStream variable outNewMaster to wrap a FileOutputStream. Ob- ANS: ObjectOutputStream outNewMaster = new ObjectOutputStream( new FileOutputStream( "newmast.ser" ) ); d) Write a statement that reads a record from the file "oldmast.ser". The record is an object of class AccountRecordSerializable—use ObjectInputStream variable inOldMaster. Assume class AccountRecordSerializable is the same as the AccountRecordSerializable class in Fig. 14.17. ANS: accountRecord = ( AccountRecordSerializable ) inOldMaster.readObject(); e) Write a statement that reads a record from the file "trans.ser". The record is an object of class TransactionRecord—use ObjectInputStream variable inTransaction. ANS: transactionRecord = ( TransactionRecord ) inTransaction.readObject(); f) Write a statement that outputs a record to the file "newmast.ser". The record is an object of type AccountRecordSerializable—use ObjectOutputStream variable outNewMaster. ANS: outNewMaster.writeObject( newAccountRecord ); 14.5 Find the error in each block of code and show how to correct it. a) Assume that account, company and amount are declared. © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 4 Chapter 14 Files and Streams ObjectOutputStream outputStream; outputStream.writeInt( account ); outputStream.writeChars( company ); outputStream.writeDouble( amount ); ANS: Error: The file has not been opened before the attempt is made to output data to the stream. Correction: Open a file for output by creating a new ObjectOutputStream object that wraps a FileOutputStream object. b) The following statements should read a record from the file "payables.txt". The Scanner variable inPayable should be used to refer to this file. Scanner inPayable = new Scanner( new File( "payables.txt" ) ); PayablesRecord record = ( PayablesRecord ) inPayable.readObject(); ANS: Error: This example uses text files with a Scanner, there is no object serialization. As a result, method readObject cannot be used to read that data from the file. Each piece of data must be read separately, then used to create a PayablesRecord object. Correction: Use methods of inPayable to read each piece of the PayablesRecord object. Exercises 14.6 Fill in the blanks in each of the following statements: a) Computers store large amounts of data on secondary storage devices as . ANS: files b) A(n) is composed of several fields. ANS: record c) To facilitate the retrieval of specific records from a file, one field in each record is chosen as a(n) . ANS: record key d) Files that are created using byte-based streams are referred to as files, while files created using character-based streams are referred to as files. ANS: binary, text e) The standard stream objects are , and . ANS: System.in, System.out, System.err 14.7 (File Matching) Self-Review Exercise 14.3 asks the reader to write a series of single statements. Actually, these statements form the core of an important type of file-processing program, namely, a file-matching program. In commercial data processing, it is common to have several files in each application system. In an accounts receivable system, for example, there is generally a master file containing detailed information about each customer, such as the customer’s name, address, telephone number, outstanding balance, credit limit, discount terms, contract arrangements and possibly a condensed history of recent purchases and cash payments. As transactions occur (i.e., sales are made and payments arrive in the mail), information about them is entered into a file. At the end of each business period (a month for some companies, a week for others, and a day in some cases), the file of transactions (called "trans.txt") is applied to the master file (called "oldmast.txt") to update each account’s purchase and payment record. During an update, the master file is rewritten as the file "newmast.txt", which is then used at the end of the next business period to begin the updating process again. File-matching programs must deal with certain problems that do not arise in single-file programs. For example, a match does not always occur. If a customer on the master file has not made © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 5 any purchases or cash payments in the current business period, no record for this customer will appear on the transaction file. Similarly, a customer who did make some purchases or cash payments could have just moved to this community, and if so, the company may not have had a chance to create a master record for this customer. Write a complete file-matching accounts receivable program. Use the account number on each file as the record key for matching purposes. Assume that each file is a sequential text file with records stored in increasing account-number order. a) Define class TransactionRecord. Objects of this class contain an account number and amount for the transaction. Provide methods to modify and retrieve these values. b) Modify class AccountRecord in Fig. 14.6 to include method combine, which takes a TransactionRecord object and combines the balance of the AccountRecord object and amount value of the TransactionRecord object. c) Write a program to create data for testing the program. Use the sample account data in Figs. 14.24 and 14.25. Run the program to create the files trans.txt and oldmast.txt, to be used by your file-matching program. Master file Account number Name Balance 100 Alan Jones 348.17 300 Mary Smith 27.19 500 Sam Sharp 0.00 700 Suzy Green –14.22 Fig. 14.1 | Sample data for master file. Transaction file Account number Transaction amount 100 27.14 300 62.11 400 100.56 900 82.17 Fig. 14.2 | Sample data for transaction file. d) Create class FileMatch to perform the file-matching functionality. The class should contain methods that read oldmast.txt and trans.txt. When a match occurs (i.e., records with the same account number appear in both the master file and the transaction file), add the dollar amount in the transaction record to the current balance in the master record, and write the "newmast.txt" record. (Assume that purchases are indicated by positive amounts in the transaction file and payments by negative amounts.) When there is a master record for a particular account, but no corresponding transaction record, merely write the master record to "newmast.txt". When there is a transac- © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 6 Chapter 14 Files and Streams tion record, but no corresponding master record, print to a log file the message "Unmatched transaction record for account number…" (fill in the account number from the transaction record). The log file should be a text file named "log.txt". ANS: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 // Exercise 14.7 Solution: AccountRecord.java // A class that represents one record of information. public class AccountRecord { private int account; private String firstName; private String lastName; private double balance; // no-argument constructor calls other constructor with default values public AccountRecord() { this( 0, "", "", 0.0 ); // call four-argument constructor } // end no-argument AccountRecord constructor // initialize a record public AccountRecord( int acct, String first, String last, double bal ) { setAccount( acct ); setFirstName( first ); setLastName( last ); setBalance( bal ); } // end four-argument AccountRecord constructor // add a transaction to an account record public void combine( TransactionRecord transaction ) { balance = balance + transaction.getAmount(); } // end method combine // set account number public void setAccount( int acct ) { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount // set first name public void setFirstName( String first ) { firstName = first; } // end method setFirstName © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 7 // get first name public String getFirstName() { return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; } // end method setLastName // get last name public String getLastName() { return lastName; } // end method getLastName // set balance public void setBalance( double bal ) { balance = bal; } // end method setBalance // get balance public double getBalance() { return balance; } // end method getBalance } // end class AccountRecord // Exercise 14.7 Solution: TransactionRecord.java // A class that represents one transaction record. public class TransactionRecord { private int account; private double amount; // no-argument constructor calls other constructor with default values public TransactionRecord() { this( 0, 0.0 ); } // end no-argument TransactionRecord // initialize a record public TransactionRecord( int acct, double amt ) { setAccount( acct ); setAmount( amt ); } // end two-argument TransactionRecord // set account number public void setAccount( int acct ) © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 8 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Chapter 14 Files and Streams { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount // set amount public void setAmount( double amt ) { amount = amt; } // end method setAmount // get amount public double getAmount() { return amount; } // end method getAmount } // end class TransactionRecord // Exercise 14.7 Solution: CreateData.java // Create data to put into an account file and a transactions file. import java.io.File; import java.io.FileNotFoundException; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; public class CreateData { public static void main( String args[] ) { Formatter outOldMaster = null; Formatter outTransaction = null; AccountRecord accounts[] = new AccountRecord[ 4 ]; TransactionRecord transactions[] = new TransactionRecord[ 4 ]; // create accounts[ accounts[ accounts[ accounts[ account records 0 ] = new AccountRecord( 1 ] = new AccountRecord( 2 ] = new AccountRecord( 3 ] = new AccountRecord( // create transactions transactions[ 0 ] = new transactions[ 1 ] = new transactions[ 2 ] = new transactions[ 3 ] = new 100, 300, 500, 700, "Alan", "Jones", 348.17 ); "Mary", "Smith", 27.19 ); "Sam", "Sharp", 0.00 ); "Suzy", "Green", -14.22 ); TransactionRecord( TransactionRecord( TransactionRecord( TransactionRecord( 100, 300, 400, 900, 27.14 ); 62.11 ); 100.56 ); 82.17 ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 try { 9 // file stream for output file outOldMaster = new Formatter( "oldmast.txt" ); for ( int i = 0; i < accounts.length; i++ ) { outOldMaster.format( "%d %s %s %.2f\n", accounts[ i ].getAccount(), accounts[ i ].getFirstName(), accounts[ i ].getLastName(), accounts[ i ].getBalance() ); } // end for // file stream for output file outTransaction = new Formatter( "trans.txt" ); for ( int i = 0; i < transactions.length; i++ ) { outTransaction.format( "%d %.2f\n", transactions[ i ].getAccount(), transactions[ i ].getAmount() ); } // end for } // end try catch ( SecurityException securityException ) { System.err.println( "You do not have write access to this file." ); System.exit( 1 ); } // end catch catch ( FileNotFoundException fileNotFoundException ) { System.err.println( "Error creating file." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch finally { if ( outOldMaster != null ) outOldMaster.close(); if ( outTransaction != null ) outTransaction.close(); } // end finally } // end main } // end class CreateData © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 10 Chapter 14 Files and Streams ANS: Contents of oldmast.txt after CreateData.java is executed: 100 300 500 700 Alan Jones 348.17 Mary Smith 27.19 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of trans.txt after CreateData.java is executed: 100 300 400 900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 27.14 62.11 100.56 82.17 // Exercise 14.7 Solution: FileMatch.java // Combine an account file with a transactions file into a // new account file. import java.io.File; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; import java.util.NoSuchElementException; import java.util.Scanner; public class FileMatch { private static Scanner inOldMaster; private static Scanner inTransaction; private static Formatter outNewMaster; private static Formatter logFile; private static TransactionRecord transaction; private static AccountRecord account; public FileMatch() { transaction = new TransactionRecord(); account = new AccountRecord(); } // end FileMatch constructor public void openFiles() { try { // file streams for input and output files inOldMaster = new Scanner( new File( "oldmast.txt" ) ); inTransaction = new Scanner( new File( "trans.txt" ) ); outNewMaster = new Formatter( "newmast.txt" ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 logFile = new Formatter( "log.txt" ); } // end try catch ( Exception exception ) { System.err.println( "Error opening the files." ); } // end catch } // end method openFiles public void processFiles() { int transactionAccountNumber; int accountNumber; try // block for reading/writing all records { // get a transaction record and its account number transaction = getTransactionRecord(); // if the transaction is null, we are done if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); // get an account record and its account number account = getAccountRecord(); // if the account is null, we are done if ( account == null ) return; accountNumber = account.getAccount(); while ( accountNumber != 0 ) { while ( accountNumber < transactionAccountNumber ) { // there is no transaction for this account outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); account = getAccountRecord(); // get a new account if ( account == null ) return; accountNumber = account.getAccount(); } // end while // if there is a transaction for this account if ( accountNumber == transactionAccountNumber ) { // combine the records account.combine( transaction ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 11 12 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 Chapter 14 Files and Streams // write to the master file outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); // get a new account account = getAccountRecord(); if ( account == null ) return; accountNumber = account.getAccount(); } // end if while ( transactionAccountNumber < accountNumber ) { // there is no account for this transaction logFile.format( "%s %d\n", "Unmatched transaction record for account number", transactionAccountNumber ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); } // end while } // end outer while } // end try catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch } // end method processFiles public void closeFiles() { try // close the files { © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 if ( inTransaction != null ) inTransaction.close(); if ( outNewMaster != null ) outNewMaster.close(); if ( inOldMaster != null ) inOldMaster.close(); if ( logFile != null ) logFile.close(); } // end try catch ( Exception exception ) { System.err.println( "Error closing the files." ); System.exit( 1 ); } // end catch } // end method closeFiles // get a transaction record private TransactionRecord getTransactionRecord() { // try to read the record try { if ( inTransaction.hasNext() ) { transaction.setAccount( inTransaction.nextInt() ); transaction.setAmount( inTransaction.nextDouble() ); return transaction; } // end if else // we have hit end of transaction file { // these remaining accounts have while ( inOldMaster.hasNext() ) { account.setAccount( inOldMaster.nextInt() ); account.setFirstName( inOldMaster.next() ); account.setLastName( inOldMaster.next() ); account.setBalance( inOldMaster.nextDouble() ); // store in new master outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); } // end while } // end else } // end try catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 13 14 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 Chapter 14 Files and Streams { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch catch ( NoSuchElementException elementException ) { System.err.println( "Invalid input from file." ); } // end catch // return null - no more records return null; } // end method getTransactionRecord // get an account record private AccountRecord getAccountRecord() { try // try to read an account record { if ( inOldMaster.hasNext() ) { account.setAccount( inOldMaster.nextInt() ); account.setFirstName( inOldMaster.next() ); account.setLastName( inOldMaster.next() ); account.setBalance( inOldMaster.nextDouble() ); return account; } // end if else // we have hit end of old master file { logFile.format( "%s %d\n", "Unmatched transaction record for account number", transaction.getAccount() ); // these records are transactions without accounts while ( inTransaction.hasNext() ) { transaction.setAccount( inTransaction.nextInt() ); transaction.setAmount( inTransaction.nextDouble() ); } // end while } // end else } // end try catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch catch ( NoSuchElementException elementException ) { System.err.println( "Invalid input from file." ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 15 257 } // end catch 258 259 return null; 260 } // end method getAccountRecord 261 } // end class FileMatch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // Exercise 14.7 Solution: FileMatchTest.java // Tests FileMatch program. public class FileMatchTest { public static void main( String args[] ) { FileMatch application = new FileMatch(); application.openFiles(); application.processFiles(); application.closeFiles(); } // end main } // end class FileMatchTest ANS: Contents of newmast.txt after FileMatchTest is executed. 100 300 500 700 Alan Jones 375.31 Mary Smith 89.30 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of log.txt after FileMatchTest is executed. Unmatched transaction record for account number 400 Unmatched transaction record for account number 900 14.8 (File Matching with Multiple Transactions) It is possible (and actually common) to have several transaction records with the same record key. This situation occurs, for example, when a customer makes several purchases and cash payments during a business period. Rewrite your accounts receivable file-matching program from Exercise 14.8 to provide for the possibility of handling several transaction records with the same record key. Modify the test data of CreateData.java to include the additional transaction records in Fig. 14.26. © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 16 Chapter 14 Files and Streams Account number Dollar amount 300 83.89 700 80.78 700 1.53 Fig. 14.3 | Additional transaction records. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 // Exercise 14.8 Solution: AccountRecord.java // A class that represents one record of information. public class AccountRecord { private int account; private String firstName; private String lastName; private double balance; // no-argument constructor calls other constructor with default values public AccountRecord() { this( 0, "", "", 0.0 ); // call four-argument constructor } // end no-argument AccountRecord constructor // initialize a record public AccountRecord( int acct, String first, String last, double bal ) { setAccount( acct ); setFirstName( first ); setLastName( last ); setBalance( bal ); } // end four-argument AccountRecord constructor // add a transaction to an account record public void combine( TransactionRecord transaction ) { balance = balance + transaction.getAmount(); } // end method combine // set account number public void setAccount( int acct ) { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 17 // set first name public void setFirstName( String first ) { firstName = first; } // end method setFirstName // get first name public String getFirstName() { return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; } // end method setLastName // get last name public String getLastName() { return lastName; } // end method getLastName // set balance public void setBalance( double bal ) { balance = bal; } // end method setBalance // get balance public double getBalance() { return balance; } // end method getBalance } // end class AccountRecord // Exercise 14.8 Solution: TransactionRecord.java // A class that represents one transaction record. public class TransactionRecord { private int account; private double amount; // no-argument constructor calls other constructor with default values public TransactionRecord() { this( 0, 0.0 ); } // end no-argument TransactionRecord // initialize a record public TransactionRecord( int acct, double amt ) { © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 18 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Chapter 14 Files and Streams setAccount( acct ); setAmount( amt ); } // end two-argument TransactionRecord // set account number public void setAccount( int acct ) { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount // set amount public void setAmount( double amt ) { amount = amt; } // end method setAmount // get amount public double getAmount() { return amount; } // end method getAmount } // end class TransactionRecord // Exercise 14.8 Solution: CreateData.java // Create data to put into an account file and a transactions file. import java.io.File; import java.io.FileNotFoundException; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; public class CreateData { public static void main( String args[] ) { Formatter outOldMaster = null; Formatter outTransaction = null; AccountRecord accounts[] = new AccountRecord[ 4 ]; TransactionRecord transactions[] = new TransactionRecord[ 4 ]; // create accounts[ accounts[ accounts[ accounts[ account records 0 ] = new AccountRecord( 1 ] = new AccountRecord( 2 ] = new AccountRecord( 3 ] = new AccountRecord( 100, 300, 500, 700, "Alan", "Jones", 348.17 ); "Mary", "Smith", 27.19 ); "Sam", "Sharp", 0.00 ); "Suzy", "Green", -14.22 ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 // create transactions transactions[ 0 ] = new transactions[ 1 ] = new transactions[ 2 ] = new transactions[ 3 ] = new try { TransactionRecord( TransactionRecord( TransactionRecord( TransactionRecord( 100, 300, 300, 900, 19 27.14 ); 62.11 ); -10.00 ); 82.17 ); // file stream for output file outOldMaster = new Formatter( "oldmast.txt" ); for ( int i = 0; i < accounts.length; i++ ) { outOldMaster.format( "%d %s %s %.2f\n", accounts[ i ].getAccount(), accounts[ i ].getFirstName(), accounts[ i ].getLastName(), accounts[ i ].getBalance() ); } // end for // file stream for output file outTransaction = new Formatter( "trans.txt" ); for ( int i = 0; i < transactions.length; i++ ) { outTransaction.format( "%d %.2f\n", transactions[ i ].getAccount(), transactions[ i ].getAmount() ); } // end for } // end try catch ( SecurityException securityException ) { System.err.println( "You do not have write access to this file." ); System.exit( 1 ); } // end catch catch ( FileNotFoundException fileNotFoundException ) { System.err.println( "Error creating file." ); System.exit( 1 ); } // end catch catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch finally { if ( outOldMaster != null ) outOldMaster.close(); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 20 79 80 81 82 83 84 Chapter 14 Files and Streams if ( outTransaction != null ) outTransaction.close(); } // end finally } // end main } // end class CreateData ANS: Contents of oldmast.txt after CreateData.java is executed: 100 300 500 700 Alan Jones 348.17 Mary Smith 27.19 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of trans.txt after CreateData.java is executed: 100 300 300 900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 27.14 62.11 -10.00 82.17 // Exercise 14.8 Solution: FileMatch.java // Combine an account file with a transactions file into a // new account file. import java.io.File; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; import java.util.NoSuchElementException; import java.util.Scanner; public class FileMatch { private static Scanner inOldMaster; private static Scanner inTransaction; private static Formatter outNewMaster; private static Formatter logFile; private static TransactionRecord transaction; private static AccountRecord account; public FileMatch() { transaction = new TransactionRecord(); account = new AccountRecord(); } // end FileMatch constructor © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 public void openFiles() { try { // file streams for input and output files inOldMaster = new Scanner( new File( "oldmast.txt" ) ); inTransaction = new Scanner( new File( "trans.txt" ) ); outNewMaster = new Formatter( "newmast.txt" ); logFile = new Formatter( "log.txt" ); } // end try catch ( Exception exception ) { System.err.println( "Error opening the files." ); } // end catch } // end method openFiles public void processFiles() { int transactionAccountNumber; int accountNumber; try // block for reading/writing all records { // get a transaction record and its account number transaction = getTransactionRecord(); // if the transaction is null, we are done if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); // get an account record and its account number account = getAccountRecord(); // if the account is null, we are done if ( account == null ) return; accountNumber = account.getAccount(); while ( accountNumber != 0 ) { while ( accountNumber < transactionAccountNumber ) { // there is no transaction for this account outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); account = getAccountRecord(); // get a new account if ( account == null ) return; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 21 22 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 Chapter 14 Files and Streams accountNumber = account.getAccount(); } // end while // if there is a transaction for this account if ( accountNumber == transactionAccountNumber ) { while ( accountNumber == transactionAccountNumber ) { // combine the records account.combine( transaction ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); } // end while // write them to the master file outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); // get a new account account = getAccountRecord(); if ( account == null ) return; accountNumber = account.getAccount(); } // end if while ( transactionAccountNumber < accountNumber ) { // there is no account for this transaction logFile.format( "%s %d\n", "Unmatched transaction record for account number", transactionAccountNumber ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); } // end while } // end outer while } // end try catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch } // end method processFiles public void closeFiles() { try // close the files { if ( inTransaction != null ) inTransaction.close(); if ( outNewMaster != null ) outNewMaster.close(); if ( inOldMaster != null ) inOldMaster.close(); if ( logFile != null ) logFile.close(); } // end try catch ( Exception exception ) { System.err.println( "Error closing the files." ); System.exit( 1 ); } // end catch } // end method closeFiles // get a transaction record private TransactionRecord getTransactionRecord() { // try to read the record try { if ( inTransaction.hasNext() ) { transaction.setAccount( inTransaction.nextInt() ); transaction.setAmount( inTransaction.nextDouble() ); return transaction; } // end if else // we have hit end of transaction file { // these remaining accounts have while ( inOldMaster.hasNext() ) { account.setAccount( inOldMaster.nextInt() ); account.setFirstName( inOldMaster.next() ); account.setLastName( inOldMaster.next() ); account.setBalance( inOldMaster.nextDouble() ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 23 24 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 Chapter 14 Files and Streams // store in new master outNewMaster.format( "%d %s %s %.2f\n", account.getAccount(), account.getFirstName(), account.getLastName(), account.getBalance() ); } // end while } // end else } // end try catch ( FormatterClosedException closedException ) { System.err.println( "Error writing to file - file has been closed." ); System.exit( 1 ); } // end catch catch ( IllegalFormatException formatException ) { System.err.println( "Error with output." ); System.exit( 1 ); } // end catch catch ( NoSuchElementException elementException ) { System.err.println( "Invalid input from file." ); } // end catch // return null - no more records return null; } // end method getTransactionRecord // get an account record private AccountRecord getAccountRecord() { try // try to read an account record { if ( inOldMaster.hasNext() ) { account.setAccount( inOldMaster.nextInt() ); account.setFirstName( inOldMaster.next() ); account.setLastName( inOldMaster.next() ); account.setBalance( inOldMaster.nextDouble() ); return account; } // end if else // we have hit end of old master file { logFile.format( "%s %d\n", "Unmatched transaction record for account number", transaction.getAccount() ); // these records are transactions without accounts while ( inTransaction.hasNext() ) { transaction.setAccount( inTransaction.nextInt() ); transaction.setAmount( inTransaction.nextDouble() ); } // end while } // end else } // end try © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 246 catch ( FormatterClosedException closedException ) 247 { 248 System.err.println( 249 "Error writing to file - file has been closed." ); 250 System.exit( 1 ); 251 } // end catch 252 catch ( IllegalFormatException formatException ) 253 { 254 System.err.println( "Error with output." ); 255 System.exit( 1 ); 256 } // end catch 257 catch ( NoSuchElementException elementException ) 258 { 259 System.err.println( "Invalid input from file." ); 260 } // end catch 261 262 return null; 263 } // end method getAccountRecord 264 } // end class FileMatch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // Exercise 14.8 Solution: FileMatchTest.java // Tests FileMatch program. public class FileMatchTest { public static void main( String args[] ) { FileMatch application = new FileMatch(); application.openFiles(); application.processFiles(); application.closeFiles(); } // end main } // end class FileMatchTest ANS: Contents of newmast.txt after FileMatchTest is executed. 100 300 500 700 Alan Jones 375.31 Mary Smith 79.30 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of log.txt after FileMatchTest is executed. Unmatched transaction record for account number 900 © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 25 26 Chapter 14 Files and Streams 14.9 (File Matching with Object Serialization) Recreate your solution for Exercise 14.9 using object serialization. Use the statements from Exercise 14.4 as your basis for this program. You may want to create applications to read the data stored in the .ser files—the code in Section 14.6.2 can be modified for this purpose. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 // Exercise 14.9 Solution: AccountRecordSerializable.java // A class that represents one record of information. import java.io.Serializable; public class AccountRecordSerializable implements Serializable { private int account; private String firstName; private String lastName; private double balance; // no-argument constructor calls other constructor with default values public AccountRecordSerializable() { this( 0, "", "", 0.0 ); // call four-argument constructor } // end no-argument AccountRecordSerializable constructor // initialize a record public AccountRecordSerializable( int acct, String first, String last, double bal ) { setAccount( acct ); setFirstName( first ); setLastName( last ); setBalance( bal ); } // end four-argument AccountRecordSerializable constructor // add a transaction record to an account record public void combine( TransactionRecord transaction ) { balance = balance + transaction.getAmount(); } // end method combine // set account number public void setAccount( int acct ) { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount // set first name public void setFirstName( String first ) { firstName = first; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 27 } // end method setFirstName // get first name public String getFirstName() { return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; } // end method setLastName // get last name public String getLastName() { return lastName; } // end method getLastName // set balance public void setBalance( double bal ) { balance = bal; } // end method setBalance // get balance public double getBalance() { return balance; } // end method getBalance } // end class AccountRecordSerializable // Exercise 14.9 Solution: TransactionRecord.java // A class that represents one transaction record. import java.io.Serializable; public class TransactionRecord implements Serializable { private int account; private double amount; // no-argument constructor calls other constructor with default values public TransactionRecord() { this( 0, 0.0 ); } // end no-argument TransactionRecord // initialize a record public TransactionRecord( int acct, double amt ) { setAccount( acct ); setAmount( amt ); } // end two-argument TransactionRecord © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 28 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Chapter 14 Files and Streams // set account number public void setAccount( int acct ) { account = acct; } // end method setAccount // get account number public int getAccount() { return account; } // end method getAccount // set amount public void setAmount( double amt ) { amount = amt; } // end method setAmount // get amount public double getAmount() { return amount; } // end method getAmount } // end class TransactionRecord // Exercise 14.9 Solution: CreateData.java // Create data to put into an account file and a transactions file. import java.io.IOException; import java.io.FileOutputStream; import java.io.ObjectOutputStream; public class CreateData { private static ObjectOutputStream outOldMaster, outTransaction; public static void main( String args[] ) { try { try { // file streams for output files outOldMaster = new ObjectOutputStream( new FileOutputStream( "oldmast.ser" ) ); outTransaction = new ObjectOutputStream( new FileOutputStream( "trans.ser" ) ); } // end try catch ( IOException io ) { System.err.println( "Error opening the file." ); } // end catch © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 try { 29 outOldMaster.writeObject( new AccountRecordSerializable( 100, "Alan", "Jones", 348.17 ) ); outOldMaster.writeObject( new AccountRecordSerializable( 300, "Mary", "Smith", 27.19 ) ); outOldMaster.writeObject( new AccountRecordSerializable( 500, "Sam", "Sharp", 0.00 ) ); outOldMaster.writeObject( new AccountRecordSerializable( 700, "Suzy", "Green", -14.22 ) ); outTransaction.writeObject( new TransactionRecord( 100, 27.14 ) ); outTransaction.writeObject( new TransactionRecord( 300, 62.11 ) ); outTransaction.writeObject( new TransactionRecord( 300, -10.00 ) ); outTransaction.writeObject( new TransactionRecord( 400, 100.56 ) ); outTransaction.writeObject( new TransactionRecord( 900, 82.17 ) ); } // end try catch ( IOException io ) { System.out.println( "Error reading or writing to the file." ); System.exit( 1 ); } // end catch } finally // close the files { try { if ( outTransaction != null ) outTransaction.close(); if ( outOldMaster != null ) outOldMaster.close(); } // end try catch ( IOException io ) { System.err.println( "Error closing the file." ); System.exit( 1 ); } // end catch } // end finally } // end main } // end class CreateData © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 30 Chapter 14 Files and Streams ANS: Contents of oldmast.ser after CreateData.java is executed: 100 300 500 700 Alan Jones 348.17 Mary Smith 27.19 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of trans.ser after CreateData.java is executed: 100 300 300 400 900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 27.14 62.11 -10.00 100.56 82.17 // Exercise 14.9 Solution: FileMatch.java // Combine account file and a transactions file into a new account file. import java.io.EOFException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.ClassNotFoundException; import java.util.Formatter; public class FileMatch { private static ObjectInputStream inOldMaster; private static ObjectInputStream inTransaction; private static ObjectOutputStream outNewMaster; private static Formatter logFile; private static TransactionRecord transaction; private static AccountRecordSerializable account; public FileMatch() { transaction = new TransactionRecord(); account = new AccountRecordSerializable(); } // end FileMatch constructor public void openFiles() { try { // file streams for input and output files inOldMaster = new ObjectInputStream( new FileInputStream( "oldmast.ser" ) ); inTransaction = new ObjectInputStream( © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 new FileInputStream( "trans.ser" ) ); outNewMaster = new ObjectOutputStream( new FileOutputStream( "newmast.ser" ) ); logFile = new Formatter( "log.txt" ); } // end try catch ( IOException io ) { System.err.println( "Error opening the file." ); } // end catch } // end method openFiles public void processFiles() { int transactionAccountNumber; int accountNumber; try // block for reading/writing all records { // get a transaction record and its account number transaction = getTransactionRecord(); // if the transaction is null, we are done if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); // get an account record and its account number account = getAccountRecord(); // if the account is null, we are done if ( account == null ) return; accountNumber = account.getAccount(); while ( true ) { while ( accountNumber < transactionAccountNumber ) { // there is no transaction for this account outNewMaster.writeObject( account ); account = getAccountRecord(); // get a new account if ( account == null ) return; accountNumber = account.getAccount(); } // end while // if there is a transaction for this account if ( accountNumber == transactionAccountNumber ) { while ( accountNumber == transactionAccountNumber ) © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 31 32 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 Chapter 14 Files and Streams { // combine the records account.combine( transaction ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); } // end while // write them to the master file outNewMaster.writeObject( account ); // get a new account account = getAccountRecord(); if ( account == null ) return; accountNumber = account.getAccount(); } // end if while ( transactionAccountNumber < accountNumber ) { // there is no account for this transaction logFile.format( "%s %d\n", "Unmatched transaction record for account number", transactionAccountNumber ); // get a new transaction transaction = getTransactionRecord(); if ( transaction == null ) return; transactionAccountNumber = transaction.getAccount(); } // end while } // end outer while } // end try catch ( IOException io ) { System.err.println( "Error reading or writing the file." ); System.exit( 1 ); } // end catch catch ( ClassNotFoundException noClass ) { System.err.println( "Error reading the file." ); System.exit( 1 ); } // end catch } // end method processFiles public void closeFiles() © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 { 33 try // close the files { if ( inTransaction != null ) inTransaction.close(); if ( outNewMaster != null ) outNewMaster.close(); if ( inOldMaster != null ) inOldMaster.close(); if ( logFile != null ) logFile.close(); } // end try catch ( IOException io ) { System.err.println( "Error closing the file." ); System.exit( 1 ); } // end catch } // end method closeFiles // get a transaction record private TransactionRecord getTransactionRecord() throws IOException, ClassNotFoundException { TransactionRecord transaction; try // try to read the record { transaction = ( TransactionRecord ) inTransaction.readObject(); } // end try catch ( EOFException eof ) // if we hit end of transaction file { try { // read the remaining records from the old master while ( true ) outNewMaster.writeObject( inOldMaster.readObject() ); } // end try catch ( EOFException eof2 ) // we have hit end of old master file { return null; } // end catch } // end outer catch // return a transaction if we successfully read it return transaction; } // end method getTransactionRecord // get an account record private AccountRecordSerializable getAccountRecord() throws IOException, ClassNotFoundException { AccountRecordSerializable account; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 34 Chapter 14 Files and Streams 200 201 // try to read an account record 202 try 203 { 204 account = ( AccountRecordSerializable ) inOldMaster.readObject(); 205 } // end try 206 catch ( EOFException eof ) // we hit end of old master file 207 { 208 try 209 { 210 // all of these records are transactions without accounts 211 while ( true ) 212 { 213 logFile.format( "%s %d\n", 214 "Unmatched transaction record for account number", 215 transaction.getAccount() ); 216 transaction = 217 ( TransactionRecord ) inTransaction.readObject(); 218 } // end while 219 } // end try 220 catch ( EOFException eof2 ) // we hit end of transaction file 221 { 222 return null; 223 } // end catch 224 } // end outer catch 225 226 return account; 227 } // end method getAccountRecord 228 } // end class FileMatch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // Exercise 14.9 Solution: FileMatchTest.java // Tests FileMatch program. public class FileMatchTest { public static void main( String args[] ) { FileMatch application = new FileMatch(); application.openFiles(); application.processFiles(); application.closeFiles(); } // end main } // end class FileMatchTest © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 35 ANS: Contents of newmast.ser after FileMatchTest is executed. 100 300 500 700 Alan Jones 375.31 Mary Smith 79.30 Sam Sharp 0.00 Suzy Green -14.22 ANS: Contents of log.txt after FileMatchTest is executed. Unmatched transaction record for account number 400 Unmatched transaction record for account number 900 14.10 (Student Poll) Figure 7.8 contains an array of survey responses that is hard coded into the program. Suppose we wish to process survey results that are stored in a file. This exercise requires two separate programs. First, create an application that prompts the user for survey responses and outputs each response to a file. Use a Formatter to create a file called numbers.txt. Each integer should be written using method format. Then modify the program of Fig. 7.8 to read the survey responses from numbers.txt. The responses should be read from the file by using a Scanner. Method nextInt should be used to input one integer at a time from the file. The program should continue to read responses until it reaches the end of file. The results should be output to the text file "output.txt". ANS: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Exercise 14.10 Solution: CreateResults.java // Create poll results and output them to a file. import java.io.FileNotFoundException; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; import java.util.NoSuchElementException; import java.util.Scanner; public class CreateResults { private int getValue() { int result = -1; Scanner scanner = new Scanner( System.in ); // prompt the user for input System.out.print( "Enter integer result (1 - 10), -1 to quit: " ); try { result = scanner.nextInt(); } // end try catch ( NoSuchElementException noSuchElementException ) © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 36 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 Chapter 14 Files and Streams { System.err.println( "Error with input." ); System.exit( 1 ); } // end catch return result; } // end method getValue private void outputData() { Formatter pollNumbers = null; try { // create the output stream pollNumbers = new Formatter( "numbers.txt" ); int pollValue = getValue(); // get a number from the user // test for the sentinel value while ( pollValue != -1 ) { // if the number is valid if ( pollValue > 0 && pollValue < 11 ) // write the value pollNumbers.format( "%d\n", pollValue ); pollValue = getValue(); // get another value } // end while pollNumbers.close(); // close the file } // end try catch( SecurityException securityException ) { System.err.println( "Error opening file." ); } // end catch catch( FileNotFoundException fileNotFoundException ) { System.err.println( "Output file cannot be found." ); } // end catch catch( IllegalFormatException illegalFormatException ) { System.err.println( "Error with the output's format." ); } // end catch catch( FormatterClosedException formatterClosedException ) { System.err.println( "File has been closed." ); } // end catch finally { if ( pollNumbers != null ) © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 78 79 80 81 82 83 84 85 86 87 pollNumbers.close(); } // end finally } // end method outputData public static void main( String args[] ) { CreateResults application = new CreateResults(); application.outputData(); } // end main } // end class CreateResults ANS: Contents of numbers.txt after CreateResults.java has been executed: 3 4 5 2 2 2 8 8 9 9 9 9 9 5 7 7 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // Exercise 14.10 Solution: StudentPoll.java // Read poll results from a file and output ratings. import java.io.File; import java.io.FileNotFoundException; import java.util.Formatter; import java.util.FormatterClosedException; import java.util.IllegalFormatException; import java.util.NoSuchElementException; import java.util.Scanner; public class StudentPoll { public void displayData() { int frequency[] = new int[ 11 ]; Formatter writer = null; Scanner pollNumbers = null; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 37 38 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 Chapter 14 Files and Streams try { pollNumbers = new Scanner( new File( "numbers.txt" ) ); writer = new Formatter( "output.txt" ); writer.format( "%-12s%-12s\n", "Rating", "Frequency" ); // for each answer, use that value as subscript to // determine element to increment while ( pollNumbers.hasNext() ) ++frequency[ pollNumbers.nextInt() ]; // append frequencies to String output for ( int rating = 1; rating < frequency.length; rating++ ) writer.format( "%-12d%-12d\n", rating, frequency[ rating ] ); } // end try catch ( FileNotFoundException fileNotFoundException ) { System.err.println( "Error: Files cannot be opened." ); } // end catch catch ( FormatterClosedException formatterClosedException ) { System.err.println( "Error: Output file is closed." ); } // end catch catch ( SecurityException securityException ) { System.err.println( "Error opening file for writing." ); } // end catch catch ( IllegalFormatException illegalFormatException ) { System.err.println( "Error writing data to file." ); } // end catch catch ( NoSuchElementException noSuchElementException ) { System.err.println( "Error reading from file." ); } // end catch catch ( IllegalStateException illegalStateException ) { System.err.println( "Error: Input file is closed." ); } // end catch finally { if ( writer != null ) writer.close(); if ( pollNumbers != null ) pollNumbers.close(); } // end finally } // end displayData } // end class StudentPoll © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 1 2 3 4 5 6 7 8 9 10 11 39 // Exercise 14.10 Solution: StudentPollTest.java // Testing the StudentPoll class. public class StudentPollTest { public static void main( String args[] ) { StudentPoll application = new StudentPoll(); application.displayData(); } // end main } // end class StudentPollTest ANS: Contents of output.txt after StudentPollTest.java has been executed. Rating 1 2 3 4 5 6 7 8 9 10 Frequency 0 3 1 1 2 0 3 2 5 0 14.11 Modify Exercise 11.18 to allow the user to save a drawing into a file or load a prior drawing from a file using object serialization. Add buttons Load (to read objects from a file) and Save (to write objects to a file). Use an ObjectOutputStream to write to the file and an ObjectInputStream to read from the file. Write the array of MyShape objects using method writeObject (class ObjectOutputStream), and read the array using method readObject (ObjectInputStream). Note that the object-serialization mechanism can read or write entire arrays—it is not necessary to manipulate each element of the array of MyShape objects individually. It is simply required that all the shapes be Serializable. Because the array of MyShape objects is of length 100 (and is not necessarily filled with shapes drawn by the user), you may also want to store the number of shapes drawn to the file. For both the Load and Save buttons, use a JFileChooser to allow the user to select the file in which the shapes will be stored or from which they will be read. When the user first runs the program, no shapes should be displayed on the screen. The user can display shapes by opening a previously saved file of shapes or by drawing their own shapes. Once there are shapes on the screen, users can save them to a file using the Save button. ANS: 1 2 3 4 5 6 // Exercise 14.11: MyShape.java // Declaration of class MyShape. import java.awt.Color; import java.awt.Graphics; import java.io.Serializable; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 40 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 Chapter 14 Files and Streams public abstract class MyShape implements Serializable { private int x1; // x coordinate of first endpoint private int y1; // y coordinate of first endpoint private int x2; // x coordinate of second endpoint private int y2; // y coordinate of second endpoint private Color myColor; // color of this shape // default constructor initializes values with 0 public MyShape() { this( 0, 0, 0, 0, Color.BLACK ); // call constructor to set values } // end MyShape no-argument constructor // constructor public MyShape( int x1, int y1, int x2, int y2, Color color ) { setX1( x1 ); // set x coordinate of first endpoint setY1( y1 ); // set y coordinate of first endpoint setX2( x2 ); // set x coordinate of second endpoint setY2( y2 ); // set y coordinate of second endpoint setColor( color ); // set the color } // end MyShape constructor // set the x-coordinate of the first point public void setX1( int x1 ) { this.x1 = ( x1 >= 0 ? x1 : 0 ); } // end method setX1 // get the x-coordinate of the first point public int getX1() { return x1; } // end method getX1 // set the x-coordinate of the second point public void setX2( int x2 ) { this.x2 = ( x2 >= 0 ? x2 : 0 ); } // end method setX2 // get the x-coordinate of the second point public int getX2() { return x2; } // end method getX2 // set the y-coordinate of the first point public void setY1( int y1 ) { this.y1 = ( y1 >= 0 ? y1 : 0 ); } // end method setY1 // get the y-coordinate of the first point © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public int getY1() { return y1; } // end method getY1 // set the y-coordinate of the second point public void setY2( int y2 ) { this.y2 = ( y2 >= 0 ? y2 : 0 ); } // end method setY2 // get the y-coordinate of the second point public int getY2() { return y2; } // end method getY2 // set the color public void setColor( Color color ) { myColor = color; } // end method setColor // get the color public Color getColor() { return myColor; } // end method getColor // abstract draw method public abstract void draw( Graphics g ); } // end class MyShape // Exercise 14.11: MyLine.java // Declaration of class MyLine. import java.awt.Color; import java.awt.Graphics; public class MyLine extends MyShape { // call default superclass constructor public MyLine() { super(); } // end MyLine no-argument constructor // call superclass constructor passing parameters public MyLine( int x1, int y1, int x2, int y2, Color color ) { super( x1, y1, x2, y2, color ); } // end MyLine constructor © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 41 42 Chapter 14 Files and Streams 20 21 22 23 24 25 26 // draw line in specified color public void draw( Graphics g ) { g.setColor( getColor() ); g.drawLine( getX1(), getY1(), getX2(), getY2() ); } // end method draw } // end class MyLine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 // Exercise 14.11: MyBoundedShape.java // Declaration of class MyBoundedShape. import java.awt.Color; import java.awt.Graphics; public abstract class MyBoundedShape extends MyShape { private boolean filled; // whether this shape is filled // call default superclass constructor public MyBoundedShape() { super(); setFilled( false ); } // end MyBoundedShape no-argument constructor // call superclass constructor passing parameters public MyBoundedShape( int x1, int y1, int x2, int y2, Color color, boolean isFilled ) { super( x1, y1, x2, y2, color ); setFilled( isFilled ); } // end MyBoundedShape constructor // get upper left x coordinate public int getUpperLeftX() { return Math.min( getX1(), getX2() ); } // end method getUpperLeftX // get upper left y coordinate public int getUpperLeftY() { return Math.min( getY1(), getY2() ); } // end method getUpperLeftY // get shape width public int getWidth() { return Math.abs( getX2() - getX1() ); } // end method getWidth // get shape height public int getHeight() © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 { return Math.abs( getY2() - getY1() ); } // end method getHeight // determines whether this shape is filled public boolean isFilled() { return filled; } // end method is filled // sets whether this shape is filled public void setFilled( boolean isFilled ) { filled = isFilled; } // end method setFilled } // end class MyBoundedShape // Exercise 14.11: MyRect.java // Declaration of class MyRect. import java.awt.Color; import java.awt.Graphics; public class MyRect extends MyBoundedShape { // call default superclass constructor public MyRect() { super(); } // end MyRect no-argument constructor // call superclass constructor passing parameters public MyRect( int x1, int y1, int x2, int y2, Color color, boolean isFilled ) { super( x1, y1, x2, y2, color, isFilled ); } // end MyRect constructor // draw rectangle public void draw( Graphics g ) { g.setColor( getColor() ); if ( isFilled() ) g.fillRect( getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight() ); else g.drawRect( getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight() ); } // end method draw } // end class MyRect © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 43 44 Chapter 14 Files and Streams 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 // Exercise 14.11: MyOval.java // Declaration of class MyOval. import java.awt.Color; import java.awt.Graphics; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // Exercise 14.11: DrawPanel.java // JPanel that allows the user to draw shapes with the mouse. import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import javax.swing.JFileChooser; import javax.swing.JLabel; public class MyOval extends MyBoundedShape { // call default superclass constructor public MyOval() { super(); } // end MyOval no-argument constructor // call superclass constructor passing parameters public MyOval( int x1, int y1, int x2, int y2, Color color, boolean isFilled ) { super( x1, y1, x2, y2, color, isFilled ); } // end MyOval constructor // draw oval public void draw( Graphics g ) { g.setColor( getColor() ); if ( isFilled() ) g.fillOval( getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight() ); else g.drawOval( getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight() ); } // end method draw } // end class MyOval © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 import javax.swing.JOptionPane; import javax.swing.JPanel; public class DrawPanel extends JPanel { private MyShape shapes[]; // array containing all the shapes private int shapeCount; // statistic on the number of each shape private private private private int shapeType; // the type of shape to draw MyShape currentShape; // the current shape being drawn Color currentColor; // the color of the shape boolean filledShape; // whether this shape is filled private JLabel statusLabel; // label displaying mouse coordinates // constructor public DrawPanel( JLabel status ) { shapes = new MyShape[ 100 ]; // create the array shapeCount = 0; // initially we have no shapes setShapeType( 0 ); // initially draw lines setDrawingColor( Color.BLACK ); // start drawing with black setFilledShape( false );// not filled by default currentShape = null; // not drawing anything initially setBackground( Color.WHITE ); // set a white background // add the mouse listeners MouseHandler mouseHandler = new MouseHandler(); addMouseListener( mouseHandler ); addMouseMotionListener( mouseHandler ); // set the status label for displaying mouse coordinates statusLabel = status; } // end DrawPanel constructor // draw shapes using polymorphism public void paintComponent( Graphics g ) { super.paintComponent( g ); for ( int i = 0; i < shapeCount; i++ ) shapes[ i ].draw( g ); if ( currentShape != null ) currentShape.draw( g ); } // end method paintComponent // sets the type of shape to draw public void setShapeType( int shapeType ) { if ( shapeType < 0 || shapeType > 2 ) shapeType = 0; © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 45 46 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 Chapter 14 Files and Streams this.shapeType = shapeType; } // end method setShapeType // sets the drawing color public void setDrawingColor( Color c ) { currentColor = c; } // end method setDrawingColor // clears the last shape drawn public void clearLastShape() { if ( shapeCount > 0 ) { shapeCount--; repaint(); } // end if } // end method clearLastShape // clears all drawings on this panel public void clearDrawing() { shapeCount = 0; repaint(); } // end method clearDrawing // sets whether to draw a filled shape public void setFilledShape( boolean isFilled ) { filledShape = isFilled; } // end method setFilledShape // load saved drawing public void loadDrawing() { ObjectInputStream input = null; try // user selects file, shapes are input { // use JFileChooser to select file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( DrawPanel.this ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // get selected file File fileName = fileChooser.getSelectedFile(); // display error if invalid © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 if ( ( fileName == null ) || ( fileName.getName().equals( "" ) ) ) { JOptionPane.showMessageDialog( DrawPanel.this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); return; } // end if // open file for input input = new ObjectInputStream( new FileInputStream( fileName ) ); // read in number of shapes using deserialization shapeCount = ( Integer ) input.readObject(); // read in shapes using deserialization // set shapes to be displayed on drawPanel shapes = ( MyShape [] ) input.readObject(); repaint(); // redraw shapes } // end try catch ( EOFException eofException ) { JOptionPane.showMessageDialog( DrawPanel.this, "No more records in file.", "End of File", JOptionPane.ERROR_MESSAGE ); } // end catch catch ( ClassNotFoundException classNotFoundException ) { JOptionPane.showMessageDialog( DrawPanel.this, "Unable to create object.", "Class Not Found", JOptionPane.ERROR_MESSAGE ); } // end catch catch ( IOException ioException ) { JOptionPane.showMessageDialog( DrawPanel.this, "Error opening file.", "Error", JOptionPane.ERROR_MESSAGE ); } // end catch finally { try { if ( input != null ) input.close(); // close file and stream } // end try catch ( IOException ioException ) { JOptionPane.showMessageDialog( DrawPanel.this, "Error closing file.", "Error", JOptionPane.ERROR_MESSAGE ); } // end catch } // end finally } // end method loadDrawing © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 47 48 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 Chapter 14 Files and Streams // save drawing as serialized objects public void saveDrawing() { ObjectOutputStream output = null; try { // use JFileChooser to select file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showSaveDialog( DrawPanel.this ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // get selected file File fileName = fileChooser.getSelectedFile(); // display error if invalid if ( ( fileName == null ) || ( fileName.getName().equals( "" ) ) ) { JOptionPane.showMessageDialog( DrawPanel.this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); return; } // end if // open file for output output = new ObjectOutputStream( new FileOutputStream( fileName ) ); // write number of shapes to file output.writeObject( shapeCount ); // write shapes to file using serialization output.writeObject( shapes ); } // end try catch ( IOException ioException ) { JOptionPane.showMessageDialog( DrawPanel.this, "Error Opening File", "Error.", JOptionPane.ERROR_MESSAGE ); } // end catch finally { try { if ( output != null ) output.close(); // close file and stream } // end try © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 catch ( IOException ioException ) { JOptionPane.showMessageDialog( DrawPanel.this, "Error closing file.", "Error", JOptionPane.ERROR_MESSAGE ); } // end catch } // end finally } // end method saveDrawing // Handles mouse events for this JPanel private class MouseHandler extends MouseAdapter implements MouseMotionListener { // creates and sets the initial position for the new shape public void mousePressed( MouseEvent e ) { if ( currentShape != null ) return; // create the appropriate shape based on shapeType switch ( shapeType ) { case 0: currentShape = new MyLine( e.getX(), e.getY(), e.getX(), e.getY(), currentColor ); break; case 1: currentShape = new MyOval( e.getX(), e.getY(), e.getX(), e.getY(), currentColor, filledShape ); break; case 2: currentShape = new MyRect( e.getX(), e.getY(), e.getX(), e.getY(), currentColor, filledShape ); break; } // end switch } // end method mousePressed // fixes the current shape onto the panel public void mouseReleased( MouseEvent e ) { if ( currentShape == null ) return; // set the second point on the shape currentShape.setX2( e.getX() ); currentShape.setY2( e.getY() ); // only set the shape if there is room in the array if ( shapeCount < shapes.length ) { shapes[ shapeCount ] = currentShape; shapeCount++; } // end if currentShape = null; // clear the temporary drawing shape © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 49 50 Chapter 14 Files and Streams 293 repaint(); 294 } // end method mouseReleased 295 296 // update the shape to the current mouse position while dragging 297 public void mouseDragged( MouseEvent e ) 298 { 299 if ( currentShape != null ) 300 { 301 currentShape.setX2( e.getX() ); 302 currentShape.setY2( e.getY() ); 303 repaint(); 304 } // end if 305 306 mouseMoved( e ); // update status bar 307 } // end method mouseDragged 308 309 // updates the status bar to show the current mouse coordinates 310 public void mouseMoved( MouseEvent e ) 311 { 312 statusLabel.setText( 313 String.format( "(%d,%d)", e.getX(), e.getY() ) ); 314 } // end method mouseMoved 315 } // end class MouseHandler 316 } // end class DrawPanel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Exercise 14.11: DrawFrame.java // Program that creates a panel for the user to draw shapes. // Allows the user to choose the shape and color. import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class DrawFrame extends JFrame implements ItemListener, ActionListener { // Array of possible colors private Color colors[] = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW }; // Array of names corresponding to the possible colors © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 51 private String colorNames[] = { "Black", "Blue", "Cyan", "Dark Gray", "Gray", "Green", "Light Gray", "Magenta", "Orange", "Pink", "Red", "White", "Yellow" }; // Array of possible shapes private String shapes[] = { "Line", "Oval", "Rectangle" }; private DrawPanel drawPanel; // panel that handles the drawing private private private private private private private JButton loadButton; // button to load saved drawing JButton saveButton; // button to save drawing to file JButton undoButton; // button to undo the last shape drawn JButton clearButton; // button to clear all shapes JComboBox colorChoices; // combo box for selecting the color JComboBox shapeChoices; // combo box for selecting shapes JCheckBox filledCheckBox; // check box to toggle filled shapes // constructor public DrawFrame() { super( "Java Drawings" ); // create a panel to store the components at the top of the frame JPanel topPanel = new JPanel( new FlowLayout() ); // create a button for loading a saved drawing loadButton = new JButton( "Load" ); loadButton.addActionListener( this ); topPanel.add( loadButton ); // create a button for saving drawing saveButton = new JButton( "Save" ); saveButton.addActionListener( this ); topPanel.add( saveButton ); // create a button for clearing the last drawing undoButton = new JButton( "Undo" ); undoButton.addActionListener( this ); topPanel.add( undoButton ); // create a button for clearing all drawings clearButton = new JButton( "Clear" ); clearButton.addActionListener( this ); topPanel.add( clearButton ); // create a combo-box for choosing colors colorChoices = new JComboBox( colorNames ); colorChoices.addItemListener( this ); topPanel.add( colorChoices ); // create a combo-box for choosing shapes shapeChoices = new JComboBox( shapes ); shapeChoices.addItemListener( this ); topPanel.add( shapeChoices ); © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 52 Chapter 14 Files and Streams 83 // create a check-box to determine whether the shape is filled 84 filledCheckBox = new JCheckBox( "Filled" ); 85 filledCheckBox.addItemListener( this ); 86 topPanel.add( filledCheckBox ); 87 88 // add the top panel to the frame 89 add( topPanel, BorderLayout.NORTH ); 90 91 // create a label for the status bar 92 JLabel statusLabel = new JLabel( "(0,0)" ); 93 94 // add the status bar at the bottom 95 add( statusLabel, BorderLayout.SOUTH ); 96 97 // create the DrawPanel with its status bar label 98 drawPanel = new DrawPanel( statusLabel ); 99 100 add( drawPanel ); // add the drawing area to the center 101 } // end DrawFrame constructor 102 103 // handle selections made to a combo box of check box 104 public void itemStateChanged( ItemEvent e ) 105 { 106 if ( e.getSource() == shapeChoices ) // choosing a shape 107 drawPanel.setShapeType( shapeChoices.getSelectedIndex() ); 108 else if (e.getSource() == colorChoices ) // choosing a color 109 drawPanel.setDrawingColor( 110 colors[ colorChoices.getSelectedIndex() ] ); 111 else if ( e.getSource() == filledCheckBox ) // filled/unfilled 112 drawPanel.setFilledShape( filledCheckBox.isSelected() ); 113 } // end method itemStateChanged 114 115 // handle button clicks 116 public void actionPerformed( ActionEvent e ) 117 { 118 if ( e.getSource() == loadButton ) 119 drawPanel.loadDrawing(); 120 else if ( e.getSource() == saveButton ) 121 drawPanel.saveDrawing(); 122 else if ( e.getSource() == undoButton ) 123 drawPanel.clearLastShape(); 124 else if ( e.getSource() == clearButton ) 125 drawPanel.clearDrawing(); 126 } // end method actionPerformed 127 } // end class DrawFrame 1 2 3 4 5 6 // Exercise 14.11: TestDraw.java // Test application to display a DrawFrame import javax.swing.JFrame; public class TestDraw { © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises 7 8 9 10 11 12 13 14 public static void main( String args[] ) { DrawFrame application = new DrawFrame(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.setSize( 600, 500 ); application.setVisible( true ); } // end main } // end class TestDraw © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 53 54 Chapter 14 Files and Streams © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. Exercises © Copyright 1992-2007 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. 55