PDA

Ver la Versión Completa : file of, caracter de separación


jonmendi
07-06-2006, 09:08:10
hola a todos!
No se si es el lugar más adecuado, ya que ahora estoy programando en Pascal, pero supongo que muchos de vosotros habréis hecho pinitos (y más) con él.
Estoy haciendo un programilla que debe guardar unos registros de un tipo determinado (tipoNuevo) en un fichero en disco. Creo un file of tipoNuevo, y al grabar o leer los registros me los graba / lee bien. El problema surge cuando edito el archivo como texto. Entre campo y campo de cada registro veo que me ha insertado un carácter variable (puede ser cualquiera). El asunto es que necesito quitar este caracter, pues las ristras que le dejo yo las usa otro programa que no espera encontrar nada ahí.
He probado a escribir todo como un archivo de texto, pero el problema es que al permitir solo reset, rewrite, append no puedo acceder a la fila que yo quiero y modificarla.
¿Alguien me puede dar laguna pista?
Muuuuuuuuuuchísimas gracias.
Jon

Lepe
07-06-2006, 10:35:07
Como archivo de texto, si usas Rewrite te borrará el archivo, pero con Reset te puedes situar la principio, y despues con ReadLn puedes ir leyendo hasta situarte en la línea adecuada, para modificar, usas WriteLn.

Si usas un File of TRecord, no puedes modificar despues a mano el archivo, porque se crean las marcas de fin de registro, si lo modificas, despues al leer dará fallos.

Saludos

jonmendi
07-06-2006, 11:21:40
gracias Lepe,
es lo que he intentado, pero existe el siguiente problema. Si abro con reset el archivo es solo de lectura (ya que es de texto), por lo que aunque lea las líneas y me posiciones en la que yo quiero, a la hora de escribir tendré que hacer un rewrite, con lo que me borrará el archivo y me creará uno vacío.
¿Alguna ideas más?

Muchas gracias,
Jon

Lepe
07-06-2006, 14:52:55
Quizás fuera conveniente leer todo el archivo en memoria ¿es muy grande?

Si no lo es, 2000 o 3000 registros, puedes usar un TStringList y quitarte de todos esos problemas:


var Archivo:TStringList;
begin
Archivo := TStringList.Create;
Archivo.LoadFromFile('c:\mio.txt');
if Archivo.Count > 129 then // si tiene más de 129 líneas
Archivo[128] := 'Por la cara modifico el texto';
if Archivo.Count > 0 then
Archivo[0] := Archivo[0] + ' Añado texto a la primera fila';

if Archivo.Count > 3 then
Archivo.Insert(2,'inserto en la posición 3, recuerda empieza en cero');
Archivo.Add('añado al final este texto');
Archivo.Delete(0); // borro la primera linea
Archivo.SaveToFile('c:\mio.txt');
FreeAndNil(Archivo);
end;


saludos

jonmendi
07-06-2006, 15:47:41
muchas gracias lepe, pero (parezco el hombre de los peros) me temo que en turbo pascal no existe TStringList (o al menos yo no lo conozco). Lo único que se me ocurre es antes de escribir leer todo, añadir en el sitio adecuado la ristra que quiero y volver a escribir todo. Pero no me convence en absoluto.

Un saludo
Jon

luisgutierrezb
07-06-2006, 18:54:16
porque no pruebas a bajar el FreePascal? si mal no recuerdo ya tiene la clase de TStrings o TStringList,

otra opcion seria que hicieras el guardado de registros a mano, pero guardandolos como texto delimitado por comas, y donde cada registro es un renglon por ejemplo
"reg1campo1","reg1campo2","reg1Campo3","etc"
"reg2campo1","reg2campo2","etc","etc"

lo que si, es que es mas chamba, sin embargo, no dudo que haya por ahi una unidad ya hecha para leer y guardar datos en este formato...

jonmendi
08-06-2006, 09:09:16
gracis luisgutierrezb.
El free pascal ya lo tengo bajado, pero el problema es que el programilla que estoy haciendo yo lo tengo que importar a un proyecto bastante grande que está hecho en turbo pascal 7.0. Este proyecto he intentado pasarlo a free pascal, pero es más trabajo que matar una burra a pellizcos. por eso desistí.
Lo de los campos separados con comas tampoco me sirve, ya que tengo que dejar un fichero solo con los datos que yo le paso, pero sin comas ni nada. Si el registro es tRegistro = record
nombre : string[15];
apellido1 : string[30];
telefono : string[9];
end;
yo tengo que escribir en el fichero de texto
nnnnnnnnnnnnnnnaaaaaaaaaaaaaaaaaaaaaaaaaaattttttttt
y nada más que eso. Sin espacios ni comas ni nada de nada. El problema es que si tengo 2000 líneas de estas, y quiero modificar una, por distintos problemas de permisos y demás no puedo leer y escribir todo, por lo que no me srive un fichero de texto y usar readln writeln.
Muchas gracias a los que estáis mostrando tanto interés.
Un saludo
Jon

Lepe
08-06-2006, 11:14:21
Pues se acabó lo que se daba, esto tiene que funcionar en Turbo pascal, ya que usa las funcionies de bajo nivel del sistema operativo.

Edito: Las funciones las pillo de SysUtils, pero estarán en otra unidad de Turbo Pascal. THandle es un Entero largo.


procedure TForm1.btn1Click(Sender: TObject);
var F:THandle;
s: string[10];
i:Integer;
begin
if not sysutils.FileExists('c:\mio.txt') then
F:= sysutils.FileCreate('c:\mio.txt')
else
f:= sysutils.FileOpen('c:\mio.txt',fmOpenReadWrite);

if f>0 then
ShowMessage('archivo abierto');

s := 'texto 1';
FileWrite(F,s,SizeOf(s));
s := 'texto 2';
FileWrite(F,s,SizeOf(s));
s := 'texto 3';
FileWrite(F,s,SizeOf(s));
FileSeek(f,-(SizeOf(s)*2),1); // ir atrás en el fichero
{
Al movernos tenemos que ir sumando los bytes que hay escritos
realmente en el fichero. Multiplico por 2 para irme 2 "registros"
hacia atrás, el primero es el "Texto 3", y al retroceder otro más
me situo al principio de "texto 2", que se debe mostrar en el último
ShowMessage
}
FileRead(f,s,SizeOf(s));
ShowMessage(s);
FileClose(f);
end;

Espero que sea viable ;).

SAludos

jonmendi
08-06-2006, 12:28:33
muchas gracias lepe, pero.... me pasa solo a mi o en el archivo que crea escribe texto 18@ texto 28@ texto 38@ a todo el mundo?
Precisamente son los "cuadraditos", las arrobas y demás signos los que quiero evitar.
No sé, estoy liado.
Un saludo y muchas grcias
Jon

rafita
08-06-2006, 13:54:57
Hola Jonmendi,
No sé si me he perdido un poco con el tema, pero creo que lo estais complicando demasiado.

Lo que tu necesitas es un fichero de texto, no de un tipo concreto, de esa forma te pondrá los datos que necesitas uno tras otro, sin separadores de campo. Únicamente tendrá el caracter de fin de registro, lo cual no te dará ningún tipo de problema con la otra aplicación que debe leer ese fichero.

Con lo que sí tienes que tener cuidado es con completar el tamaño de los campos, ya que al no ir separados por nada tienen que tener su longitud exacta. Me explico con un ejemplo hecho de cabeza:
var MiNombre, MiApellido, MiTelefono, LoQueGrabo, Espacios : String;
FDisco : Text;
begin
// Inicializa la variable Espacios con 50 de caracteres en blanco
Espacios:=StringOfChar(' ', 50);
// en Pascal estándar sería algo así:
// Espacios:='';
// for i:=1 to 50 do Espacios:=Espacios+' ';

// asignar el fichero de texto y crearlo nuevo
AssignFile(FDisco,'TuFichero.txt'); // no olvides ponerle la ruta
{$I-} Rewrite(FDisco); {$I+} // lo abro borrando todo lo que tiene
if IOResult<>0 then // esto controlaba si había algún error
begin
ShowMessage('No encuentro el fichero');
Exit;
end;
// haz el bucle para ir encontrando los datos, y dentro de él grabas el fichero de texto
// MiNombre:=......
// MiApellido:=......
// MiTelefono:=.....

// completo la línea de texto a grabar uniendo los campos
LoQueGrabo:=MiNombre+Copy(Espacios,1,15-Length(MiNombre))
+MiApellido+Copy(Espacios,1,30-Length(MiApellido))
+MiTelefono+Copy(Espacios,1,9-Length(MiTelefono));
Writeln(FDisco,LoQueGrabo);
// fin del bucle

// cierra el fichero generado
CloseFile(FDisco);


Ahora mismo no recuerdo los sentencias exactas que se utilizan en pascal estándar para trabajar con ficheros de texto, pero me suena que son exactamente las mismas que estas utilizando para los ficheros con tipo, es decir: reset y rewrite para abrirlos, readln y writeln para leer o escribir una línea,... si necesitas información más exacta te busco un ejemplo hecho con Turbo Pascal.

Saludos

jonmendi
08-06-2006, 15:12:01
muchas gracias rafita!
si yo tb opino que me estoy liando, pero.... que no encuentro solución!
El código que me envías lo tengo probado, pero hay un problemilla: cuando abres un fichero de texto con reset(F), no puedes escribir en el mismo, solo leer. Si lo abro con rewrite(F) me borra todo lo que haya, cosa que tampoco me interesa (por distintos motivos de permisos etc etc...), y el append no me sirve porque yo quiero modificar una línea en concreto. Por eso creo que no puedo usar un archivo de texto. En basic se que había un put y get que hacian lo que yo quiero, pero en turbo pascal .... pues que no me sale!

Muchas gracias a todos. Y ya es jueves, así que animo.
Jon

rafita
09-06-2006, 10:12:11
Hola Jon,

Vayamos por partes.

No recuerdo exactamente las características de los ficheros de texto en pascal, pero creo que tienes toda la razón: no permite modificar, tan solo abrir para leer y para escribir (borrando lo que tuviese). Sin embargo en los ficheros "con tipo" sí permitía acceder directamente a un registro y modificarlo.

Al leer tu primer mensaje de este hilo entendí que tú generabas el fichero, y que el problema era que fuese compatible con otra aplicación. Luego bastaba con generarlo correctamente (para no tener que modificar después ninguna lína), por eso te comente lo de los ficheros de texto.

Si en tu aplicación vas a tener que acceder a un registro concreto y modificarlo, se me ocurren varias posibilidades:

1ª) trabaja con un fichero "con tipo" (si puedes, mejor con una base de datos), y cuando necesites el fichero para comunicarte con la otra aplicación, lo generas como tipo texto.

2ª) prueba a trabajar con un fichero "con tipo", pero agrupando todos los campos en uno sólo (respetando las longitudes para poder codificarlo y decodificarlo), quizá así la otra aplicación no rechace el caracter de fin de campo.

3ª) si la modificación en un registro/línea va a ser algo puntual, puedes generarte el fichero de tipo texto y modificarlo "a mano" con cualquier editor de texto.

4ª) (trabajando con Delphi) si la modificación de los registros va a ser habitual, podrías generar el fichero de texto y utilizar (mediante Delphi) las posibilidades de reemplazar texto que te dan algunos procesadores de texto como Word (mira el apartado Server de este foro).

5ª) finalmente, puedes trabajar a lo bestia. Es decir, tienes tu fichero de texto (abierto con reset) que vas pasando a otro de trabajo (abierto con rewrite), cuando llegues a la línea a modificar, la cambias, y continuas procesando el fichero hasta llegar a final. Después les cambias los nombres o vuelves a pasar el contenido del fichero de trabajo al original. Esto es trabajar a lo bestia pero lo hace la máquina, y con los procesadores de hoy en día... tampoco será tanto tiempo.

Saludos Jon (y ánimo que ya es viernes)

jonmendi
09-06-2006, 17:27:19
muchas gracias rafita!
me parece que al final la solución me paece que va a ser algo parecido a la opción 5.
Muchas gracias a todos los que habéis demostrado interés.

Un slaudo, y no os derritais.
Jon