Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 13-07-2003
Ane Ane is offline
Registrado
 
Registrado: jul 2003
Posts: 5
Poder: 0
Ane Va por buen camino
Question Problemas con ficheros de datos

Hola,
Estoy haciendo un programa donde necesito almacenar datos que contengan una parte de texto y una parte para números enteros. Para ello, he definido un fichero de datos de la siguiente forma:
type
TReg = record
Txt: TextFile;
num: Integer;
end;
var
FileReg: File of TReg;
Reg: TReg;
Para estudiarlo, he creado un formulario de prueba que contiene un Memo y dos botones. La idea es: introducir una cadena en el Memo, guardarla (presionando el botón btnGuardar) y después ver lo que se ha almacenado (presionando el botón btnVer).
El problema es que si se introducen grandes cadenas, sólo muestra en el Memo el final de dichas cadenas, las parte y no las muestra enteras. No sé qué es lo que está mal, y el por qué hace esto.
Los procedimientos que he empleado son:
procedure TForm1.btnGuardarClick(Sender: TObject);
var
i: Integer;
begin
AssignFile(FileReg, 'C:\T.dat');
ReWrite(FileReg);
AssignFile(Reg.Txt, 'C:\R.txt');
ReWrite(Reg.Txt);
Reg.num:= 0;
for i:= 0 to (Memo1.Lines.Count - 1) do
begin
Write(Reg.Txt, Memo1.lines[i]);
end;
Seek(FileReg,0);
Write(FileReg,Reg);
Memo1.Lines.Clear;
CloseFile(Reg.Txt);
CloseFile(FileReg);
end;

procedure TForm1.btnVerClick(Sender: TObject);
var
buffer: string;
begin
AssignFile(FileReg, 'C:\T.dat');
Reset(FileReg);
AssignFile(Reg.Txt, 'C:\R.txt');
ReWrite(Reg.Txt);
Seek(FileReg,0);
Read(FileReg, Reg);
Reset(Reg.Txt);
while not Eof(Reg.Txt) do
begin
Read(Reg.Txt, buffer);
Memo1.lines.Add(buffer);
end;
CloseFile(Reg.Txt);
Erase(Reg.Txt);
CloseFile(FileReg);
Erase(FileReg);
end;
Estoy comenzando en esto de la programación en Delphi y sé que lo normal es emplear estructuras del tipo:
type
TReg = record
Txt: string[20];
num: Integer;
end;
var
FileReg: File of TReg;
Reg: TReg;
pero en mi caso no puedo emplear esto porque las cadenas a almacenar es muy posible que superen los 255 caracteres.
Si alguien puede darme alguna pista sobre lo que estoy haciendo mal, lo agradecería mucho.
Gracias de antemano por atender mi petición.
Responder Con Cita
  #2  
Antiguo 14-07-2003
Jose_Pérez Jose_Pérez is offline
Miembro
 
Registrado: may 2003
Posts: 156
Poder: 22
Jose_Pérez Va por buen camino
Hola Ane:

A ver si esto te funciona:

Prueba a poner el valor True (verdadero) en la propiedad WordWrap del componente TMemo.

Suerte.
Responder Con Cita
  #3  
Antiguo 14-07-2003
Ane Ane is offline
Registrado
 
Registrado: jul 2003
Posts: 5
Poder: 0
Ane Va por buen camino
Gracias por contestar a mi problema, pero la propiedad WordWrap del TMemo ya estaba a True.
¿alguna pista de qué puede estar mal?
Gracias.
Responder Con Cita
  #4  
Antiguo 15-07-2003
nachoasensio nachoasensio is offline
Miembro
 
Registrado: may 2003
Ubicación: Málaga
Posts: 61
Poder: 22
nachoasensio Va por buen camino
Hola:

Hace ya mucho tiempo que el tipo string no tiene la limitación de 255 caracteres en Delphi. La mejor solución es que cambies el registro para que sea:

type Reg = record
Txt : string;
num: integer;
end;


Y luego, en lugar de ir asignando línea a línea el Memo, puedes hacer:

Reg.Txt := Memo1.Text;

Éso te preserva todo el texto, incluyendo tabuladores (si está activo WantTabs) y saltos de línea.


Espero haberte ayudado.

Un saludo

Nacho
Responder Con Cita
  #5  
Antiguo 15-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Posteado originalmente por nachoasensio
Hace ya mucho tiempo que el tipo string no tiene la limitación de 255 caracteres en Delphi. La mejor solución es que cambies el registro para que sea:

type Reg = record
Txt : string;
num: integer;
end;
jejeje, hola nachoasensio. Esto fue lo primero que se me ocurrio para contestar, pero antes de hacerlo hice la prueba y, claro esta, no funciona

Para lo que expones (

****** le di a SUMMIT sin querer, sorry, continua en el de abajo

Última edición por __cadetill fecha: 15-07-2003 a las 10:48:33.
Responder Con Cita
  #6  
Antiguo 15-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Posteado originalmente por nachoasensio
Hace ya mucho tiempo que el tipo string no tiene la limitación de 255 caracteres en Delphi. La mejor solución es que cambies el registro para que sea:

type Reg = record
Txt : string;
num: integer;
end;
jejeje, hola nachoasensio. Esto fue lo primero que se me ocurrio para contestar, pero antes de hacerlo hice la prueba y, claro esta, no funciona

Para lo que expones (que es lo que yo pensaba), necesitas declarar una variable de tipo File of Reg y, al declararla, te saltara un error muuu bonito que dice que tiene que ser de tamaño fijo una declaracion de ese tipo (mas o menos y traduciendo muu a mi manera).
El error es precisamente por lo que comentas, porque una variable string ya no es solo de 255 caracteres.

La unica solocion que yo le vi, era limitar eso poniendo algo como...

Código:
type Reg = record
        Txt : string[255];
        num: integer;
end;
Pero claro, ya no se podria escribir todo el texto que uno quisiera, te limitas a una cierta cantidad de caracteres que no es lo que desea nuestro amigo/a Ane

Una solucion que se me acaba de ocurrir mientras escribia esto, es que la variable Txt del record lo que indicase fuera el PATH de un nombre de un archivo y que para grabar el contenido de un memo utilizara un metodo de la classe TStrings que es el SaveToFile

Memo1.Lines.SaveToFile('c:\lolo.txt');

y claro, Txt valdria el "c:\lolo.txt"

Espero que os sirva

Última edición por __cadetill fecha: 15-07-2003 a las 10:50:14.
Responder Con Cita
  #7  
Antiguo 15-07-2003
nachoasensio nachoasensio is offline
Miembro
 
Registrado: may 2003
Ubicación: Málaga
Posts: 61
Poder: 22
nachoasensio Va por buen camino
Efectivamente, cadetill tiene razón (eso me pasa por no dedicar más tiempo a pensar en el problema y responder demasiado deprisa).

Otra posible solución es declarar el fichero FileReg directamente como TextFile y "esconder" el número en el propio fichero, delimitado por un par de caracteres que no se utilicen en el fichero, por ejemplo |45|.´Creo que es la solución más sencilla. La primera línea contiene el número, las siguientes contienen el texto, hasta que se encuentre el delimitador; éste indicará que estamos ante otro registro; es decir:

|45|
dhjfsd sdjklh sdh fs fsd fsld fl sdfsdh fhsdf
sdfs
df
sdf
sdf
sdfsd fgasd fsdjfgsd fjgs d fs
|34|
dfl´ñskd f sdfj sdklñfañs ñfasdññfasñdfsadf
asd f
asd
fa
sd
fsdf asdjkl fasdjklfasd f
ds
fda
s fasd
|27|
sdjk fksf
sdfsd
f
d
s
f


Meter la información es ahora trivial. Para sacarla basta ir buscando la letra '|' con Pos, con algo como:

Memo1.Lines.LoadFromFile('..........');

Texto := Memo1.Text;
cont := 1;

//1ª aparición de '|'
Pos1 := Pos('|', Texto);

while (Pos1 > 0) do
begin

// 2ª aparición de '|'
Pos2 := Pos('|'+Chr(13)+Chr(10), Texto);

//Extraemos el núm. Numero[i] es un array de enteros
Numero[cont] := StrToInt(Copy(Texto, Pos1+1, Pos2-1));

// Eliminamos el '|nº|'+Salto de línea
Texto := Copy(Texto, Pos2+3, Length(Texto));

// Buscamos el siguiente '|'
Pos1 := Pos('|', Texto);

if Pos1 > 0 then
//Extraemos el texto del registro cont
Contenido[cont] := Copy(Texto, 1, Pos1-3); // El -3 es para
// eliminar el salto de línea tras el texto

// Incrementamos el contador
INC(cont);
end; // del while


Tras el bucle en Numero[i] están los números y en Contenido[i] están los contenidos. Hay que iterar desde 1 hasta cont-1.

Nota: el código lo he escrito al vuelo, a lo mejos se me ha pasado algo.

Espero que, ahora sí , te sirva.

Un saludo

Nacho
Responder Con Cita
  #8  
Antiguo 15-07-2003
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
Hola.

El almacenar strings largos de longitud variable es un tema interesante y algo complicado, al igual hay varias formas de abordarlo.

Si tu archivo no va a tener muchos registros y no necesitas hacer movimientos rápidos dentro de él, sino podes limitarte a movimietnos secuenciales, podes utilizar un FileStream.

Así, yo lo que hago es primero almacenar en un entero de 32 bits la longitud del texto que sigue y luego ya se cuanto leer del stream. Por supuesto, esto anula cualquier capacidad Seek que querras darle a tu fichero.

Otra opción (la menos elegante) es almacenar en un archivo externo los datos de texto de cada registro, con lo que podes hacer busquedas secuenciales y movimientos rápidos del tipo Seek(NumeroRegistro).

Por último, podes utilizar dos ficheros, uno que contenga el registro con los datos de longitud fija y otro que contenga los datos de texto. De esta forma, en el primero podrias almacenar la posición inicial y la longitud del texto perteneciente al registro actual en el otro archivo, que sería un mar de letras (o una sopa, quizas... )

Esa solución, que puede ser la mas apropiada, sin embargo, es dificil de implementar de una forma eficiente, sobre todo si necesitas dar al usuario la capacidad de editar el texto (con lo que podria ya no caber la información en el espacio asignado originalmente y tendrias que moverla al final del archivo, o llevar un registro de los espacios disponibles donde podria caber. Inclusive podrias dividir el texto en varias partes... pero es complicado.

Te sugiero también que penses en la posibilidad de dejarle el trabajo sucio a una base de datos. Inclusive paradox.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #9  
Antiguo 15-07-2003
nachoasensio nachoasensio is offline
Miembro
 
Registrado: may 2003
Ubicación: Málaga
Posts: 61
Poder: 22
nachoasensio Va por buen camino
Hola otra vez.

A ojo, creo que falta el else del if, para que cuando no encuentre más '|' guarde el último texto. Así, el if quedaría:

if Pos1 > 0 then
//Extraemos el texto del registro cont
Contenido[cont] := Copy(Texto, 1, Pos1-3)
// El -3 es para
// eliminar el salto de línea tras el texto
else
Contenido[cont] := Texto;

Un saludo

Nacho
Responder Con Cita
  #10  
Antiguo 15-07-2003
Ane Ane is offline
Registrado
 
Registrado: jul 2003
Posts: 5
Poder: 0
Ane Va por buen camino
Muchas gracias a todos por la ayuda.
Voy a seguir el consejo de Nacho a ver qué tal me va.
Hasta pronto.
- Ane -
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 09:41:31.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi