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:

Dany dijo...

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

Anónimo dijo...

Me ha sido de mucha utilidad. Muchas gracias :D

Rafael Antonio Rojas Jaque dijo...

gracias por el codigo, me facilito el trabajo de veras muchas gracias

Unknown dijo...

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

Administrador dijo...

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.

rpa dijo...

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?

Administrador dijo...

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.

study dijo...

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.

Administrador dijo...

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.

GEFERdMAUSER dijo...

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?,

GEFERdMAUSER dijo...

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?

Administrador dijo...

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.

HALWSEMON dijo...

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..

HALWSEMON dijo...

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

Unknown dijo...

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.

Unknown dijo...

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;

Administrador dijo...

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.

Unknown dijo...

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?

Administrador dijo...

Pues igual que el anterior pero al revés:

BlockWrite(.....

Prepara un buen buffer para que grabe bloques grandes.

Unknown dijo...

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

Unknown dijo...

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

Unknown dijo...

¿perdona mi ignorancia pero donde queda guardado el archivo?

Unknown dijo...

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

Publicidad