Control de usuario
Patrocinadores
Estadísticas
Miembros:
334.544
Online:
1.429
Hilos:
1.380.494
Mensajes:
24.874.551
Stats

Índice de foros Otras Consolas Desarrollo

[C] Modificar fichero

Dedicado al desarrollo de software casero para videoconsolas

Moderador: jiXo

nazareth
Avatar de usuario
I'm Finishing
 
Mensajes: 2466
Registrado: 03 Ene 2008
Ubicación: Cartagena

[C] Modificar fichero

Mensajepor nazareth 26 Oct 2011 23:02

Vereis, según creo, si tienes un fichero y quieres modificarlo, tienes que leerlo completo cambiar lo que quieras dentro del array y volver a escribirlo entero.

¿Hay forma de ir a un punto del archivo (fseek) leer lo que se quiera (fread) cambiar el dato y volver a escribir en el fichero (???) sin tener que leer todo el fichero y escribir todo el fichero? Sería algo tipo sql pero con un archivo normal, no se bien como funciona el sql pero sería hacer algo tipo.

Busca: tornillo

Archivo:
alicates= 2;
llaves= 5;
tornillo= 28;

Sería... quizas este mal dicho, pasearse y buscar por el fichero como si se tratase de un array.

No se si se entiende o no ^^''

Saludos!

trueskins
Avatar de usuario
MegaAdicto!!!
 
Mensajes: 1054
Registrado: 05 Oct 2007

Mensajepor trueskins 01 Nov 2011 00:23

Si no me equivoco al utilizar fseek puedes alternar entre lectura y escriptura siempre y cuando el archivo lo hayas abierto en modo que permita esto. El truco es usar fseek pero sin desplazarte entonces podrás alternar el modo de lectura y escriptura sin abrir y cerrar el archivo

fseek ( pFile , 0 , SEEK_CUR );

No sé si es más o menos esto a lo que haces referencia.
ImagenImagen

nuvalo
Avatar de usuario
MegaAdicto!!!
 
Mensajes: 1493
Registrado: 14 Mar 2007

Mensajepor nuvalo 01 Nov 2011 14:41

Depende del tamaño de los datos que quieras modificar te servirá o no fseek. Me refiero, si es un archivo binario y quieres modificar valores enteros ("tipo int") no tendrás problemas ya que los datos ocuparán siempre 32 bits (depende de la arquitectura también, pero supongamos que no es un problema).

Si usas ficheros de texto, eso no es tan directo, dado que "128" ocupa 3 bytes, mientras que "28" ocupa solo 2 (un byte por carácter). Tendrás que "estandarizar" los datos, para que sepas que "llaves" tiene suficiente hueco para almacenar el nuevo valor, y no pisar a "tornillo". Lo más fácil es llevar registros de un tamaño fijo, es decir, que los nombres del registro siempre sean de 10 letras rellenando lo que sobre con espacios, y que el número sea siempre de 20 letras, rellenando también con espacios.

Así los accesos te serán mucho más fáciles, si quieres escribir la linea 10, solo tienes que hacer un fseek desde el inicio de 30(bytes por linea)*9 (linea en la que quieres empezar a escribir) +10 (nombre del registro 10). Lo mismo para la lectura. Me he comido los separadores tipo ":" y "\n", pero para el caso supongo que no te importará si no van a ser leidos.

Si vas a usar ficheros binarios, es el mismo caso, asegúrate de cuantos bytes reservas para el texto y el valor (puedes usar sizeof para saber el tamaño en bytes de cada campo) y así echas cuentas de donde te quieres posicionar en nº de bytes. Otra opción más elegante sería usar structs de tamaño fijo donde usas el sizeof del struct para echar cuentas y moverte por el fichero, leer almacenando directamente en el struct, volver a posicionarte en el fichero, y escribirlo. ASí usas siempre datos en binario, ahorrándote llamadas de "atoi" y viceversa cuando queires pasar un dato de un tipo a otro.
Código: Seleccionar todo
"Dios no juega a los dados, usa /dev/random"

Empty your mind, be formless, shapeless — like void*.If you put an  int into a void*, it           (__)
becomes the int. You put float into a void* it becomes the float. You put in a char it             (oo)
becomes the char. Now, void* can flow or it can overflow                                     /------\/
                                                                                            / |    ||
Be void* my friend.                                                                        *  /\---/\
                                                                                              ~~   ~~
(Ahora, con poderes de super vaca)


Chiste del día: ctrl+c, crtl+v http://imgur.com/CCeQf.jpg

nazareth
Avatar de usuario
I'm Finishing
 
Mensajes: 2466
Registrado: 03 Ene 2008
Ubicación: Cartagena

Mensajepor nazareth 01 Nov 2011 21:18

Si, básicamente lo que quiero es por ejemplo:

Código: Seleccionar todo
[utensilios]
//nombre, cantidad, precio
tornillo:23:29,5


Código: Seleccionar todo
[utensilios]
//nombre, cantidad, precio
tornillo:22:29,5


Poder cambiar el 23 por el 22 sin tener que copiar todo el archivo, cambiarlo, y volverlo a escribir, la cosa seria copiar la linea en la que esta no? Vuelvo a ponerlo asi porque no entiendo bien como darle ese uso a fseek.

nuvalo
Avatar de usuario
MegaAdicto!!!
 
Mensajes: 1493
Registrado: 14 Mar 2007

Mensajepor nuvalo 02 Nov 2011 15:46

¿Vas a trabajar con ficheros de texto o binarios?. Lo que tienes que entender es que cuando escribes, no es como en el word, no "añades". Sobreescribes lo que haya en esa posición, es como escribir con el botón "insert" activo. Ej:

Código: Seleccionar todo
[utensilios]
//nombre, cantidad, precio
tornillo:22:29,5


Ese fichero así tal cual, ocupa 56Bytes (un byte por caracter, contando los \n sin retorno de carro). El número "22" está en el byte 49 del fichero, por lo tanto puedes hacer un

fseek (fichero , 49 , SEEK_SET );
fputs ( "23" , fichero );

Y el resultado será:

Código: Seleccionar todo
[utensilios]
//nombre, cantidad, precio
tornillo:23:29,5


El problema viene cuando quieras cambiar el 23 por un 1300 (por ejemplo). Al hacer lo mismo lo que ocurrirá será:

fseek (fichero , 49 , SEEK_SET );
fputs ( "1300" , fichero );


Código: Seleccionar todo
[utensilios]
//nombre, cantidad, precio
tornillo:13009,5


Eso te sobreescribe los datos que ya tenías, solo podrás almacenar números del 00 al 99. Una solución es que todos los campos (nombre, cantidad y precio) tengan un tamaño prefijado, de "10 espacios" (10 bytes) cada uno por ejemplo. Así, cuando quieras editarlo, te asegurarás de que no haya problemas porque tendrás espacio. Ej:

Código: Seleccionar todo
[utensilios]\n
//nombre, cantidad, precio\n
tornillo  :23        :29,5          \n
tuerca    :100       :29,5          \n

He marcado los saltos de linea para que se vea que en el precio tienes 10 espacios.Ahora puedes hacer

fseek (fichero , 51 , SEEK_SET );
fputs ( "1300" , fichero );

Sin ningún peligro. Además, te será útil tener los tamaños prefijados para moverte dentro del fichero con fseek.
Un saludo, y suerte
Código: Seleccionar todo
"Dios no juega a los dados, usa /dev/random"

Empty your mind, be formless, shapeless — like void*.If you put an  int into a void*, it           (__)
becomes the int. You put float into a void* it becomes the float. You put in a char it             (oo)
becomes the char. Now, void* can flow or it can overflow                                     /------\/
                                                                                            / |    ||
Be void* my friend.                                                                        *  /\---/\
                                                                                              ~~   ~~
(Ahora, con poderes de super vaca)


Chiste del día: ctrl+c, crtl+v http://imgur.com/CCeQf.jpg

nazareth
Avatar de usuario
I'm Finishing
 
Mensajes: 2466
Registrado: 03 Ene 2008
Ubicación: Cartagena

Mensajepor nazareth 02 Nov 2011 18:05

Comprendo lo que dices, he trabajado con editores hexadecimales y si, mejor tener un tamaño prefijado.

Una pregunta, posiblemente tonta, ¿cómo hago un salto de línea en un fichero? ¿hago un fputs("\n",fichero)?

nuvalo
Avatar de usuario
MegaAdicto!!!
 
Mensajes: 1493
Registrado: 14 Mar 2007

Mensajepor nuvalo 03 Nov 2011 00:52

Sí, con eso bastaría para añadir una línea. El problema es que algunos editores (notepad solia usarlo) de texto usan "\r\n", que significa "retorno de carro + salto de linea". Asegurate de como se escriben los saltos de línea en el editor que uses, para seguir el mismo estandar. Aui tienes una explicacion un poco más extensa:

http://www.codeguru.com/forum/showthread.php?t=253826

Como ves, los estándares se los suelen pasar por el forro :), dependiendo de si estás en linux, windows o mac.
Código: Seleccionar todo
"Dios no juega a los dados, usa /dev/random"

Empty your mind, be formless, shapeless — like void*.If you put an  int into a void*, it           (__)
becomes the int. You put float into a void* it becomes the float. You put in a char it             (oo)
becomes the char. Now, void* can flow or it can overflow                                     /------\/
                                                                                            / |    ||
Be void* my friend.                                                                        *  /\---/\
                                                                                              ~~   ~~
(Ahora, con poderes de super vaca)


Chiste del día: ctrl+c, crtl+v http://imgur.com/CCeQf.jpg


Volver a Desarrollo

¿Quién está conectado?

Usuarios navegando por este foro: No hay usuarios registrados visitando el foro y 0 invitados