Skip to content

4 Ficheros Binarios

Introducción

Los ficheros binarios almacenan secuencias de dígitos binarios que no son legibles directamente por el usuario. Tienen la ventaja de que ocupan menos espacio en disco.

En Java, las dos clases que que nos permiten trabajar con ficheros son FileInputStream, para entrada de datos, y FileOutputStream, para salida. Estas dos clases trabajan con flujos de bytes y crean un enlace entre el flujo de bytes y el fichero.

FileInputStream

Los métodos que proporciona la clase FileInputStream para lectura son similares a los vistos para la clase FileReader, estos métodos devuelven el número de bytes leídos o -1 si se ha llegado al final.

Método Función
int read() Lee un byte y lo devuelve
int read(byte[] b) Lee hasta b.length bytes de datos de una matriz de bytes
int read(byte[] b, int desplazamiento, int n) Lee hasta n bytes de la matriz b comenzando por b[desplazamiento] y devuelve el número leído de bytes.
public class ReadFile {
    public void show() throws IOException {
        File file = new File("src/exercises/bloque_iv/tema_14/binary_files/ReadFile.java");
        FileInputStream reader = new FileInputStream(file);

        int i;
        while ((i = reader.read()) != -1) { 
            System.out.println((char) i);
            reader.close();
        }
    }

    public static void main(String[] args) throws IOException {
        new ReadFile().show();
    }
}

FileOutputStream

Los métodos que proporciona la clase FileOutputStream para escritura son:

Método Función
void write() Escribe un byte
void write(byte[] b) Escribe b.length bytes
void write(byte[] b, int desplazamiento, int n) Escribe n bytes de la matriz b comenzando por b[desplazamiento].

Para añadir bytes al final del fichero usaremos FileOutputStream colocando en el segundo parámetro del constructor el valor true.

public class WriteFile {
    public void show() throws IOException {
        File fichero = new File("file.txt"); //declarar fichero
        FileOutputStream fic = new FileOutputStream(fichero);

        String cadena = "Esto es una prueba con FileWriter";

        char[] cad  = cadena.toCharArray();
        for (char c : cad) {
            fic.write(c); // se va escribiendo un carácter
        }

        fic.close(); //cerrar fichero
    }

    public static void main(String[] args) {
        new WriteFile().show();
    }
}

Lectura y escritura de datos primitivos

Para leer y escribir datos de tipos primitivos: int, float, long, etc usaremos las clases DataInputStream y DataOutputStream. Estas clases definen diversos métodos readXXX y writeXXX que son variaciones de los métodos read() y write() de la clase base para leer y escribir datos de tipo primitivo. Algunos de los métodos se muestran en la siguiente tabla:

MÉTODOS PARA LECTURA MÉTODOS PARA ESCRITURA
boolean readBoolean(); void writeBoolean(boolean v);
byte readByte(); void writeByte(int v);
int readUnsignedByte(); void writeBytes(String s);
int readUnsignedShort(); void writeShort(int v);
short readShort(); void writeChars(String s);
char readChar(); void writeChar(int v);
int readInt(); void writeInt(int v);
long readLong(); void writeLong(long v);
float readFloat(); void writeFloat(float v);
double readDouble(); void writeDouble(double v);
String readUTF(); void writeUTF(String str);

Para crear un objeto det tipo DataInputStream o DataOutputStream es necesario pasarle como argumento en el constructor un FileInputStream y un FileOutputStream, respectivamente.

El siguiente ejemplo inserta datos en el fichero data_file.dat, los datos los toma de dos arrays, uno contiene los nombres de una serie de personas y el otro sus edades, recorremos los arrays y vamos escribiendo en el fichero el nombre y la edad.

public class DataWrite {
    public void show() throws IOException {
        File f = new File("FilesData.dat");
        FileOutputStream file = new FileOutputStream(f);
        DataOutputStream writer = new DataOutputStream(file);
        String[] nombres = {"Ana", "Luis Miguel", "Alicia", "Pedro", 
                "Manuel", "Andrés", "Julio", "Antonio", "María Jesús"};
        int[] edades = {14, 15, 13, 15, 16, 12, 16, 14, 13};

        for (int i = 0; i < edades.length; i++) {
            writer.writeUTF(nombres[i]); // escribe nombre
            writer.writeInt(edades[i]); // escribe edad
        }

        writer.close(); // cierre
    }

    public static void main(String[] args) throws IOException {
        new DataWrite().show();
    }
}

En el siguiente ejemplo visualiza los datos grabados anteriormente en el fichero, se deben recuperar en el mismo orden en el que se escribieron, es decir, primero obtenemos el nombre y luego la edad.

public class DataRead {
    public void show() throws IOException {
        File f = new File("FilesData.dat");
        FileInputStream file = new FileInputStream(f);
        DataInputStream reader = new DataInputStream(file);
        String n;
        int e;

        try{
            while(true){
                n = reader.readUTF(); // recupera el nombre
                e = reader.readInt(); // recupera la edad
                System.out.println("Nombre: " + n + ", edad: " + e );
            }
        } catch(EOFException ignored){}

        reader.close();
    }

    public static void main(String[] args) throws IOException {
        new DataRead().show();
    }
}