Saturday, June 28, 2008

Java RandomAccessFile Example

Here is another example of how to use a common file handling mechanism in Java. RandomAccessFile is very powerful tool to open a file and find specific items in it. It also allows you to update, delete, or append data to the file. Developers become accustomed to using File for a number of operations, but I contend that using RandomAccessFile is more powerful and flexible.

In the code example and Netbeans project that follow, I create a file and append data to it. I print the data out, and then add the class name to the beginning of the file, append the existing data, and print it back out again.

I originally came across my work on it when I was learning Java many years ago. I re-examined it, tweaked it, and converted it to a Netbeans project.

1 /*
  2  * 
  3  * Blue Lotus Software, LLC
  4  * 
  5  * Copyright 2008. All Rights Reserved.
  6  * 
  7  * $Id$
  8  * 
  9  */
 10 /*
 11  * Copyright (C) 2008 Blue Lotus Software. All Rights Reserved.
 12  *
 13  * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND.
 14  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 15  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 16  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 
 17  * BLUE LOTUS SOFTWARE, LLC AND ITS LICENSORS SHALL NOT BE LIABLE 
 18  * FOR ANY DAMAGES OR LIABILITIES
 19  * SUFFERED BY LICENSEE AS A RESULT OF  OR RELATING TO USE, MODIFICATION
 20  * OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
 21  * BLUE LOTUS SOFTWARE, LLC OR ITS LICENSORS BE LIABLE FOR ANY LOST 
 22  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 
 23  * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED 
 24  * AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE 
 25  * OF OR INABILITY TO USE SOFTWARE, EVEN IF BLUE LOTUS SOFTWARE, LLC 
 26  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 27  *
 28  * You acknowledge that Software is not designed, licensed or intended
 29  * for use in the design, construction, operation or maintenance of any
 30  * nuclear facility.
 31  */
 32 package com.bluelotussoftware.j2se.examples;
 33
 34 import java.io.FileNotFoundException;
 35 import java.io.IOException;
 36 import java.io.RandomAccessFile;
 37 import java.util.logging.Level;
 38 import java.util.logging.Logger;
 39
 40 /**
 41  *
 42  * @author John Yeary
 43  * @version 1.0
 44  */
 45 public class RandomAccessFileExample {
 46
 47     private static final String CLASSNAME = RandomAccessFileExample.class.getName();
 48     private static Logger logger = Logger.getLogger(CLASSNAME);
 49
 50     /**
 51      * @param args the command line arguments
 52      */
 53     public static void main(String[] args) {
 54
 55         if (args.length < 1) {
 56             System.err.print("You must provide at least a file name with path!");
 57             logger.log(Level.WARNING, "You must provide at least a file name with path");
 58             System.exit(0);
 59         }
 60
 61         RandomAccessFile raf = null;
 62
 63         try {
 64             raf = new RandomAccessFile(args[0], "rw");
 65         } catch (FileNotFoundException e) {
 66             logger.log(Level.SEVERE, null, e);
 67             // Error, set return to 1, and exit 
 68             System.exit(1);
 69         }
 70
 71         for (int i = 1; i < args.length; i++) {
 72             try {
 73                 raf.seek(raf.length());
 74                 raf.writeBytes(args[i] + "\n");
 75             } catch (IOException e) {
 76                 logger.log(Level.SEVERE, null, e);
 77             }
 78         }
 79
 80         try {
 81             raf.close();
 82         } catch (IOException e) {
 83             logger.log(Level.SEVERE, null, e);
 84         }
 85
 86         RandomAccessFileExample.readRAF(args[0]);
 87
 88         try {
 89             raf = new RandomAccessFile(args[0], "rw");
 90
 91             /* If you call seek() before you read, it will not work
 92              * as expected. The read operation will move the cursor
 93              * to the end of the read method.
 94              */
 95             //raf.seek(0); 
 96
 97             byte[] b = new byte[(int) raf.length()];
 98             raf.read(b);
 99
100             /* Here we place the seek() method to append to
101              * start writing at the beginning of the file.
102              */
103             raf.seek(0);
104             raf.writeBytes(CLASSNAME + "\n");
105
106             // Append the original content of the file.
107             raf.write(b);
108             raf.close();
109         } catch (IOException ex) {
110             logger.log(Level.SEVERE, null, ex);
111         }
112         RandomAccessFileExample.readRAF(args[0]);
113     }
114
115     public static void readRAF(String fileName) {
116         try {
117             RandomAccessFile raf = new RandomAccessFile(fileName, "r");
118             String line = null;
119             while ((line = raf.readLine()) != null) {
120                 System.out.println(line);
121                 logger.log(Level.INFO, line);
122             }
123         } catch (FileNotFoundException ex) {
124             logger.log(Level.SEVERE, null, ex);
125         } catch (IOException ex) {
126             logger.log(Level.SEVERE, null, ex);
127         }
128     }
129 }

UPDATED 12/29/2009
The Netbeans project is here: RandomAccessFile.zip

Here is an example of how to delete a String value from the file.

public static void deleteRAF(String value, String fileName) {
        try {
            RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
            long position = 0;
            String line = null;
            while ((line = raf.readLine()) != null) {
                System.out.println("line::line.length()::position::getFilePointer()");
                System.out.println(line + "::" + line.length() + "::" + position + "::" + raf.getFilePointer());
                logger.log(Level.INFO, line);

                if (line.equals(value)) {
                    //Create a byte[] to contain the remainder of the file.
                    byte[] remainingBytes = new byte[(int) (raf.length() - raf.getFilePointer())];
                    System.out.println("Remaining byte information::" + new String(remainingBytes));
                    raf.read(remainingBytes);
                    //Truncate the file to the position of where we deleted the information.
                    raf.getChannel().truncate(position);
                    System.out.println("Moving to beginning of line..." + position);
                    raf.seek(position);
                    raf.write(remainingBytes);
                    return;
                }
                position += raf.getFilePointer();
            }
        } catch (FileNotFoundException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }

3 comments :

Ed Mazur said...

You state that it is possible to delete data from a file - how do you do this? I didn't think deletes were possible with RAF, only overwrites.

John Yeary said...

I have included a sample of how to delete a String value from the file.

John Yeary said...

I updated the project files for download.

Popular Posts