28 agosto 2007

Trabajando con archivos de texto y binarios (I)

Voy a mostrar a continuación las distintas maneras que tenemos para crear, editar o eliminar archivos de texto o binarios. También aprenderemos a movermos por los directorios y por dentro de los archivos obteniendo la información del sistema cuando sea necesario.

CREANDO UN ARCHIVO DE TEXTO

Los pasos para crear un archivo son los siguientes:

1º Se crea una variable de tipo TextFile, la cual es un puntero a un archivo de texto.

2º Se utiliza la función AssignFile para asignar el puntero F al archivo de texto.

3º A continuación abrimos el archivo en modo escritura mediante el procedimiento Rewrite.

4º Escrimimos en el archivo mediante la función WriteLn.

5º Cerramos el archivo creado con el procedimiento CloseFile.

Vamos a crear un procedimiento para crear el archivo prueba.txt al lado de nuestro programa:

procedure TFormulario.CrearArchivoTexto;
var
F: TextFile;
begin
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'prueba.txt' );
Rewrite( F );
WriteLn( F, 'Esto es el contenido del archivo de texto.' );
CloseFile( F );
end;

MODIFICANDO UN ARCHIVO DE TEXTO

Cuando se utiliza la función Rewrite no comprueba si el archivo ya existía anteriormente, lo que puede provocar que elimine la información anterior. Para prevenir esto lo que hacemos es preguntar si ya existe el archivo y si es así entonces añadimos al contenido del archivo mediante el procedimiento Append:

procedure TFormulario.AnadirArchivoTexto;
var
F: TextFile;
sArchivo: string;
begin
sArchivo := ExtractFilePath( Application.ExeName ) + 'prueba.txt';
AssignFile( F, sArchivo );

if FileExists( sArchivo ) then
Append( F )
else
Rewrite( F );

WriteLn( F, 'Añadiendo información al archivo de texto.' );
CloseFile( F );
end;

ABRIENDO UN ARCHIVO DE TEXTO

Vamos a abrir el archivo de texto en modo lectura para volcar su contenido en un campo memo del formulario. Para ello abrimos el archivo con el procedimiento Reset y leemos cada línea de texto mediante ReadLn:

procedure TFormulario.CargarArchivoTexto;
var F: TextFile;
sLinea: String;
begin
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'prueba.txt' );
Reset( F );

while not Eof( F ) do
begin
ReadLn( F, sLinea );
Memo.Lines.Add( sLinea );
end;

CloseFile( F );
end;

El procedimiento ReadLn obliga a leer la línea de texto dentro de una variable. Después incrementa automáticamente el puntero F hasta la siguiente línea de texto, siendo la función Eof la que nos dice si ha llegado al final del archivo. Aunque en este caso lo más fácil sería utilizar la propiedad LoadFromFile del objeto memo:

Memo.Lines.LoadFromFile( ExtractFilePath( Application.ExeName ) + 'prueba.txt' );

ELIMINANDO UN ARCHIVO

La eliminación de un archivo se hace con la función DeleteFile la cual está dentro de la unidad SysUtils:

procedure TFormulario.EliminarArchivoTexto;
var sArchivo: String;
begin
sArchivo := ExtractFilePath( Application.ExeName ) + 'prueba.txt';
if FileExists( sArchivo ) then
DeleteFile( sArchivo );
end;

Todas estas funciones (Rewrite, Append, etc.) vienen del lenguaje estándar de Pascal, ya que en Delphi hay maneras mucho más sencillas de realizar estas tareas, como veremos más adelante.

Pruebas ralizadas en Delphi 7.

23 comentarios:

  1. Muy bueno el blog. Me facilita mucho mi trabajo. Enhorabuena y sigue así.

    ResponderEliminar
  2. Anónimo9:33 a. m.

    Me ha sido de mucha utilidad. Muchas gracias :D

    ResponderEliminar
  3. gracias por el codigo, me facilito el trabajo de veras muchas gracias

    ResponderEliminar
  4. Usando este metodo, solo me lee las primeras 70558 lineas de un archivo de texto ¿por que?.

    ResponderEliminar
  5. Debería poder leer todas las líneas que quieras. Lo que ocurre es que si vas a leer archivos de texto muy grandes no deberías utilizar este método, sino leyendo grandes bloques mediante buffer o con un TFileStream.

    Saludos.

    ResponderEliminar
  6. ola disculpa pero quiero crear un texto asi como indicas pero la la vdd es que no se nada de delphi y no se que elemento debo arrastrar al formulario ya intente con un memo, label, button, pero no aparece uno q diga "crearArchivo.exe"
    que debo hacer desde el principio? o sea despues de abrir el borland delphi y antes de introducir la secuencia del programa?

    ResponderEliminar
  7. Antes de tirarte al toro te recomiendo que te pilles un libro de introducción a Delphi, ya que aunque este lenguaje pueda parecer sencillo al principio, se va complicando a cada paso que das.

    Ten paciencia y aprende primero las bases. Ten en cuenta que mis artículos están destinados a programadores que ha tienen bastantes nociones de Delphi. Son soluciones a problemas concretos.

    Avanza paso a paso.

    ResponderEliminar
  8. No voy a mentir delphi no me gusta ni un poquito. Pero dado que en el estudio desde que en el estudio de desarrollo donde trabajo me encajaron este ide/lenguaje este blog me ha sido de mucha utilidad.

    ResponderEliminar
  9. Ningún lenguaje es ni muy bueno ni muy malo, depende más de la API de desarrollo y de la documentación que del lenguaje en si.

    Yo llevo muchos años con Delphi y aunque tiene cosas que te dan ganas de patearlo, en general, no he encontrado ningún compilador más rápido y con el que puede hacer de todo como Delphi.

    Las máquinas virtuales (NET y Java) me dan alergia. No puedo con el software lento.

    Saludos.

    ResponderEliminar
  10. Hola, gracias por el aportetodo parece muy coherente,un favor podrias decirme que elementos debe contener el formulario para que sea compatible con el codigo que nos presentas?,

    ResponderEliminar
  11. ah y tengo otra duda, tal ves sea una pregunta un tanto ingenua, pero es que hace poco que estoy trabajando con delphi, ¿como puedo asignarle la ruta de acceso al archivo de texto?

    ResponderEliminar
  12. El código de este artículo es compatible con cualquier formulario de Delphi.

    La ruta de acceso a un archivo puede asignarse directamente o utilizando la función ExtractFilePath(Application.Exename) para extraer la ruta donde se encuentra nuestro ejecutable.

    ResponderEliminar
  13. hola buen dia.. soy algo inesperto en esto de los codigos en delphi.. solo quisisera saber si esto hay que ponerlo en algun botton o siemplemente como cabecera.. oajal me puedas ayudar.. gracia..

    ResponderEliminar
  14. .. soy algo inesperto con delphi.. quiero crear archivos de texto.. me podrias indicar si esto lo podriamos poner en un boton.. muchas gracias..

    ResponderEliminar
  15. Hola. Necesito leer un archivo de texto de unos 3 millones de registros de 10 caracteres de largo, para colocarlos en una base Firebird. Hice el prototipo usando ReadLn y probando con un par de miles de registros, y claro, funciona. Estoy investigando lo del TFileStream que señalaste, pero agredecería una alguna sugerencia previa.
    Saludos y gracias.

    ResponderEliminar
  16. buenas... lo hice con TFileStream, pero mi problema es que el procedimiento es demasiado lento. ¿Alguien conoce otra forma de hacerlo más ágilmente?. Adjunto el código. Gracias

    procedure TForm1.btnCargarCodigosClick(Sender: TObject);
    var
    txtFile: TFileStream;
    sLine: array [0..255] of Char;

    b: boolean;
    n, m, nLargoCodigo: integer;

    begin
    b:= False;
    n:= 1;
    m:= 0;
    ProgressBar1.Min:= 0;
    ProgressBar1.Max:= 1000;
    ProgressBar1.Position:= m;

    if OpenDialog1.Execute = True then
    begin
    txtFile := TFileStream.Create(OpenDialog1.FileName,fmOpenRead or fmShareExclusive);

    ZQuery1.Close;
    ZQuery1.SQL.Clear;
    ZQuery1.SQL.Append('delete from codigos');
    ZQuery1.ExecSQL;
    ZTable1.Open;

    nLargoCodigo:= 0;
    txtFile.Read(sLine, 16); //15, largo máximo del campo en la base de datos
    nLargoCodigo:= Pos(#13#10,sLine) - 1;
    txtFile.Position:= 0;
    sLine:= '';

    if (nLargoCodigo > 0) and (nLargoCodigo <= 15) then
    begin
    while txtFile.Position < txtFile.Size do
    begin
    txtFile.Read(sLine, nLargoCodigo); //lee hasta el largo del campo, sin contar 0D 0A
    try
    ZTable1.AppendRecord([
    sLine,
    0,
    n
    ]);
    b:= True;
    Inc(n);
    Inc(m);
    txtFile.Position:= txtFile.Position + 2;

    ProgressBar1.Position:= m;
    if m > ProgressBar1.Max then
    m:= 0
    ;
    Label1.Caption:= IntToStr(n) + ' códigos leídos';
    except
    begin
    ShowMessage('Error al insertar código "' + sLine + '"' + #13#10 + 'El archivo de códigos no será cargado');
    ZQuery1.Close;
    ZQuery1.SQL.Clear;
    ZQuery1.SQL.Append('delete from codigos');
    ZQuery1.ExecSQL;
    b:= False;
    exit;
    end;
    end;
    end
    ;
    ZTable1.Close;
    txtFile.Free;
    end
    ;
    end
    ;

    if b = True then
    begin
    Label1.Caption:= IntToStr(n - 1) + ' códigos cargados correctamente';
    modo:= codigos;
    //btnComenzar.Enabled:= True;
    end
    else
    begin
    Label1.Caption:= IntToStr(n) + ' códigos cargados correctamente. Error en valor ' + sLine;
    modo:= none;
    end
    ;
    end;

    ResponderEliminar
  17. Prueba a utilizar la función Blockread, que te permite cargar archivos por bloques mediante buffer:

    http://delphiallimite.blogspot.com/2007/09/trabajando-con-archivos-de-texto-y.html

    Es un poco más difícil de implementar pero los resultados son espectaculares. Cuanto más grande es el buffer, más rápido lee el archivo.

    ResponderEliminar
  18. Gracias por la sugerencia. Pero después de postear, me di cuenta que mi problema mayor no está en el archivo de texto, sino en el AppendRecord, ahí es donde se demora ¿otra sugerencia, please?

    ResponderEliminar
  19. Pues igual que el anterior pero al revés:

    BlockWrite(.....

    Prepara un buen buffer para que grabe bloques grandes.

    ResponderEliminar
  20. Gracias por los ejemplos.Oye la verdad es que no se nada de delphi (tengo ya 2 años con Visual 6.0) me puedes enviar a mi correo el source code de el ejemplo crear un archivo txt con delphi es que me tira muchs errorres y no los entiendo para poder solucionarlos.Apoyame :

    ramirezjunior220@yahoo.es

    ResponderEliminar
  21. buenas estoy probando el codigo y el error que me da es que no reconoce AssingFile porq? donde y como debo declarar el AssingFile

    ResponderEliminar
  22. ¿perdona mi ignorancia pero donde queda guardado el archivo?

    ResponderEliminar
  23. Disculpe. El archivo de texto solo puede ser leído en forma descendente porque? Porque me gustaría regresarme varias líneas atrás si se cumple una condición

    ResponderEliminar