Como leer y escribir un fichero con RandomAccessFile

Hola a todos, hoy os voy a explicar como escribir un fichero con RandomAccessFile.

Con la clase RandomAccessFile podemos leer y escribir archivos de manera aleatoria, es decir, que nos podemos situar en una posición concreta, en lugar de tener que recorrer desde el principio.

Con esta clase, podemos escribir y leer con cada tipo de variable como integer, string, double, etc.

Se escribe de forma binaria en el archivo, por lo que no sera legible para nosotros al abrir el fichero.

Es importante saber que cada tipo de variable ocupa un numero de bytes.

  • Long: 8 bytes
  • Integer: 4 bytes
  • Short: 2 bytes
  • Byte: 1 byte
  • Double: 8 bytes
  • Float: 4 bytes
  • Boolean: 1 byte
  • Char: 2 bytes
  • String: 2 bytes por cada caracter.

Vamos a crear una clase Producto:


public class Producto {

    private int id;
    private String nombre;
    private double precio;
    private boolean descuento;
    private char tipo;

    public Producto(int id, String nombre, double precio, boolean descuento, char tipo) {
        this.id = id;
        this.nombre = nombre;
        this.precio = precio;
        this.descuento = descuento;
        this.tipo = tipo;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public double getPrecio() {
        return precio;
    }

    public void setPrecio(double precio) {
        this.precio = precio;
    }

    public boolean isDescuento() {
        return descuento;
    }

    public void setDescuento(boolean descuento) {
        this.descuento = descuento;
    }

    public char getTipo() {
        return tipo;
    }

    public void setTipo(char tipo) {
        this.tipo = tipo;
    }

    @Override
    public String toString() {
        return "Producto{" + "id=" + id + ", nombre=" + nombre + ", precio=" + precio + ", descuento=" + descuento + ", tipo=" + tipo + '}';
    }
    
}

Lo primero es crear los productos que vamos a insertar, yo los voy a meter en un ArrayList.


ArrayList<Producto> productos = new ArrayList<>();

productos.add(new Producto(1, "Producto 1", 10.5, true, 'T'));
productos.add(new Producto(2, "Producto 2", 15.1, true, 'R'));
productos.add(new Producto(3, "Producto 3", 11.5, false, 'T'));
productos.add(new Producto(4, "Producto 4", 50, false, 'D'));
productos.add(new Producto(5, "Producto 5", 79.3, true, 'U'));


Vamos a crear el objeto RandomaccessFile:


try (RandomAccessFile raf = new RandomAccessFile("ejemplo_raf.dat", "rw")) {


} catch (FileNotFoundException ex) {
    System.out.println(ex.getMessage());
} catch (IOException ex) {
    System.out.println(ex.getMessage());
}

Necesitamos dos parámetros, uno es la ruta del fichero y otro es el modo de los que tiene estos:

  • r: solo lectura.
  • rw: lectura y escritura. Este es el más usado.
  • rws: es como rw pero vacía el contenido del archivo y la fecha de modificación del archivo.
  • rwd: es como rw pero vacía el contenido del archivo, pero es posible que la fecha de modificación no cambie hasta que se cierre el archivo.

Es importante que a la hora de escribir lo hagamos en orden, para cada tipo de variable tenemos un método:


try (RandomAccessFile raf = new RandomAccessFile("ejemplo_raf.dat", "rw")) {

    for (Producto p: productos) {

        raf.writeInt(p.getId());

        StringBuffer sb = new StringBuffer(p.getNombre());
        sb.setLength(10);

        raf.writeChars(sb.toString());
        raf.writeDouble(p.getPrecio());
        raf.writeBoolean(p.isDescuento());
        raf.writeChar(p.getTipo());
    }


} catch (FileNotFoundException ex) {
    System.out.println(ex.getMessage());
} catch (IOException ex) {
    System.out.println(ex.getMessage());
}

En este caso, cada registro seria 35 bytes (4 (int) + (10 * 2) (string) + 8 (double) + 1 (boolean) + 2 (char)).

Es importante ver como añado los String, uso la clase StringBuffer y lo limito al tamaño que yo desee, en este caso a 10 caracteres, si tiene menos caracteres, lo rellenará con espacios y si tiene más lo cortará. Como he comentado, es importante saber cuánto ocupa cada String para después leer, por eso todos deben tener un tamaño fijo.

Pues ahora vamos a leer el fichero con RandomAccessFile, lo primero es posicionarse en que posición queremos empezar. Esto lo podemos hacer con el método seek, indicando el byte a posicionarse.

También es importante que debemos leer en el orden de como escribimos.

Por lo que si queremos posicionarnos en el segundo registro, tendremos que usar seek(35), ya que el primero es el byte 0, si quisiéramos el tercer registro seria seek(70).

Veamos como se lee:


raf.seek(35);

System.out.println(raf.readInt());
String nombre = "";
for (int i = 0; i < 10; i++) {
    nombre += raf.readChar();
}
System.out.println(nombre);
System.out.println(raf.readDouble());
System.out.println(raf.readBoolean());
System.out.println(raf.readChar());

Te dejo el ejemplo completo:



import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;

public class EjemploRandomAccessFile {

    public static void main(String[] args) {

        ArrayList<Producto> productos = new ArrayList<>();

        productos.add(new Producto(1, "Producto 1", 10.5, true, 'T'));
        productos.add(new Producto(2, "Producto 2", 15.1, true, 'R'));
        productos.add(new Producto(3, "Producto 3", 11.5, false, 'T'));
        productos.add(new Producto(4, "Producto 4", 50, false, 'D'));
        productos.add(new Producto(5, "Producto 5", 79.3, true, 'U'));

        try (RandomAccessFile raf = new RandomAccessFile("ejemplo_raf.dat", "rw")) {

            for (Producto p : productos) {

                raf.writeInt(p.getId());

                StringBuffer sb = new StringBuffer(p.getNombre());
                sb.setLength(10);

                raf.writeChars(sb.toString());
                raf.writeDouble(p.getPrecio());
                raf.writeBoolean(p.isDescuento());
                raf.writeChar(p.getTipo());
            }

            raf.seek(35);

            System.out.println(raf.readInt());
            String nombre = "";
            for (int i = 0; i < 10; i++) {
                nombre += raf.readChar();
            }
            System.out.println(nombre);
            System.out.println(raf.readDouble());
            System.out.println(raf.readBoolean());
            System.out.println(raf.readChar());

        } catch (FileNotFoundException ex) {
            System.out.println(ex.getMessage());
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }

    }

}


Para leer los String, os recomiendo leer la longitud que hayamos decidido y guardarlo en un String.

Este seria el resultado:

Te dejo aquí el ejemplo para descargar.

Espero que os guste. si tenéis dudas, preguntad. Estamos para ayudarte.

Etiquetas

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *