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
Chapter 16 – Files and Streams Outline 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 16.10 16.11 16.12 Introduction Data Hierarchy Files and Streams Creating a Sequential-Access File Reading Data from a Sequential-Access File Updating Sequential-Access File Random-Access File Creating a Random-Access File Writing Data Randomly to a Random-Access File Reading Data Sequentially from a Random-Access File Example: A Transaction-Processing Program Class File 2002 Prentice Hall, Inc. All rights reserved. 16.1 Introduction • Files – Long-term storage of large amounts of data – Persistent data exists after termination of program – Files stored on secondary storage devices • Magnetic disks • Optical disks • Magnetic tapes – Sequential and random access files 2002 Prentice Hall, Inc. All rights reserved. 16.2 Data Hierarchy • Smallest data item in a computer is a bit – Bit can be either 0 or 1 – Bit short for “binary digit” • Programmers work with higher level data items – – – – Decimal digits: (0-9) Letters: (A-Z and a-z) Special symbols: (e.g., $, @, %, &, *, (, ), -, +, “, :, ?, /, etc.) Java uses Unicode characters composed of 2 bytes • A byte is normally 8 bits long • Fields (Java instance variables) – Composed of characters or bytes – Conveys meaning 2002 Prentice Hall, Inc. All rights reserved. 16.2 Data Hierarchy • Data hierarchy – Data items in a computer form a hierarchy • Progresses from bits, to characters, to fields, etc. • Records – Composed of several fields – Implemented as a class in Java – See Fig. 16.1 for example • File is a group of related records – One field in each record is a record key • Record key is a unique identifier for a record – Sequential file • Records stored in order by record key 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.1 The data hierarchy. Sally Black Tom Blue Judy Green Iris Orange Randy Red Judy Green J u dy 01001010 1 Bit 2002 Prentice Hall, Inc. All rights reserved. File Rec ord Fie ld Byte (ASC II c hara c ter J) 16.3 Files and Streams • Java views a file as a stream of bytes (Fig. 16.2) – File ends with end-of-file marker or a specific byte number – File as a stream of bytes associated with an object • Java also associates streams with devices – System.in, System.out, and System.err – Streams can be redirected • File processing with classes in package java.io – – – – – FileInputStream for byte-based input from a file FileOutputStream for byte-based output to a file FileReader for character-based input from a file FileWriter for character-based output to a file Fig 16.3 summarizes inheritance relationships in java.io 2002 Prentice Hall, Inc. All rights reserved. 16.3 Files and Streams • Buffering – Improves performance of I/O – Copies each output to a region of memory called a buffer – Entire buffer output to disk at once • One long disk access takes less time than many smaller ones – BufferedInputStream buffers file output – BufferedOutputStream buffers file input 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.2 Java’s view of a file of n bytes. 0 1 2 3 4 5 6 7 8 9 ... n-1 end -o f-file marker ... 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.3 A portion of the class hierarchy of the java.io package. A portion of the class hierarchy of the java.io package java.lang.Object File FileDescriptor InputStream ByteArrayInputStream FileInputStream FilterInputStream BufferedInputStream DataInputStream PushbackInputStream ObjectInputStream PipedInputStream SequenceInputStream OutputStream ByteArrayOutputStream FileOutputStream FilterOutputStream BufferedOutputStream DataOutputStream PrintStream ObjectOutputStream PipedOutputStream 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.3 A portion of the class hierarchy of the java.io package (cont.). RandomAccessFile Reader BufferedReader LineNumberReader CharArrayReader FilterReader PushbackReader InputStreamReader FileReader PipedReader StringReader Writer BufferedWriter CharArrayWriter FilterWriter OutputStreamWriter FileWriter PipedWriter PrintWriter StringWriter 2002 Prentice Hall, Inc. All rights reserved. 16.4 Creating a Sequential-Access File • Java Files – Java imposes no structure on a file – Programmer structures file according to application – Following program uses simple record structure 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.4: BankUI.java // A reusable GUI for the examples in this chapter. package com.deitel.jhtp4.ch16; // Java core packages import java.awt.*; // Java extension packages import javax.swing.*; public class BankUI extends JPanel { // label text for GUI protected final static String names[] = { "Account number", "First name", "Last name", "Balance", "Transaction Amount" }; // GUI components; protected for future subclass access protected JLabel labels[]; protected JTextField fields[]; protected JButton doTask1, doTask2; protected JPanel innerPanelCenter, innerPanelSouth; Outline Fig. 16.4 BankUI contains a reusable GUI for several programs. Bank GUI for all Line 11 examples in this chapter Lines 19-22 JButtons, JLabels and JTextFields for the GUI // number of text fields in GUI protected int size; // constants representing text fields in GUI public static final int ACCOUNT = 0, FIRSTNAME = 1, LASTNAME = 2, BALANCE = 3, TRANSACTION = 4; 2002 Prentice Hall, Inc. All rights reserved. 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 // Set up GUI. Constructor argument of 4 creates four rows // of GUI components. Constructor argument of 5 (used in a // later program) creates five rows of GUI components. public BankUI( int mySize ) { size = mySize; labels = new JLabel[ size ]; fields = new JTextField[ size ]; // create labels for ( int count = 0; count < labels.length; count++ ) labels[ count ] = new JLabel( names[ count ] ); Outline BankUI constructor initializes and Fig. 16.4 GUI BankUI sets number of contains a reusable and GUIJLabels for several JTextFields programs (Part 2). Lines 34-75 // create text fields for ( int count = 0; count < fields.length; count++ ) fields[ count ] = new JTextField(); // create panel to lay out labels and fields innerPanelCenter = new JPanel(); innerPanelCenter.setLayout( new GridLayout( size, 2 ) ); // attach labels and fields to innerPanelCenter for ( int count = 0; count < size; count++ ) { innerPanelCenter.add( labels[ count ] ); innerPanelCenter.add( fields[ count ] ); } // create generic buttons; no labels or event handlers doTask1 = new JButton(); doTask2 = new JButton(); 2002 Prentice Hall, Inc. All rights reserved. 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 90 91 92 93 // create panel to lay out buttons and attach buttons innerPanelSouth = new JPanel(); innerPanelSouth.add( doTask1 ); innerPanelSouth.add( doTask2 ); // set layout of this container and attach panels to it setLayout( new BorderLayout() ); add( innerPanelCenter, BorderLayout.CENTER ); add( innerPanelSouth, BorderLayout.SOUTH ); // validate layout validate(); } // end constructor // return reference to generic task button doTask1 public JButton getDoTask1Button() { return doTask1; } // return reference to generic task button doTask2 public JButton getDoTask2Button() { return doTask2; } Outline Fig. 16.4 BankUI contains a reusable Method GUI for several getDoTask1Button programs 3). returns reference(Part to button doTask1 Lines 78-81 Method Lines 84-87 getDoTask2Button returns reference Lines 90-93to button doTask2 Method getFields returns reference to array of JTextFields // return reference to fields array of JTextFields public JTextField[] getFields() { return fields; } 2002 Prentice Hall, Inc. All rights reserved. 94 95 // clear content of text fields 96 public void clearFields() 97 { 98 for ( int count = 0; count < size; count++ ) 99 fields[ count ].setText( "" ); 100 } 101 102 // set text field values; throw IllegalArgumentException if 103 // incorrect number of Strings in argument 104 public void setFieldValues( String strings[] ) 105 throws IllegalArgumentException 106 { 107 if ( strings.length != size ) 108 throw new IllegalArgumentException( "There must be " + 109 size + " Strings in the array" ); 110 111 for ( int count = 0; count < size; count++ ) 112 fields[ count ].setText( strings[ count ] ); 113 } 114 115 // get array of Strings with current text field contents 116 public String[] getFieldValues() 117 { 118 String values[] = new String[ size ]; 119 120 for ( int count = 0; count < size; count++ ) 121 values[ count ] = fields[ count ].getText(); 122 123 return values; 124 } 125 126 } // end class BankUI Outline Method clearFields deletes all text in the Fig. 16.4 BankUI JTextFields contains a reusable GUI for several programs (Part 4). Method setFieldValues Lines 96-100 sets the values of the JTextFields Lines 104-113 Lines 116-124 Method getFieldValues returns the values of the JTextFields 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.5: AccountRecord.java // A class that represents one record of information. package com.deitel.jhtp4.ch16; // Java core packages import java.io.Serializable; public class AccountRecord implements Serializable { 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 ); } ImplementsOutline interface Serializable so AccountRecords can be Fig. 16.5 used withClass AccountRecord ObjectInputStreams maintains and information for one ObjectOutputStreams account. Line 8 account, Fields firstName, Lines 9-12 and lastName balance hold record information // initialize a record public AccountRecord( int acct, String first, String last, double bal ) { setAccount( acct ); setFirstName( first ); setLastName( last ); setBalance( bal ); } // set account number public void setAccount( int acct ) { account = acct; } 2002 Prentice Hall, Inc. All rights reserved. 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 // get account number public int getAccount() { return account; } // set first name public void setFirstName( String first ) { firstName = first; } Outline Fig. 16.5 Class AccountRecord maintains information for one account (Part 2). // get first name public String getFirstName() { return firstName; } // set last name public void setLastName( String last ) { lastName = last; } // get last name public String getLastName() { return lastName; } 2002 Prentice Hall, Inc. All rights reserved. 66 67 68 69 70 71 72 73 74 75 76 77 78 79 } // set balance public void setBalance( double bal ) { balance = bal; } // get balance public double getBalance() { return balance; } Outline Fig. 16.5 Class AccountRecord maintains information for one account (Part 3). // end class AccountRecord 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.6: CreateSequentialFile.java // Demonstrating object output with class ObjectOutputStream. // The objects are written sequentially to a file. // Java core packages import java.io.*; import java.awt.*; import java.awt.event.*; Outline Fig. 16.6 Creating a sequential file. // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.BankUI; import com.deitel.jhtp4.ch16.AccountRecord; public class CreateSequentialFile extends JFrame { private ObjectOutputStream output; private BankUI userInterface; private JButton enterButton, openButton; // set up GUI public CreateSequentialFile() { super( "Creating a Sequential File of Objects" ); // create instance of reusable user interface userInterface = new BankUI( 4 ); // four textfields getContentPane().add( userInterface, BorderLayout.CENTER ); // get reference to generic task button doTask1 in BankUI // and configure button for use in this program openButton = userInterface.getDoTask1Button(); openButton.setText( "Save into File ..." ); 2002 Prentice Hall, Inc. All rights reserved. 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 // register listener to call openFile when button pressed openButton.addActionListener( // anonymous inner class to handle openButton event new ActionListener() { // call openFile when button pressed public void actionPerformed( ActionEvent event ) { openFile(); } } Outline Fig. 16.6 Creating a sequential file (Part 2). Lines 66-69 // end anonymous inner class ); // end call to addActionListener // get reference to generic task button doTask2 in BankUI // and configure button for use in this program enterButton = userInterface.getDoTask2Button(); enterButton.setText( "Enter" ); enterButton.setEnabled( false ); // disable button // register listener to call addRecord when button pressed enterButton.addActionListener( // anonymous inner class to handle enterButton event new ActionListener() { // call addRecord when button pressed public void actionPerformed( ActionEvent event ) { addRecord(); } Method actionPerformed calls method addRecord 2002 Prentice Hall, Inc. All rights reserved. 70 71 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 } // end anonymous inner class ); // end call to addActionListener // register window listener to handle window closing event addWindowListener( // anonymous inner class to handle windowClosing event new WindowAdapter() { Outline Fig. 16.6 Creating aAdd sequential file to current record (Part file 3). and close file when closing window Lines 82-88 // add current record in GUI to file, then close file public void windowClosing( WindowEvent event ) { if ( output != null ) addRecord(); closeFile(); } } // end anonymous inner class ); // end call to addWindowListener setSize( 300, 200 ); show(); } // end CreateSequentialFile constructor 2002 Prentice Hall, Inc. All rights reserved. 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 // allow user to specify file name private void openFile() { // display file dialog, so user can choose file to open JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showSaveDialog( 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( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file try { output = new ObjectOutputStream( new FileOutputStream( fileName ) ); openButton.setEnabled( false ); enterButton.setEnabled( true ); } Instantiate a Outline JFileChooser and assign it to Fig. 16.6 Creating fileChooser a sequential file (Part 4). Method call setFileSelectionMode LineFILES_ONLY 103 with constant indicates only files can be Lines 104-105 selected Line 107 Method showSaveDialog Line 110 causes the JFileChooser Line titled 114 Save to appear Lines Return127-128 if user clicked Cancel button on dialog Retrieve selected file Open selected file 2002 Prentice Hall, Inc. All rights reserved. 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 // process exceptions from opening file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Opening File", "Error", JOptionPane.ERROR_MESSAGE ); } } } // end method openFile // close file and terminate application private void closeFile() { // close file try { output.close(); Outline Fig. 16.6 Creating a sequential file (Part 5). Lines 145-161 Method closeFile closes the current file System.exit( 0 ); } // process exceptions from closing file catch( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); } } 2002 Prentice Hall, Inc. All rights reserved. 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 // add record to file public void addRecord() { int accountNumber = 0; AccountRecord record; String fieldValues[] = userInterface.getFieldValues(); // if account field value is not empty if ( ! fieldValues[ BankUI.ACCOUNT ].equals( "" ) ) { // output values to file try { accountNumber = Integer.parseInt( fieldValues[ BankUI.ACCOUNT ] ); Method Outline addRecord performs the write operation Fig. 16.6 Creating a sequential file (Part 6). Lines 164-211 Line 188 Line 189 if ( accountNumber > 0 ) { // create new record record = new AccountRecord( accountNumber, fieldValues[ BankUI.FIRSTNAME ], fieldValues[ BankUI.LASTNAME ], Double.parseDouble( fieldValues[ BankUI.BALANCE ] ) ); // output record and flush buffer output.writeObject( record ); output.flush(); } // clear textfields userInterface.clearFields(); Method writeObject writes the record object to file Method flush ensures all data in memory written to file } 2002 Prentice Hall, Inc. All rights reserved. 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 } // process invalid account number or balance format catch ( NumberFormatException formatException ) { JOptionPane.showMessageDialog( this, "Bad account number or balance", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } Outline Fig. 16.6 Creating a sequential file (Part 7). // process exceptions from file output catch ( IOException ioException ) { closeFile(); } } } // end if // end method addRecord // execute application; CreateSequentialFile constructor // displays window public static void main( String args[] ) { new CreateSequentialFile(); } // end class CreateSequentialFile 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.6 Creating a sequential file (Part 8). Select location for file here Click Save to submit new file name to program Files and directories are displayed here BankUI graphical user interface 2002 Prentice Hall, Inc. All rights reserved. 16.5 Reading Data from a SequentialAccess File • Data stored in files – Retrieved for processing when needed – Accessing a sequential file • Data must be read in same format it was written 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.7 Sample data for the program of Fig. 16.6. Sample Data 100 Bob Jones 24.98 200 300 400 500 Steve Pam Sam Sue Doe White Stone Rich -345.67 0.00 -42.16 224.62 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.8: ReadSequentialFile.java // This program reads a file of objects sequentially // and displays each record. // Java core packages import java.io.*; import java.awt.*; import java.awt.event.*; Outline Fig. 16.8 Reading a sequential file. // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.*; public class ReadSequentialFile extends JFrame { private ObjectInputStream input; private BankUI userInterface; private JButton nextButton, openButton; // Constructor -- initialize the Frame public ReadSequentialFile() { super( "Reading a Sequential File of Objects" ); // create instance of reusable user interface userInterface = new BankUI( 4 ); // four textfields getContentPane().add( userInterface, BorderLayout.CENTER ); // get reference to generic task button doTask1 from BankUI openButton = userInterface.getDoTask1Button(); openButton.setText( "Open File" ); 2002 Prentice Hall, Inc. All rights reserved. 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 // register listener to call openFile when button pressed openButton.addActionListener( // anonymous inner class to handle openButton event new ActionListener() { // close file and terminate application public void actionPerformed( ActionEvent event ) { openFile(); } } Outline Fig. 16.8 Reading a sequential file (Part 2). // end anonymous inner class ); // end call to addActionListener // register window listener for window closing event addWindowListener( // anonymous inner class to handle windowClosing event new WindowAdapter() { // close file and terminate application public void windowClosing( WindowEvent event ) { if ( input != null ) closeFile(); System.exit( 0 ); } } // end anonymous inner class ); // end call to addWindowListener 2002 Prentice Hall, Inc. All rights reserved. 70 71 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 // get reference to generic task button doTask2 from BankUI nextButton = userInterface.getDoTask2Button(); nextButton.setText( "Next Record" ); nextButton.setEnabled( false ); // register listener to call readRecord when button pressed nextButton.addActionListener( // anonymous inner class to handle nextRecord event new ActionListener() { // call readRecord when user clicks nextRecord public void actionPerformed( ActionEvent event ) { readRecord(); } } Outline Fig. 16.8 Reading a sequential file (Part 3). Line 84 Method actionPerformed calls method readRecord // end anonymous inner class ); // end call to addActionListener pack(); setSize( 300, 200 ); show(); } // end ReadSequentialFile constructor // enable user to select file to open private void openFile() { // display file dialog so user can select file to open JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); 2002 Prentice Hall, Inc. All rights reserved. 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 int result = fileChooser.showOpenDialog( this ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // obtain selected file File fileName = fileChooser.getSelectedFile(); Method Outline showOpenDialog displays the Open file dialog Fig. 16.8 Reading a sequential file (Part 4). Line 105 // display error if file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) JOptionPane.showMessageDialog( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); Lines 125-126 else { // open file try { input = new ObjectInputStream( new FileInputStream( fileName ) ); ObjectInputStream object created and assigned to input openButton.setEnabled( false ); nextButton.setEnabled( true ); } // process exceptions opening file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Opening File", "Error", JOptionPane.ERROR_MESSAGE ); } 2002 Prentice Hall, Inc. All rights reserved. 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 } } // end else // end method openFile // read record from file public void readRecord() { AccountRecord record; // input the values from the file try { record = ( AccountRecord ) input.readObject(); // create array of Strings to display in GUI String values[] = { String.valueOf( record.getAccount() ), record.getFirstName(), record.getLastName(), String.valueOf( record.getBalance() ) }; Outline Fig. 16.8 Reading a sequential file (Part Method 5). readRecord reads a record from the file Lines 144-187 Method readObject reads an 150 Object from Line the ObjectInputStream // display record contents userInterface.setFieldValues( values ); } // display message when end-of-file reached catch ( EOFException endOfFileException ) { nextButton.setEnabled( false ); JOptionPane.showMessageDialog( this, "No more records in file", "End of File", JOptionPane.ERROR_MESSAGE ); } 2002 Prentice Hall, Inc. All rights reserved. 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 202 // display error message if cannot read object // because class not found catch ( ClassNotFoundException classNotFoundException ) { JOptionPane.showMessageDialog( this, "Unable to create object", "Class Not Found", JOptionPane.ERROR_MESSAGE ); } Outline Fig. 16.8 Reading a sequential file (Part 6). // display error message if cannot read // due to problem with file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error during read from file", "Read Error", JOptionPane.ERROR_MESSAGE ); } } // close file and terminate application private void closeFile() { // close file and exit try { input.close(); System.exit( 0 ); } // process exception while closing file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); 2002 Prentice Hall, Inc. All rights reserved. 203 204 205 206 207 208 209 210 211 212 213 214 215 } System.exit( 1 ); Outline } } // execute application; ReadSequentialFile constructor // displays window public static void main( String args[] ) { new ReadSequentialFile(); } Fig. 16.8 Reading a sequential file (Part 7). // end class ReadSequentialFile 2002 Prentice Hall, Inc. All rights reserved. 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 // // // // // Fig. 16.9: CreditInquiry.java This program reads a file sequentially and displays the contents in a text area based on the type of account the user requests (credit balance, debit balance or zero balance). // Java core packages import java.io.*; import java.awt.*; import java.awt.event.*; import java.text.DecimalFormat; Outline Fig. 16.9 Credit inquiry program. Line 20 // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.AccountRecord; public class CreditInquiry extends JFrame { private JTextArea recordDisplayArea; private JButton openButton, creditButton, debitButton, zeroButton; private JPanel buttonPanel; private private private private JTextArea recordDisplayArea shows record information ObjectInputStream input; FileInputStream fileInput; File fileName; String accountType; // set up GUI public CreditInquiry() { super( "Credit Inquiry Program" ); 2002 Prentice Hall, Inc. All rights reserved. 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 Container container = getContentPane(); Outline // set up panel for buttons buttonPanel = new JPanel(); // create and configure button to open file openButton = new JButton( "Open File" ); buttonPanel.add( openButton ); Fig. 16.9 Credit inquiry program (Part 2). // register openButton listener openButton.addActionListener( // anonymous inner class to handle openButton event new ActionListener() { // open file for processing public void actionPerformed( ActionEvent event ) { openFile( true ); } } // end anonymous inner class ); // end call to addActionListener // create and configure button to get // accounts with credit balances creditButton = new JButton( "Credit balances" ); buttonPanel.add( creditButton ); creditButton.addActionListener( new ButtonHandler() ); // create and configure button to get // accounts with debit balances debitButton = new JButton( "Debit balances" ); buttonPanel.add( debitButton ); debitButton.addActionListener( new ButtonHandler() ); 2002 Prentice Hall, Inc. All rights reserved. 71 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 // create and configure button to get // accounts with credit balances zeroButton = new JButton( "Zero balances" ); buttonPanel.add( zeroButton ); zeroButton.addActionListener( new ButtonHandler() ); // set up display area recordDisplayArea = new JTextArea(); JScrollPane scroller = new JScrollPane( recordDisplayArea ); Outline Fig. 16.9 Credit inquiry program (Part 3). // attach components to content pane container.add( scroller, BorderLayout.CENTER ); container.add( buttonPanel, BorderLayout.SOUTH ); // disable creditButton, debitButton and zeroButton creditButton.setEnabled( false ); debitButton.setEnabled( false ); zeroButton.setEnabled( false ); // register window listener addWindowListener( // anonymous inner class for windowClosing event new WindowAdapter() { // close file and terminate program public void windowClosing( WindowEvent event ) { closeFile(); System.exit( 0 ); } } // end anonymous inner class 2002 Prentice Hall, Inc. All rights reserved. 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 ); // end call to addWindowListener // pack components and display window pack(); setSize( 600, 250 ); show(); } Outline Fig. 16.9 Credit inquiry program (Part 4). // end CreditInquiry constructor // enable user to choose file to open first time; // otherwise, reopen chosen file private void openFile( boolean firstTime ) { if ( firstTime ) { // display dialog, so user can choose file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // obtain selected file fileName = fileChooser.getSelectedFile(); } 2002 Prentice Hall, Inc. All rights reserved. 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 // display error if file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) JOptionPane.showMessageDialog( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { Outline Fig. 16.9 Credit inquiry program (Part 5). // open file try { // close file from previous operation if ( input != null ) input.close(); fileInput = new FileInputStream( fileName ); input = new ObjectInputStream( fileInput ); openButton.setEnabled( false ); creditButton.setEnabled( true ); debitButton.setEnabled( true ); zeroButton.setEnabled( true ); } // catch problems manipulating file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "File does not exist", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); } } } // end method openFile 2002 Prentice Hall, Inc. All rights reserved. 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 202 203 // close file before application terminates private void closeFile() { // close file try { input.close(); } // process exception from closing file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); Outline Fig. 16.9 Credit inquiry program (Part 6). Lines 191-238 System.exit( 1 ); } } // read records from file and display only records of // appropriate type private void readRecords() { AccountRecord record; DecimalFormat twoDigits = new DecimalFormat( "0.00" ); openFile( false ); Method readRecords reads records from file and displays only records of appropriate type // read records try { recordDisplayArea.setText( "The accounts are:\n" ); // input the values from the file while ( true ) { 2002 Prentice Hall, Inc. All rights reserved. 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 // read one AccountRecord record = ( AccountRecord ) input.readObject(); // if proper acount type, display record if ( shouldDisplay( record.getBalance() ) ) recordDisplayArea.append( record.getAccount() + "\t" + record.getFirstName() + "\t" + record.getLastName() + "\t" + twoDigits.format( record.getBalance() ) + "\n" ); } } // close file when end-of-file reached catch ( EOFException eofException ) { closeFile(); } // display error if cannot read object // because class not found catch ( ClassNotFoundException classNotFound ) { JOptionPane.showMessageDialog( this, "Unable to create object", "Class Not Found", JOptionPane.ERROR_MESSAGE ); } Outline Fig. 16.9 Credit inquiry program (Part 7). If proper account type, append record Line 208-213 to JTextArea Line 219 Close file when endof-file reached // display error if cannot read // because problem with file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error reading from file", "Error", JOptionPane.ERROR_MESSAGE ); } } // end method readRecords 2002 Prentice Hall, Inc. All rights reserved. 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 // uses record ty to determine if a record should be displayed private boolean shouldDisplay( double balance ) { if ( accountType.equals( "Credit balances" ) && balance < 0 ) return true; else if ( accountType.equals( "Debit balances" ) && balance > 0 ) Outline Method shouldDisplay determines if a record Fig. 16.9 Credit should be displayed inquiry program (Part 8). Lines 241-259 return true; else if ( accountType.equals( "Zero balances" ) && balance == 0 ) return true; return false; } // execute application public static void main( String args[] ) { new CreditInquiry(); } // private inner class for creditButton, debitButton and // zeroButton event handling private class ButtonHandler implements ActionListener { 2002 Prentice Hall, Inc. All rights reserved. 271 272 273 274 275 276 277 278 279 280 } // read records from file public void actionPerformed( ActionEvent event ) { accountType = event.getActionCommand(); readRecords(); } } // end class ButtonHandler // end class CreditInquiry ClickingOutline a button sets accountType to the clicked button’s Fig. 16.9 Credit text and invokes inquirymethod program (Part 9). readRecords Line 274-275 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.9 Credit inquiry program (Part 10). 2002 Prentice Hall, Inc. All rights reserved. 16.6 Updating Sequential-Access File • Difficult to update a sequential-access file – Entire file must be rewritten to change one field – Only acceptable if many records being updated at once 2002 Prentice Hall, Inc. All rights reserved. 16.7 Random-Access File • “Instant-access” applications – Record must be located immediately – Transaction-processing systems require rapid access • Random-access files – Access individual records directly and quickly – Use fixed length for every record • Easy to calculate record locations – Insert records without destroying other data in file – Fig. 16.10 shows random-access file 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.10 Java’s view of a random-access file. 0 100 100 b yte s 200 100 b yte s 2002 Prentice Hall, Inc. All rights reserved. 100 b yte s 300 100 b yte s 400 100 b yte s 500 100 b yte s by te offsets 16.8 Creating a Random-Access File • RandomAccessFile objects – Like DataInputStream and DataOutputstream – Reads or writes data in spot specified by file-position pointer • Manipulates all data as primitive types • Normally writes one object at a time to file 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.11: RandomAccessAccountRecord.java // Subclass of AccountRecord for random access file programs. package com.deitel.jhtp4.ch16; // Java core packages import java.io.*; public class RandomAccessAccountRecord extends AccountRecord { // no-argument constructor calls other constructor // with default values public RandomAccessAccountRecord() { this( 0, "", "", 0.0 ); } // initialize a RandomAccessAccountRecord public RandomAccessAccountRecord( int account, String firstName, String lastName, double balance ) { super( account, firstName, lastName, balance ); } // read a record from specified RandomAccessFile public void read( RandomAccessFile file ) throws IOException { setAccount( file.readInt() ); setFirstName( padName( file ) ); setLastName( padName( file ) ); setBalance( file.readDouble() ); } Outline Class inherits all of AccountRecord’s methods and instance Fig. 16.11 variables RandomAccessAccountRecord class used in the random-access file programs. Method read reads one Line 8 record from the RandomAccessFile Lines 25-31 object passed as an argument Line 27 Line 30 readInt Method reads variable account Method readDouble reads variable balance 2002 Prentice Hall, Inc. All rights reserved. 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 // ensure that name is proper length private String padName( RandomAccessFile file ) throws IOException { char name[] = new char[ 15 ], temp; for ( int count = 0; count < name.length; count++ ) { temp = file.readChar(); name[ count ] = temp; } return new String( name ).replace( '\0', ' ' ); } // write a record to specified RandomAccessFile public void write( RandomAccessFile file ) throws IOException { file.writeInt( getAccount() ); writeName( file, getFirstName() ); writeName( file, getLastName() ); file.writeDouble( getBalance() ); } // write a name to file; maximum of 15 characters private void writeName( RandomAccessFile file, String name ) throws IOException { StringBuffer buffer = null; Method padName Outline reads fifteen characters and from the file and returns a Fig. 16.11 String RandomAccessAccountRecord Replace nullinbytes class used the with spaces file random-access programs (Part 2). Method write outputs one record Lines 34-45to the RandomAccessFile passed as an argument Line 44 Lines 48-54 Lines 57-69 Method writeName performs write operation for first and last name if ( name != null ) buffer = new StringBuffer( name ); else buffer = new StringBuffer( 15 ); 2002 Prentice Hall, Inc. All rights reserved. 67 68 69 70 71 72 73 74 75 76 77 78 } buffer.setLength( 15 ); file.writeChars( buffer.toString() ); Outline } // NOTE: This method contains a hard coded value for the // size of a record of information. public static int size() { return 72; } // end class RandomAccessAccountRecord Fig. 16.11 RandomAccessAccountRecord class used in the random-access file programs (Part 3). 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.12: CreateRandomFile.java // This program creates a random access file sequentially // by writing 100 empty records to disk. // Java core packages import java.io.*; // Java extension packages import javax.swing.*; Outline Fig. 16.12 Creating a random-access file sequentially. // Deitel packages import com.deitel.jhtp4.ch16.RandomAccessAccountRecord; public class CreateRandomFile { // enable user to select file to open private void createFile() { // display dialog so user can choose file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showSaveDialog( null ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // obtain selected file File fileName = fileChooser.getSelectedFile(); 2002 Prentice Hall, Inc. All rights reserved. 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 // display error if file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) JOptionPane.showMessageDialog( null, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); else { // open file try { RandomAccessFile file = new RandomAccessFile( fileName, "rw" ); Outline Fig. 16.12 Creating a random-access file sequentially (Part 2). Open a Lines 44-45 RandomAccessFile forLines use in 51-52 the program RandomAccessAccountRecord blankRecord = new RandomAccessAccountRecord(); // write 100 blank records for ( int count = 0; count < 100; count++ ) blankRecord.write( file ); // close file file.close(); If file opens successfully, write 100 blank records // display message that file was created JOptionPane.showMessageDialog( null, "Created file " + fileName, "Status", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); // terminate program } 2002 Prentice Hall, Inc. All rights reserved. 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 } // process exceptions during open, write or // close file operations catch ( IOException ioException ) { JOptionPane.showMessageDialog( null, "Error processing file", "Error processing file", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); } Outline If IOException occurs, display message and Fig. 16.12 Creating terminate a random-access file sequentially (Part 3). } } // end method openFile Lines 67-73 // execute application to create file user specifies public static void main( String args[] ) { CreateRandomFile application = new CreateRandomFile(); application.createFile(); } // end class CreateRandomFile 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.12 Creating a random-access file sequentially (Part 4). 2002 Prentice Hall, Inc. All rights reserved. 16.9 Writing Data Randomly to a RandomAccess File • RandomAccessFile method seek – Determines location in file where record is stored – Sets file-position pointer to a specific point in file 2002 Prentice Hall, Inc. All rights reserved. 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 // // // // Fig. 16.13: WriteRandomFile.java This program uses textfields to get information from the user at the keyboard and writes the information to a random-access file. // Java core packages import java.awt.*; import java.awt.event.*; import java.io.*; Outline Fig. 16.13 Writing data randomly to a random-access file. // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.*; public class WriteRandomFile extends JFrame { private RandomAccessFile output; private BankUI userInterface; private JButton enterButton, openButton; // set up GUI public WriteRandomFile() { super( "Write to random access file" ); // create instance of reusable user interface BankUI userInterface = new BankUI( 4 ); // four textfields getContentPane().add( userInterface, BorderLayout.CENTER ); // get reference to generic task button doTask1 in BankUI openButton = userInterface.getDoTask1Button(); openButton.setText( "Open..." ); 2002 Prentice Hall, Inc. All rights reserved. 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 // register listener to call openFile when button pressed openButton.addActionListener( // anonymous inner class to handle openButton event new ActionListener() { // allow user to select file to open public void actionPerformed( ActionEvent event ) { openFile(); } } Outline Fig. 16.13 Writing data randomly to a random-access file (Part 2). // end anonymous inner class ); // end call to addActionListener // register window listener for window closing event addWindowListener( // anonymous inner class to handle windowClosing event new WindowAdapter() { // add record in GUI, then close file public void windowClosing( WindowEvent event ) { if ( output != null ) addRecord(); closeFile(); } } // end anonymous inner class ); // end call to addWindowListener 2002 Prentice Hall, Inc. All rights reserved. 71 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 // get reference to generic task button doTask2 in BankUI enterButton = userInterface.getDoTask2Button(); enterButton.setText( "Enter" ); enterButton.setEnabled( false ); // register listener to call addRecord when button pressed enterButton.addActionListener( // anonymous inner class to handle enterButton event new ActionListener() { Outline Fig. 16.13 Writing data randomly to a random-access file (Part 3). // add record to file public void actionPerformed( ActionEvent event ) { addRecord(); } } // end anonymous inner class ); // end call to addActionListener setSize( 300, 150 ); show(); } // enable user to choose file to open private void openFile() { // display file dialog so user can select file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); 2002 Prentice Hall, Inc. All rights reserved. 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 // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; // obtain selected file File fileName = fileChooser.getSelectedFile(); // display error if file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) JOptionPane.showMessageDialog( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); Outline Fig. 16.13 Writing data randomly to a random-access file (Part 4). else { // open file try { output = new RandomAccessFile( fileName, "rw" ); enterButton.setEnabled( true ); openButton.setEnabled( false ); } // process exception while opening file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "File does not exist", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); } } } // end method openFile 2002 Prentice Hall, Inc. All rights reserved. 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 // close file and terminate application private void closeFile() { // close file and exit try { if ( output != null ) output.close(); System.exit( 0 ); Outline Fig. 16.13 Writing data randomly to a random-access file (Part 5). } // process exception while closing file catch( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); Lines 162-207 System.exit( 1 ); } } // add one record to file public void addRecord() { int accountNumber = 0; String fields[] = userInterface.getFieldValues(); RandomAccessAccountRecord record = new RandomAccessAccountRecord(); Method addRecord retrieves data from the GUI, stores the data in a record and writes the data to a file // ensure account field has a value if ( ! fields[ BankUI.ACCOUNT ].equals( "" ) ) { // output values to file try { accountNumber = 2002 Prentice Hall, Inc. All rights reserved. 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 202 203 204 205 206 207 208 Integer.parseInt( fields[ BankUI.ACCOUNT ] ); if ( accountNumber > 0 && accountNumber <= 100 ) { record.setAccount( accountNumber ); record.setFirstName( fields[ BankUI.FIRSTNAME ] ); record.setLastName( fields[ BankUI.LASTNAME ] ); record.setBalance( Double.parseDouble( fields[ BankUI.BALANCE ] ) ); output.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); record.write( output ); } userInterface.clearFields(); Outline Fig. 16.13 Writing data randomly to a random-access file Method (Part 6). seeks positions file-position pointer for object output to the proper byte location // clear TextFields } // process improper account number or balance format catch ( NumberFormatException formatException ) { JOptionPane.showMessageDialog( this, "Bad account number or balance", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } // process exceptions while writing to file catch ( IOException ioException ) { closeFile(); } } } // end method addRecord 2002 Prentice Hall, Inc. All rights reserved. 209 210 211 212 213 214 215 } // execute application public static void main( String args[] ) { new WriteRandomFile(); } // end class WriteRandomFile Outline Fig. 16.13 Writing data randomly to a random-access file (Part 7). 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.13 Writing data randomly to a random-access file (Part 8). 2002 Prentice Hall, Inc. All rights reserved. 16.10 Reading Data Sequentially from a Random-Access File • Read all valid records in a RandomAccessFile 2002 Prentice Hall, Inc. All rights reserved. 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 // Fig. 16.14: ReadRandomFile.java // This program reads a random-access file sequentially and // displays the contents one record at a time in text fields. // Java core packages import java.awt.*; import java.awt.event.*; import java.io.*; import java.text.DecimalFormat; Outline Fig. 16.14 Reading a random-access file sequentially. // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.*; public class ReadRandomFile extends JFrame { private BankUI userInterface; private RandomAccessFile input; private JButton nextButton, openButton; // set up GUI public ReadRandomFile() { super( "Read Client File" ); // create reusable user interface instance userInterface = new BankUI( 4 ); // four textfields getContentPane().add( userInterface ); // configure generic doTask1 button from BankUI openButton = userInterface.getDoTask1Button(); openButton.setText( "Open File for Reading..." ); // register listener to call openFile when button pressed 2002 Prentice Hall, Inc. All rights reserved. 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 openButton.addActionListener( // anonymous inner class to handle openButton event new ActionListener() { // enable user to select file to open public void actionPerformed( ActionEvent event ) { openFile(); } } Outline Fig. 16.14 Reading a random-access file sequentially (Part 2). // end anonymous inner class ); // end call to addActionListener // configure generic doTask2 button from BankUI nextButton = userInterface.getDoTask2Button(); nextButton.setText( "Next" ); nextButton.setEnabled( false ); // register listener to call readRecord when button pressed nextButton.addActionListener( // anonymous inner class to handle nextButton event new ActionListener() { // read a record when user clicks nextButton public void actionPerformed( ActionEvent event ) { readRecord(); } } // end anonymous inner class ); // end call to addActionListener 2002 Prentice Hall, Inc. All rights reserved. 71 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 // register listener for window closing event addWindowListener( // anonymous inner class to handle windowClosing event new WindowAdapter() { // close file and terminate application public void windowClosing( WindowEvent event ) { closeFile(); } } Outline Fig. 16.14 Reading a random-access file sequentially (Part 3). // end anonymous inner class ); // end call to addWindowListener setSize( 300, 150 ); show(); } // enable user to select file to open private void openFile() { // display file dialog so user can select file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); // if user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return; 2002 Prentice Hall, Inc. All rights reserved. 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 // obtain selected file File fileName = fileChooser.getSelectedFile(); Outline // display error is file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) JOptionPane.showMessageDialog( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); Fig. 16.14 Reading a random-access file sequentially (Part 4). else { Lines 136-174 // open file try { input = new RandomAccessFile( fileName, "r" ); nextButton.setEnabled( true ); openButton.setEnabled( false ); } // catch exception while opening file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "File does not exist", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); } } } // end method openFile // read one record public void readRecord() { DecimalFormat twoDigits = new DecimalFormat( "0.00" ); RandomAccessAccountRecord record = new RandomAccessAccountRecord(); Method readRecord reads through file until it finds a valid account record 2002 Prentice Hall, Inc. All rights reserved. 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 // read a record and display try { do { record.read( input ); } while ( record.getAccount() == 0 ); String values[] = { String.valueOf( record.getAccount() ), record.getFirstName(), record.getLastName(), String.valueOf( record.getBalance() ) }; userInterface.setFieldValues( values ); Outline Invoke methodReading read Fig. 16.14 to read data into a random-access object filerecord sequentially (Part 5). Line 146 } // close file when end-of-file reached catch ( EOFException eofException ) { JOptionPane.showMessageDialog( this, "No more records", "End-of-file reached", JOptionPane.INFORMATION_MESSAGE ); closeFile(); } // process exceptions from problem with file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Reading File", "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); } } // end method readRecord 2002 Prentice Hall, Inc. All rights reserved. 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 202 203 } // close file and terminate application private void closeFile() { // close file and exit try { if ( input != null ) input.close(); System.exit( 0 ); Outline Fig. 16.14 Reading a random-access file sequentially (Part 6). } // process exception closing file catch( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); } } // execute application public static void main( String args[] ) { new ReadRandomFile(); } // end class ReadRandomFile 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.14 Reading a random-access file sequentially (Part 7). 2002 Prentice Hall, Inc. All rights reserved. 16.11 Example: A Transaction-Processing Program • Substantial transaction-processing system – Uses random-access file – Updates, adds and deletes accounts 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.15 The initial Transaction Processor window. 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.16 Loading a record into the Update Record internal frame. Type account number and press the key to load record. 2002 Prentice Hall, Inc. All rights reserved. Enter Fig. 16.17 Inputting a transaction in the Update Record internal frame. Type transaction amount and press the Enter key to update balance in dialog. Press Save balance in file. Changes to store new 2002 Prentice Hall, Inc. All rights reserved. 16.18 New Record internal frame. 2002 Prentice Hall, Inc. All rights reserved. 16.19 Delete Record internal frame. 2002 Prentice Hall, Inc. All rights reserved. 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 // // // // // Transaction processing program using RandomAccessFiles. This program reads a random-access file sequentially, updates records already written to the file, creates new records to be placed in the file and deletes data already in the file. // Java core packages import java.awt.*; import java.awt.event.*; import java.io.*; import java.text.DecimalFormat; Outline Fig. 16.20 Transactionprocessing program. // Java extension packages import javax.swing.*; // Deitel packages import com.deitel.jhtp4.ch16.*; public class TransactionProcessor extends JFrame { private UpdateDialog updateDialog; private NewDialog newDialog; private DeleteDialog deleteDialog; private JMenuItem newItem, updateItem, deleteItem, openItem, exitItem; private JDesktopPane desktop; private RandomAccessFile file; private RandomAccessAccountRecord record; // set up GUI public TransactionProcessor() { super( "Transaction Processor" ); 2002 Prentice Hall, Inc. All rights reserved. 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 // set up desktop, menu bar and File menu desktop = new JDesktopPane(); getContentPane().add( desktop ); JMenuBar menuBar = new JMenuBar(); setJMenuBar( menuBar ); JMenu fileMenu = new JMenu( "File" ); menuBar.add( fileMenu ); Outline Fig. 16.20 Transactionprocessing program (Part 2). // set up menu item for adding a record newItem = new JMenuItem( "New Record" ); newItem.setEnabled( false ); // display new record dialog when user selects New Record newItem.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { newDialog.setVisible( true ); } } ); // set up menu item for updating a record updateItem = new JMenuItem( "Update Record" ); updateItem.setEnabled( false ); // display update dialog when user selects Update Record updateItem.addActionListener( new ActionListener() { 2002 Prentice Hall, Inc. All rights reserved. 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 94 95 96 97 98 99 100 public void actionPerformed( ActionEvent event ) { updateDialog.setVisible( true ); } } ); // set up menu item for deleting a record deleteItem = new JMenuItem( "Delete Record" ); deleteItem.setEnabled( false ); Outline Fig. 16.20 Transactionprocessing program (Part 3). // display delete dialog when user selects Delete Record deleteItem.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { deleteDialog.setVisible( true ); } } ); // set up button for opening file openItem = new JMenuItem( "New/Open File" ); // enable user to select file to open, then set up // dialog boxes openItem.addActionListener( new ActionListener() { 2002 Prentice Hall, Inc. All rights reserved. 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 public void actionPerformed( ActionEvent event ) { boolean opened = openFile(); if ( !opened ) return; openItem.setEnabled( false ); Outline Fig. 16.20 Transactionprocessing program (Part 4). // set up internal frames for record processing updateDialog = new UpdateDialog( file ); desktop.add( updateDialog ); deleteDialog = new DeleteDialog( file ); desktop.add ( deleteDialog ); newDialog = new NewDialog( file ); desktop.add( newDialog ); } } // end anonymous inner class ); // end call to addActionListener // set up menu item for exiting program exitItem = new JMenuItem( "Exit" ); exitItem.setEnabled( true ); // teminate application exitItem.addActionListener( new ActionListener() { 2002 Prentice Hall, Inc. All rights reserved. 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 public void actionPerformed( ActionEvent event ) { closeFile(); } } ); // attach menu items to File menu fileMenu.add( openItem ); fileMenu.add( newItem ); fileMenu.add( updateItem ); fileMenu.add( deleteItem ); fileMenu.addSeparator(); fileMenu.add( exitItem ); Outline Fig. 16.20 Transactionprocessing program (Part 5). // configure window setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); setSize( 400, 250 ); setVisible( true ); } // end TransactionProcessor constructor // enable user to select file to open private boolean openFile() { // display dialog so user can select file JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode( JFileChooser.FILES_ONLY ); int result = fileChooser.showOpenDialog( this ); 2002 Prentice Hall, Inc. All rights reserved. 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 user clicked Cancel button on dialog, return if ( result == JFileChooser.CANCEL_OPTION ) return false; // obtain selected file File fileName = fileChooser.getSelectedFile(); // display error if file name invalid if ( fileName == null || fileName.getName().equals( "" ) ) { JOptionPane.showMessageDialog( this, "Invalid File Name", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); Outline Fig. 16.20 Transactionprocessing program (Part 6). return false; } else { // open file try { file = new RandomAccessFile( fileName, "rw" ); openItem.setEnabled( false ); newItem.setEnabled( true ); updateItem.setEnabled( true ); deleteItem.setEnabled( true ); } // process problems opening file catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "File does not exist", "Invalid File Name", JOptionPane.ERROR_MESSAGE ); 2002 Prentice Hall, Inc. All rights reserved. 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 return false; } Outline } return true; // file opened } // close file and terminate application private void closeFile() { // close file and exit try { if ( file != null ) file.close(); Fig. 16.20 Transactionprocessing program (Part 7). System.exit( 0 ); } // process exceptions closing file catch( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error closing file", "Error", JOptionPane.ERROR_MESSAGE ); System.exit( 1 ); } } // execute application public static void main( String args[] ) { new TransactionProcessor(); } // end class TransactionProcessor 2002 Prentice Hall, Inc. All rights reserved. 237 // class for udpating records 238 class UpdateDialog extends JInternalFrame { 239 private RandomAccessFile file; 240 private BankUI userInterface; 241 242 // set up GUI 243 public UpdateDialog( RandomAccessFile updateFile ) 244 { 245 super( "Update Record" ); 246 247 file = updateFile; 248 249 // set up GUI components 250 userInterface = new BankUI( 5 ); 251 getContentPane().add( userInterface, 252 BorderLayout.CENTER ); 253 254 // set up Save Changes button and register listener 255 JButton saveButton = userInterface.getDoTask1Button(); 256 saveButton.setText( "Save Changes" ); 257 258 saveButton.addActionListener( 259 260 new ActionListener() { 261 262 public void actionPerformed( ActionEvent event ) 263 { 264 addRecord( getRecord() ); 265 setVisible( false ); 266 userInterface.clearFields(); 267 } 268 } 269 ); 270 Class Outline UpdateDialog implements Update Record Fig. 16.20 internal frame Transactionprocessing program (Part 8). Lines 238-458 2002 Prentice Hall, Inc. All rights reserved. 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 // set up Cancel button and register listener JButton cancelButton = userInterface.getDoTask2Button(); cancelButton.setText( "Cancel" ); cancelButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { setVisible( false ); userInterface.clearFields(); } Outline Fig. 16.20 Transactionprocessing program (Part 9). Lines 295-330 } ); // set up listener for transaction textfield JTextField transactionField = userInterface.getFields()[ BankUI.TRANSACTION ]; transactionField.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { // add transaction amount to balance try { RandomAccessAccountRecord record = getRecord(); Method actionPerformed processes a transaction in the current account // get textfield values from userInterface String fieldValues[] = userInterface.getFieldValues(); 2002 Prentice Hall, Inc. All rights reserved. 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 // get transaction amount double change = Double.parseDouble( fieldValues[ BankUI.TRANSACTION ] ); // specify Strings to display in GUI String[] values = { String.valueOf( record.getAccount() ), record.getFirstName(), record.getLastName(), String.valueOf( record.getBalance() + change ), "Charge(+) or payment (-)" }; Outline Fig. 16.20 Transactionprocessing program (Part 10). // display Strings in GUI userInterface.setFieldValues( values ); } // process invalid number in transaction field catch ( NumberFormatException numberFormat ) { JOptionPane.showMessageDialog( null, "Invalid Transaction", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } } } // end method actionPerformed // end anonymous inner class ); // end call to addActionListener // set up listener for account text field JTextField accountField = userInterface.getFields()[ BankUI.ACCOUNT ]; 2002 Prentice Hall, Inc. All rights reserved. 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 accountField.addActionListener( new ActionListener() { // get record and display contents in GUI public void actionPerformed( ActionEvent event ) { RandomAccessAccountRecord record = getRecord(); if ( record.getAccount() != 0 ) { String values[] = { String.valueOf( record.getAccount() ), record.getFirstName(), record.getLastName(), String.valueOf( record.getBalance() ), "Charge(+) or payment (-)" }; Method Outline actionPerformed uses number entered 16.20 inFig. a JTextField to Transactionretrieve a record processing program from file with method (Part 11). getRecord Lines 345-360 Extract record information and Lines 350357 display in internal frame Lines 371-418 userInterface.setFieldValues( values ); } } } // end method actionPerformed // end anonymous inner class ); // end call to addActionListener setSize( 300, 175 ); setVisible( false ); } // get record from file private RandomAccessAccountRecord getRecord() { RandomAccessAccountRecord record = new RandomAccessAccountRecord(); Method getRecord reads record from file 2002 Prentice Hall, Inc. All rights reserved. 305 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 // get record from file try { JTextField accountField = userInterface.getFields()[ BankUI.ACCOUNT ]; int accountNumber = Integer.parseInt( accountField.getText() ); Outline Fig. 16.20 Transactionprocessing program (Part 12). if ( accountNumber < 1 || accountNumber > 100 ) { JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Error", JOptionPane.ERROR_MESSAGE ); return record; } // seek to appropriate record location in file file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); record.read( file ); if ( record.getAccount() == 0 ) JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Error", JOptionPane.ERROR_MESSAGE ); } // process invalid account number format catch ( NumberFormatException numberFormat ) { JOptionPane.showMessageDialog( this, "Invalid Account", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } 2002 Prentice Hall, Inc. All rights reserved. 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 // process file processing problems catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Reading File", "Error", JOptionPane.ERROR_MESSAGE ); } return record; } Outline Fig. 16.20 Transactionprocessing program (Part 13). // end method getRecord // add record to file public void addRecord( RandomAccessAccountRecord record ) { // update record in file try { int accountNumber = record.getAccount(); Lines 421-456 Method addRecord updates the current balance file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); String[] values = userInterface.getFieldValues(); // set firstName, lastName and balance in record record.setFirstName( values[ BankUI.FIRSTNAME ] ); record.setLastName( values[ BankUI.LASTNAME ] ); record.setBalance( Double.parseDouble( values[ BankUI.BALANCE ] ) ); // rewrite record to file record.write( file ); } 2002 Prentice Hall, Inc. All rights reserved. 442 // process file processing problems 443 catch ( IOException ioException ) { 444 JOptionPane.showMessageDialog( this, 445 "Error Writing To File", 446 "Error", JOptionPane.ERROR_MESSAGE ); 447 } 448 449 // process invalid balance value 450 catch ( NumberFormatException numberFormat ) { 451 JOptionPane.showMessageDialog( this, 452 "Bad Balance", "Invalid Number Format", 453 JOptionPane.ERROR_MESSAGE ); 454 } 455 456 } // end method addRecord 457 458 } // end class UpdateDialog 459 460 // class for creating new records 461 class NewDialog extends JInternalFrame { 462 private RandomAccessFile file; 463 private BankUI userInterface; 464 465 // set up GUI 466 public NewDialog( RandomAccessFile newFile ) 467 { 468 super( "New Record" ); 469 470 file = newFile; 471 472 // attach user interface to dialog 473 userInterface = new BankUI( 4 ); 474 getContentPane().add( userInterface, 475 BorderLayout.CENTER ); 476 Outline Fig. 16.20 Transactionprocessing program (Part 14). Lines 461-615 Class NewDialog implements the New Record internal frame 2002 Prentice Hall, Inc. All rights reserved. 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 // set up Save Changes button and register listener JButton saveButton = userInterface.getDoTask1Button(); saveButton.setText( "Save Changes" ); saveButton.addActionListener( new ActionListener() { // add new record to file public void actionPerformed( ActionEvent event ) { addRecord( getRecord() ); setVisible( false ); userInterface.clearFields(); } } Outline Fig. 16.20 Transactionprocessing program (Part 15). // end anonymous inner class ); // end call to addActionListener JButton cancelButton = userInterface.getDoTask2Button(); cancelButton.setText( "Cancel" ); cancelButton.addActionListener( new ActionListener() { // dismiss dialog without storing new record public void actionPerformed( ActionEvent event ) { setVisible( false ); userInterface.clearFields(); } } // end anonymous inner class 2002 Prentice Hall, Inc. All rights reserved. 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 ); // end call to addActionListener setSize( 300, 150 ); setVisible( false ); } // end constructor // get record from file private RandomAccessAccountRecord getRecord() { RandomAccessAccountRecord record = new RandomAccessAccountRecord(); Outline Fig. 16.20 Transactionprocessing program (Part 16). // get record from file try { JTextField accountField = userInterface.getFields()[ BankUI.ACCOUNT ]; int accountNumber = Integer.parseInt( accountField.getText() ); if ( accountNumber < 1 || accountNumber > 100 ) { JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Error", JOptionPane.ERROR_MESSAGE ); return record; } // seek to record location file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); 2002 Prentice Hall, Inc. All rights reserved. 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 // read record from file record.read( file ); Outline } // process invalid account number format catch ( NumberFormatException numberFormat ) { JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } Fig. 16.20 Transactionprocessing program (Part 17). // process file processing problems catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Reading File", "Error", JOptionPane.ERROR_MESSAGE ); } return record; } // end method getRecord // add record to file public void addRecord( RandomAccessAccountRecord record ) { String[] fields = userInterface.getFieldValues(); if ( record.getAccount() != 0 ) { JOptionPane.showMessageDialog( this, "Record Already Exists", "Error", JOptionPane.ERROR_MESSAGE ); return; } 2002 Prentice Hall, Inc. All rights reserved. 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 // output the values to the file try { // set account, first name, last name and balance // for record record.setAccount( Integer.parseInt( fields[ BankUI.ACCOUNT ] ) ); record.setFirstName( fields[ BankUI.FIRSTNAME ] ); record.setLastName( fields[ BankUI.LASTNAME ] ); record.setBalance( Double.parseDouble( fields[ BankUI.BALANCE ] ) ); Outline Fig. 16.20 Transactionprocessing program (Part 18). // seek to record location file.seek( ( record.getAccount() - 1 ) * RandomAccessAccountRecord.size() ); // write record record.write( file ); } // process invalid account or balance format catch ( NumberFormatException numberFormat ) { JOptionPane.showMessageDialog( this, "Invalid Balance", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } // process file processing problems catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Writing To File", "Error", JOptionPane.ERROR_MESSAGE ); } } // end method addRecord 2002 Prentice Hall, Inc. All rights reserved. 614 615 } // end class NewDialog 616 617 // class for deleting records 618 class DeleteDialog extends JInternalFrame { 619 private RandomAccessFile file; // file for output 620 private BankUI userInterface; 621 622 // set up GUI 623 public DeleteDialog( RandomAccessFile deleteFile ) 624 { 625 super( "Delete Record" ); 626 627 file = deleteFile; 628 629 // create BankUI with only account field 630 userInterface = new BankUI( 1 ); 631 632 getContentPane().add( userInterface, 633 BorderLayout.CENTER ); 634 635 // set up Delete Record button and register listener 636 JButton deleteButton = userInterface.getDoTask1Button(); 637 deleteButton.setText( "Delete Record" ); 638 639 deleteButton.addActionListener( 640 641 new ActionListener() { 642 Class Outline DeleteDialog implements the Delete Fig. 16.20Record internal frame Transactionprocessing program (Part 19). Lines 618-774 2002 Prentice Hall, Inc. All rights reserved. 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 // overwrite existing record public void actionPerformed( ActionEvent event ) { addRecord( getRecord() ); setVisible( false ); userInterface.clearFields(); } } // end anonymous inner class Outline Fig. 16.20 Transactionprocessing program (Part 20). ); // end call to addActionListener // set up Cancel button and register listener JButton cancelButton = userInterface.getDoTask2Button(); cancelButton.setText( "Cancel" ); cancelButton.addActionListener( new ActionListener() { // cancel delete operation by hiding dialog public void actionPerformed( ActionEvent event ) { setVisible( false ); } } // end anonymous inner class ); // end call to addActionListener // set up listener for account text field JTextField accountField = userInterface.getFields()[ BankUI.ACCOUNT ]; 2002 Prentice Hall, Inc. All rights reserved. 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 accountField.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { RandomAccessAccountRecord record = getRecord(); } } Outline Fig. 16.20 Transactionprocessing program (Part 21). // end anonymous inner class ); // end call to addActionListener setSize( 300, 100 ); setVisible( false ); } // end constructor // get record from file private RandomAccessAccountRecord getRecord() { RandomAccessAccountRecord record = new RandomAccessAccountRecord(); // get record from file try { JTextField accountField = userInterface.getFields()[ BankUI.ACCOUNT ]; int accountNumber = Integer.parseInt( accountField.getText() ); 2002 Prentice Hall, Inc. All rights reserved. 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 if ( accountNumber < 1 || accountNumber > 100 ) { JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Error", JOptionPane.ERROR_MESSAGE ); return( record ); } // seek to record location and read record file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); record.read( file ); Outline Fig. 16.20 Transactionprocessing program (Part 22). if ( record.getAccount() == 0 ) JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Error", JOptionPane.ERROR_MESSAGE ); } // process invalid account number format catch ( NumberFormatException numberFormat ) { JOptionPane.showMessageDialog( this, "Account Does Not Exist", "Invalid Number Format", JOptionPane.ERROR_MESSAGE ); } // process file processing problems catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Reading File", "Error", JOptionPane.ERROR_MESSAGE ); } 2002 Prentice Hall, Inc. All rights reserved. 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 } return record; } // end method getRecord // add record to file public void addRecord( RandomAccessAccountRecord record ) { if ( record.getAccount() == 0 ) return; Outline Fig. 16.20 Transactionprocessing program (Part 23). // delete record by setting account number to 0 try { int accountNumber = record.getAccount(); // seek to record position file.seek( ( accountNumber - 1 ) * RandomAccessAccountRecord.size() ); // set account to 0 and overwrite record record.setAccount( 0 ); record.write( file ); } // process file processing problems catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, "Error Writing To File", "Error", JOptionPane.ERROR_MESSAGE ); } } // end method addRecord // end class DeleteDialog 2002 Prentice Hall, Inc. All rights reserved. 16.12 Class File • Class File – Provides useful information about a file or directory – Does not open files or process files • Fig. 16.21 lists some useful File methods 2002 Prentice Hall, Inc. All rights reserved. Fig. 16.21 Some commonly used File methods. Method boolean canRead() Description Returns true if a file is readable; false otherwise. boolean canWrite() Returns true if a file is writable; false otherwise. boolean exists() Returns true if the name specified as the argument to the File constructor is a file or directory in the specified path; false otherwise. boolean isFile() Returns true if the name specified as the argument to the File constructor is a file; false otherwise. boolean Returns true if the name specified as the argument to the File isDirectory() constructor is a directory; false otherwise. boolean Returns true if the arguments specified to the File constructor isAbsolute() indicate an absolute path to a file or directory; false otherwise. String getAbsolutePath() Returns a String with the absolute path of the file or directory. 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—that is, 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 Returns a platform-dependent representation of the time at which the lastModified() file or directory was last modified. The value returned is only useful for comparison with other values returned by this method. String[] list() 2002 Prentice Hall, Inc. All rights reserved. Returns an array of Strings representing the contents of a directory. 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 // Fig. 16.22: FileTest.java // Demonstrating the File class. // Java core packages import java.awt.*; import java.awt.event.*; import java.io.*; Outline Fig. 16.22 Demonstrating class File. // Java extension packages import javax.swing.*; public class FileTest extends JFrame implements ActionListener { private JTextField enterField; private JTextArea outputArea; // set up GUI public FileTest() { super( "Testing class File" ); enterField = new JTextField( "Enter file or directory name here" ); enterField.addActionListener( this ); outputArea = new JTextArea(); ScrollPane scrollPane = new ScrollPane(); scrollPane.add( outputArea ); Container container = getContentPane(); container.add( enterField, BorderLayout.NORTH ); container.add( scrollPane, BorderLayout.CENTER ); 2002 Prentice Hall, Inc. All rights reserved. 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 setSize( 400, 400 ); show(); } // display information about file user specifies public void actionPerformed( ActionEvent actionEvent ) { File name = new File( actionEvent.getActionCommand() ); // if name exists, output information about it if ( name.exists() ) { outputArea.setText( name.getName() + " exists\n" + ( name.isFile() ? "is a file\n" : "is not a file\n" ) + ( name.isDirectory() ? "is a directory\n" : "is not a directory\n" ) + ( name.isAbsolute() ? "is absolute path\n" : "is not absolute path\n" ) + "Last modified: " + name.lastModified() + "\nLength: " + name.length() + "\nPath: " + name.getPath() + "\nAbsolute path: " + name.getAbsolutePath() + "\nParent: " + name.getParent() ); Method Outline actionPerformed creates a new File Fig.assigns 16.22 it a name and Demonstrating class File (Part 2). Lines 40-103 Body of if outputs information Lines 45-94about the file if it exists // output information if name is a file if ( name.isFile() ) { // append contents of file to outputArea try { BufferedReader input = new BufferedReader( new FileReader( name ) ); StringBuffer buffer = new StringBuffer(); String text; outputArea.append( "\n\n" ); 2002 Prentice Hall, Inc. All rights reserved. 70 71 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 while ( ( text = input.readLine() ) != null ) buffer.append( text + "\n" ); outputArea.append( buffer.toString() ); } // process file processing problems catch( IOException ioException ) { JOptionPane.showMessageDialog( this, "FILE ERROR", "FILE ERROR", JOptionPane.ERROR_MESSAGE ); } Outline Fig. 16.22 Demonstrating class File (Part 3). Lines 97-101 } // output directory listing else if ( name.isDirectory() ) { String directory[] = name.list(); outputArea.append( "\n\nDirectory contents:\n"); for ( int i = 0; i < directory.length; i++ ) outputArea.append( directory[ i ] + "\n" ); } } } // not file or directory, output error message else { JOptionPane.showMessageDialog( this, actionEvent.getActionCommand() + " Does Not Exist", "ERROR", JOptionPane.ERROR_MESSAGE ); } If file does not exist, display error // end method actionPerformed 2002 Prentice Hall, Inc. All rights reserved. 104 105 106 107 108 109 110 111 112 113 114 } // execute application public static void main( String args[] ) { FileTest application = new FileTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); Outline Fig. 16.22 Demonstrating class File (Part 4). } // end class FileTest 2002 Prentice Hall, Inc. All rights reserved.