Text and Binary Files
Random-access files
Introduction
import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; public class AddressBook extends JFrame { // Specify the size of five string fields in the record final static int NAME_SIZE = 32; final static int STREET_SIZE = 32; final static int CITY_SIZE = 20; final static int STATE_SIZE = 2; final static int ZIP_SIZE = 5; final static int RECORD_SIZE = (NAME_SIZE + STREET_SIZE + CITY_SIZE + STATE_SIZE + ZIP_SIZE); // Access address.dat using RandomAccessFile private RandomAccessFile raf; // Text fields private JTextField jtfName = new JTextField(NAME_SIZE); private JTextField jtfStreet = new JTextField(STREET_SIZE); private JTextField jtfCity = new JTextField(CITY_SIZE); private JTextField jtfState = new JTextField(ZIP_SIZE); private JTextField jtfZip = new JTextField(ZIP_SIZE); // Buttons private JButton jbtAdd = new JButton("Add"); private JButton jbtFirst = new JButton("First"); private JButton jbtNext = new JButton("Next"); private JButton jbtPrevious = new JButton("Previous"); private JButton jbtLast = new JButton("Last"); public AddressBook() { // Open or create a random access file try { raf = new RandomAccessFile("address.dat", "rw"); } catch(IOException ex) { System.out.print("Error: " + ex); System.exit(0); } // Panel p1 for holding labels Name, Street, and City JPanel p1 = new JPanel(); p1.setLayout(new GridLayout(3, 1)); p1.add(new JLabel("Name")); p1.add(new JLabel("Street")); p1.add(new JLabel("City")); // Panel jpState for holding state JPanel jpState = new JPanel(); jpState.setLayout(new BorderLayout()); jpState.add(new JLabel("State"), BorderLayout.WEST); jpState.add(jtfState, BorderLayout.CENTER); // Panel jpZip for holding zip JPanel jpZip = new JPanel(); jpZip.setLayout(new BorderLayout()); jpZip.add(new JLabel("Zip"), BorderLayout.WEST); jpZip.add(jtfZip, BorderLayout.CENTER); // Panel p2 for holding jpState and jpZip JPanel p2 = new JPanel(); p2.setLayout(new BorderLayout()); p2.add(jpState, BorderLayout.WEST); p2.add(jpZip, BorderLayout.CENTER); // Panel p3 for holding jtfCity and p2 JPanel p3 = new JPanel(); p3.setLayout(new BorderLayout()); p3.add(jtfCity, BorderLayout.CENTER); p3.add(p2, BorderLayout.EAST); // Panel p4 for holding jtfName, jtfStreet, and p3 JPanel p4 = new JPanel(); p4.setLayout(new GridLayout(3, 1)); p4.add(jtfName); p4.add(jtfStreet); p4.add(p3); // Place p1 and p4 into jpAddress JPanel jpAddress = new JPanel(new BorderLayout()); jpAddress.add(p1, BorderLayout.WEST); jpAddress.add(p4, BorderLayout.CENTER); // Set the panel with line border jpAddress.setBorder(new BevelBorder(BevelBorder.RAISED)); // Add buttons to a panel JPanel jpButton = new JPanel(); jpButton.add(jbtAdd); jpButton.add(jbtFirst); jpButton.add(jbtNext); jpButton.add(jbtPrevious); jpButton.add(jbtLast); // Add jpAddress and jpButton to the frame add(jpAddress, BorderLayout.CENTER); add(jpButton, BorderLayout.SOUTH); jbtAdd.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { writeAddress(); } }); jbtFirst.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { if (raf.length() > 0) readAddress(0); } catch (IOException ex) { ex.printStackTrace(); } } }); jbtNext.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { long currentPosition = raf.getFilePointer(); if (currentPosition < raf.length()) readAddress(currentPosition); } catch (IOException ex) { ex.printStackTrace(); } } }); jbtPrevious.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { long currentPosition = raf.getFilePointer(); if (currentPosition - 2 * RECORD_SIZE > 0) // Why 2 * 2 * RECORD_SIZE? See the follow-up remarks readAddress(currentPosition - 2 * 2 * RECORD_SIZE); else readAddress(0); } catch (IOException ex) { ex.printStackTrace(); } } }); jbtLast.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { long lastPosition = raf.length(); if (lastPosition > 0) // Why 2 * RECORD_SIZE? See the follow-up remarks readAddress(lastPosition - 2 * RECORD_SIZE); } catch (IOException ex) { ex.printStackTrace(); } } }); // Display the first record if exists try { if (raf.length() > 0) readAddress(0); } catch (IOException ex) { ex.printStackTrace(); } } /** Write a record at the end of the file */ public void writeAddress() { try { raf.seek(raf.length()); FixedLengthStringIO.writeFixedLengthString( jtfName.getText(), NAME_SIZE, raf); FixedLengthStringIO.writeFixedLengthString( jtfStreet.getText(), STREET_SIZE, raf); FixedLengthStringIO.writeFixedLengthString( jtfCity.getText(), CITY_SIZE, raf); FixedLengthStringIO.writeFixedLengthString( jtfState.getText(), STATE_SIZE, raf); FixedLengthStringIO.writeFixedLengthString( jtfZip.getText(), ZIP_SIZE, raf); } catch (IOException ex) { ex.printStackTrace(); } } /** Read a record at the specified position */ public void readAddress(long position) throws IOException { raf.seek(position); String name = FixedLengthStringIO.readFixedLengthString( NAME_SIZE, raf); String street = FixedLengthStringIO.readFixedLengthString( STREET_SIZE, raf); String city = FixedLengthStringIO.readFixedLengthString( CITY_SIZE, raf); String state = FixedLengthStringIO.readFixedLengthString( STATE_SIZE, raf); String zip = FixedLengthStringIO.readFixedLengthString( ZIP_SIZE, raf); jtfName.setText(name); jtfStreet.setText(street); jtfCity.setText(city); jtfState.setText(state); jtfZip.setText(zip); } public static void main(String[] args) { AddressBook frame = new AddressBook(); frame.pack(); frame.setTitle("AddressBook"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
public final class Address { private String street; private String city; private String state; private String zip; /** Create an address with street, city, state, and zip */ public Address(String street, String city, String state, String zip) { this.street = street; this.city = city; this.state = state; this.zip = zip; } /** Return street */ public String getStreet() { return street; } /** Return city */ public String getCity() { return city; } /** Return state */ public String getState() { return state; } /** Return zip */ public String getZip() { return zip; } /** Get full address */ public String getFullAddress() { return street + '\n' + city + ", " + state + ' ' + zip + '\n'; } }
import java.io.*; public class FixedLengthStringIO { /** Read fixed number of characters from a DataInput stream */ public static String readFixedLengthString(int size, DataInput in) throws IOException { // Declare an array of characters char[] chars = new char[size]; // Read fixed number of characters to the array for (int i = 0; i < size; i++) chars[i] = in.readChar(); return new String(chars); } /** Write fixed number of characters to a DataOutput stream */ public static void writeFixedLengthString(String s, int size, DataOutput out) throws IOException { char[] chars = new char[size]; // Fill in string with characters s.getChars(0, Math.min(s.length(), size), chars, 0); // Fill in blank characters in the rest of the array for (int i = Math.min(s.length(), size); i < chars.length; i++) chars[i] = ' '; // Create and write a new string padded with blank characters out.writeChars(new String(chars)); } }