5 Replies Latest reply: Sep 18, 2006 10:04 PM by 807569 RSS

    Random Access Files

    807569
      Hello everyone, I hope someone can help me with this problem.
      For some reason everytime I try adding a record to a random access file I trigger an IOException.
      First I created a random access file with 100 blank records. Here is the code if anyone would like to help.

      First, this is where I store information about a record.
      public class HardwareRecord {
      
           //record data
           private double cost;
           private String toolName;
           private int quantity, recordNumber;
      
           //set and get access methods     
           public void setCost(double c) { cost = c; }
           public double getCost( ) { return cost; }
      
           public void setToolName(String n) { toolName = n; }
           public String getToolName( ) { return toolName; }
      
           public void setQuantity(int q) { quantity = q; }
           public int getQuantity( ) { return quantity; }
      
           public void setRecordNumber(int r) { recordNumber = r; }
           public int getRecordNumber( ) { return recordNumber; }
      
           //default constructor, zero out all fields by calling other non-default constructor
           public HardwareRecord( ) {
                this(0.0, 0, 0, "");
           }
      
           public HardwareRecord(double theCost, int theRecordNumber, int theQuantity, String theToolName) { 
                setCost(theCost);
                setRecordNumber(theRecordNumber);
                setQuantity(theQuantity);
                setToolName(theToolName);
           }
      }
      Now here is my class RandomAccessAccount which extends the above class.
      The purpose of this class is to help me read and write from a random access file.
      import java.io.IOException;
      import java.io.RandomAccessFile;
      
      public class RandomAccessAccount extends HardwareRecord {
           
           public RandomAccessAccount( ) {
                this(0.0, 0, 0, "");
           }
      
           public RandomAccessAccount(double cost, int recordNumber, int quantity, String toolName) {
                super(cost, recordNumber, quantity, toolName);
           }
      
           public void read(RandomAccessFile fin) throws IOException {
                //get data from hardware record fields
                setRecordNumber(fin.readInt());
                setToolName(readString(fin));
                setQuantity(fin.readInt());
                setCost(fin.readDouble());
      
           }
      
           public void write(RandomAccessFile fout) throws IOException {
                //write data out to hardware record fields
                fout.writeInt(getRecordNumber());
                writeString(fout, getToolName());
                fout.writeInt(getQuantity());
                fout.writeDouble(getCost());
           }
      
           private void writeString(RandomAccessFile fout, String name) throws IOException {
                StringBuffer buffer = null;
                if(name != null) buffer = new StringBuffer(name);
                else buffer = new StringBuffer(15);
      
                buffer.setLength(15);
                fout.writeChars(buffer.toString());
           }
      
           private String readString(RandomAccessFile fin) throws IOException {
                char name[] = new char[15], 
                           temp;
      
                for(int i=0;i<name.length;i++) {
                     temp = fin.readChar();
                     name[i] = temp;
                }
      
                return new String(name);
           }
      }
      Now the original creation of the file works with blank records.
      But later I try adding a record with another class I made and I get runtime exception IOExeption.
      Here is a sample run of the program.

      Options: 1 exit, 2 add records: 2
      Valid records numbers are greater than 0 and less than 100
      To quit loop ^d in Linux or ^z in Windows..

      Enter Cost, Tool name, Quantity and Record number: 19.99 Sander 10 1
      Error writing to file..
      java.io.IOException: Bad file descriptor
      at java.io.RandomAccessFile.write(Native Method)
      at java.io.RandomAccessFile.writeInt(RandomAccessFile.java:940)
      at RandomAccessAccount.write(RandomAccessAccount.java:25)
      at DatabaseManager.addRecords(DatabaseManager.java:42)
      at Test.main(Test.java:19)

      Lastly, here is the class I use to update the records..
      import java.io.IOException;
      import java.util.NoSuchElementException;
      import java.io.File;
      import java.io.RandomAccessFile;
      import java.util.Scanner;
      
      public class DatabaseManager {
           RandomAccessFile databaseFile = null;
           Scanner input;
      
           public void addRecords( ) {
                openDatabase();
      
                input = new Scanner(System.in);
      
                RandomAccessAccount record = new RandomAccessAccount();
      
                //directions
                System.out.println("Valid records numbers are greater than 0 and less than 100\n"
                                                                  +"To quit loop ^d in Linux or ^z in Windows..\n");                         
      
                int recordNumber,
                          quantity;
                String toolName;
                double cost;
                          
                System.out.print("Enter Cost, Tool name, Quantity and Record number: ");
                while(input.hasNext()) { //keep getting input
                     try {
                          cost = input.nextDouble();
                          toolName = input.next();
                          quantity = input.nextInt();
                          recordNumber = input.nextInt();
      
                          record.setCost(cost);
                          record.setToolName(toolName);
                          record.setQuantity(quantity);
                          record.setRecordNumber(recordNumber);
      
                          if(recordNumber > 0 && recordNumber <= 100) {
                               databaseFile.seek((recordNumber - 1) * 100);
                               record.write(databaseFile);
                               System.out.printf("\nRecord %d added successfully.\n", recordNumber);
                          } else {
                               System.out.println("Invalid record number, please > 0 and <= 100 only..");
                          }
      
                          System.out.print("Enter Cost, Tool name, Quantity and Record number: ");
                     }
                     catch(IOException e) {
                          System.err.println("Error writing to file..");
                          e.printStackTrace();
                          closeDatabase();
                          System.exit(1);
                     }
                     catch(NoSuchElementException e) {
                          System.err.println("Invalid inputs.. Please try again.");
                          input.nextLine();
                     }
                }
      
                closeDatabase();
           }
      
           private void openDatabase( ) {
                try {
                     databaseFile = new RandomAccessFile("hardware.dat", "r");
                }
                catch(IOException e) {
                     System.err.println("Error opening database..");
                     e.printStackTrace();
                     System.exit(1);
                }
           }
      
           private void closeDatabase( ) {
                try {
                     if(databaseFile != null) {
                          databaseFile.close();
                          databaseFile = null;
                     }
                }
                catch(IOException e) {
                     System.err.println("Error closing database, file corrupted..");
                     e.printStackTrace();
                     System.exit(1);
                }
           }
      }
      Sorry for all the code! I just didn't want to leave anything out. I can't see why it throws an exception if the data types are right?
        • 1. Re: Random Access Files
          807569
          There are alot of quicky elements to your code. I don't like the way you pass around the file for example.

          Your immediate problem is that you are opening the file in read only mode. So no... you can't write to it.

          This line
          databaseFile = new RandomAccessFile("hardware.dat", "r");
          should be this
          databaseFile = new RandomAccessFile("hardware.dat", "rw");
          rw for read/write.
          • 2. Re: Random Access Files
            807569
            That was exactly the problem! Thanks a lot for the reply. I was overlooking the problem thinking it was larger. I know the code it not very pretty but I am still learning the language in school. Would you prefer passing it by reference to avoid a call to the copy constructor or how? Not pass the file at all?
            Thanks.
            • 3. Re: Random Access Files
              807569
              Would you prefer passing it by reference to avoid a call to the copy constructor
              There is no copy constructor in Java.
              Java is not C++.

              All references are passed by value. Allways. No exception.
              So it's only the references that are copied, not the actual objects.
              Simple isn't it?
              • 4. Re: Random Access Files
                807569
                Besides the pass by value issue which you should
                understand because it's a popular misconception I
                was more talking about your andomAccessAccount.
                Why is that a subclass at all?

                To me I would have a class that could fetch records
                (perhaps by index) and it would have the
                RandomAccessFile as a private attribute.
                • 5. Re: Random Access Files
                  807569
                  Gotcha, OK. I have been programming in C++ for a while now and just started learning Java not too long ago. I appreciate the help and tips. I was not aware there was no copy constructor in Java! So thanks for that as well.