Saiyine
Punto Com

Leer de un fichero byte a byte simulando un read, pero muchisimo mas rapido

0000-00-00 00:00:00

A peticion de Manulon, ahi va una unidad para lectura rapida de ficheros... forma parte de un viejo proyecto, de cuando salieron los mp3, tenia curiosidad por ver cual era el mejor compresor e hice un comparador de wavs, quizas algun dia haga una version 'para todos los publicos' para que saqueis vuestras propias conclusiones...

La unidad debe llamarse UCacheLecturaSecuencial.pas para evitar problemas (los nombres largos del windows hay que aprovecharlos ).

unit UCacheLecturaSecuencial;

interface

type
        Fichero_CLS = class
        private
        f : file;
        buf : array[0..1999] of byte;
        status,puntero,punterototal,maximo : integer;
        procedure Actualizar;
        public
        constructor Crear(fichero : string);
        destructor Cerrar;
        function LeerByte : byte;
        function LeerInteger : Integer;
        function LeerLongint : Longint;
        function ComprobarEstado : Integer;
end;

implementation

procedure Fichero_CLS.Actualizar;
begin
        blockread(f,buf,sizeof(buf),maximo);
        puntero:=0;
        if maximo>0
        then status:=0
        else status:=1;
end;

constructor Fichero_CLS.Crear(fichero : string);
begin
        assignfile(f,fichero);
        reset(f,1);
        Actualizar;
        punterototal:=0;
end;

destructor Fichero_CLS.Cerrar;
begin
        closefile(f);
end;

function Fichero_CLS.LeerByte : byte;
begin
        result:=buf[puntero];
        inc(puntero);
        inc(punterototal);
        if puntero>=maximo then Actualizar;
end;

function Fichero_CLS.LeerInteger : Integer;
var
aux : integer;
begin
        aux:=LeerByte;
        aux:=aux*$FF+LeerByte;
        result:=aux;
end;

function Fichero_CLS.LeerLongint : Longint;
var
aux : Longint;
begin
        aux:=LeerByte;
        aux:=aux*\$FF+LeerByte;
        aux:=aux*\$FF+LeerByte;
        aux:=aux*\$FF+LeerByte;
        result:=aux;
end;

function Fichero_CLS.ComprobarEstado : Integer;
begin
        result:=status;
end;

end.

Para usarla basta añadir UCacheLecturaSecuencial.pas al directorio del programa o a un directorio especifico para librerias y meter UCacheLecturaSecuencial en el uses de la unidad que lo use. Un ejemplo de uso seria este:

procedure TForm1.Button1Click(Sender: TObject);
var
fich : Fichero_CLS;
begin
        fich:=Fichero_CLS.Crear('y:\gadda_CD.wav');
        while fich.ComprobarEstado=0 do
        Caption:='Primer entero: '+ inttostr(fich.LeerByte);
        fich.Cerrar;
end;
Jose Luis (27/01/2005, 19:22)

Hola Saiyine.

Te escribo interesado en la informacion que tienes sobre la lectura rapida de un fichero (byte a byte). Yo tengo que hacerlo pero en C++ y escribia a ver si me puedes echar una mano. La verdad es que no entiendo muy bien lo que haces con ese codigo (supongo que tendra que ver que yo no tengo ni idea de delphi) y me preguntaba si me podrí­as explicar que es lo que haces exactamente.

Mi problema es que tengo que leer (solo leer) datos de tamaño fijo desde un archivo binario que ya esta creado. Se que utilizando la API de Windows hay una manera de hacerlo de forma rapida (utilizando las funciones createfile, creo que virtualalloc...) siempre que antes prepares el sistema adecuadamente, si no el programa es igual de lento que haciendo un read. Si puedes explicarme como va tu codigo tal vez me ayude en mi proyecto.

Gracias de antemano y un saludo
Joste

Saiyine (28/01/2005,01:19)

Hola, Joste.

Procuro no acercarme a nada que huela a C, salvo cuando no hay más remedio, y cuando no lo hay procuro limpiar mi mente enseguida, así­ que no te sabria decir lineas de código de lo que tienes que hacer.

Lo que si puedo decirte que con createfile, por el nombre de la función, no vas bien para leer de un fichero. La función read que mencionas imagino que será la misma que poseen todos los lenguajes para leer de un fichero, salvo que me esté confundiendo, con que le subas el tamaño del buffer de lectura bastará para que obtengas un gran aumento de velocidad de lectura.

Mi código, que por cierto lleva ya casi cuatro escrito así­ que lo tengo algo olvidado, simula un "read" de byte en byte, que normalmente seria lentisimo, pero usando internamente lectura en bloques mucho más grandes, que forman una cache que acelera mucho el proceso. Es decir, el usuario lee el fichero byte a byte, mientras que el programa lee bloques según sea necesario. Vaya, una caché de lectura de toda la vida.

En esta página parece que hacen algo similar en C++.


Jose Luis (31/01/2005, 18:50)

Hola otra vez!!

Asi que c++ te da urticaria, jeje. Yo ahora me estoy iniciando en java, pero hasta que lo domine mejor sigo con c++

Bueno, para empezar gracias por la ayuda, aunque me temo que mis investigaciones no van por ese camino aunque voy a mirar un poco sobre la cache de lectura... me ha gustado. El link que me has puesto trata sobre escritura y lectura estandar de archivos. No es lo que busco.

Por otro lado, la funcion CreateFile de la API de windows si que sirve para abrir archivos, aunque si no existe el mismo lo crea. La idea que tengo en mente es reservar un espacio de memoria virtual (creo que con virtualalloc de la api tambien), abrir un archivo y luego copiar todo lo necesario a toda pastilla. A ver si lo consigo. Lo que pensaba era hacerlo con un puntero, despues de haber reservado la zona de memoria virtual y teniendo la posición de memoria de los datos, recorrer con un puntero los datos y copiarlo, pero estoy seguro de que hay una forma mas rapida de conseguirlo mediante bloques de memoria. Lo que no se es que funcion utilizar y como utilizarla.
Bueno sigo investigando, y gracias otra vez.

Por cierto, me ha entrado curiosidad con esto de delphi, igual me miro algo...

Un saludo

Rollos antiguos

0000-00-00 00:00:00 - Largo de una cadena en pixels sabiendo la fuente usada para imprimirla.

2006-02-21 20:07:00 - Justificar el texto de un memo, listbox, etc.

0000-00-00 00:00:00 - Filtrar entrada en los edit.

0000-00-00 00:00:00 - Hacer un mismo codigo para varios controles.

0000-00-00 00:00:00 - Hacer un edit con filtro, por ejemplo, que solo acepte numeros hexadecimales..

Saiyine

Selfie of meHi! Welcome to Saiyine Punto Com where I talk about anything that goes through my mind!

Puedo prometer y prometo que a la mayor brevedad aquí irá un menú o algo asín.