FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
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. |
#2
|
|||
|
|||
Hola Ane:
A ver si esto te funciona: Prueba a poner el valor True (verdadero) en la propiedad WordWrap del componente TMemo. Suerte. |
#3
|
|||
|
|||
Gracias por contestar a mi problema, pero la propiedad WordWrap del TMemo ya estaba a True.
¿alguna pista de qué puede estar mal? Gracias. |
#4
|
|||
|
|||
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 |
#5
|
|||
|
|||
Cita:
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. |
#6
|
|||
|
|||
Cita:
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; 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. |
#7
|
|||
|
|||
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 |
#8
|
||||
|
||||
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 |
#9
|
|||
|
|||
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 |
#10
|
|||
|
|||
Muchas gracias a todos por la ayuda.
Voy a seguir el consejo de Nacho a ver qué tal me va. Hasta pronto. - Ane - |
|
|
|