2011-04-03 18 views
12

Deseo abrir un archivo usando el modo "a + b", es decir, si no existe, se crea automáticamente, pero si lo hace, no quiero sobrescribirlo. Quiero poder leer y escribir en el archivo.¿Hace fseek() mover el puntero del archivo al principio del archivo si se abrió en el modo "a + b"?

El archivo es binario y quiero guardar registros de un struct específico en él. Entonces quiero hacer fseek() en el registro que quiero y luego guardar el registro usando fwrite().

El código es el siguiente (MyRecord es una typedef a un struct, mientras FILENAME es una #define al nombre del archivo):

int saveRecord(MyRecord *pRecord, int pos) 
{ 
    FILE* file = fopen(FILENAME, "a+b"); 
    if (file == NULL) 
    { 
     printf("Unable to open file %s\n", FILENAME); 
     return 0; 
    } 

    fseek(file, pos * sizeof(MyRecord), SEEK_SET); 
    fwrite(pRecord, sizeof(MyRecord), 1, file); 
    fclose(file); 
    return 1; 
} 

Sin embargo, este código sólo añade el registro al final del archivo, incluso si configuré pos en 0. ¿Por qué no está fseek() con SEEK_SET trabajando en modo de adición?

Sé que puedo simplemente abrirlo con "r + b" y si falla abrirlo con "wb", pero quiero saber por qué esto no funciona y por qué fseek() con SEEK_SET deja el puntero del archivo en el fin. Se apreciaron todas las referencias a lugares donde se documentó este comportamiento (porque no pude encontrar ninguno, o estoy usando las palabras clave incorrectas).

Respuesta

18

Eso es porque en el modo a, escribir al FILE* siempre se agrega al final. fseek solo establece el puntero de lectura en este modo. Esto está documentado en el estándar de C, 7.19.5.3 fopen:

apertura de un archivo con el modo de adición ('a' como el primer carácter del argumento modo) hace que todas las escrituras posteriores en el archivo a ser obligados a el fin de archivo actual, independientemente de las llamadas intermedias a la función fseek.

+0

Gracias, la respuesta que necesitaba. – jbx

4

Utilice el modo "r + b" y la alternativa a "w + b" si falla.

El modo "a + b", le permite leer y anexar; el "r + b" permite lectura y escritura aleatorias.

La documentación para fopen describe cómo se comporta el archivo con los diferentes modos.

+0

Esto tiene una condición de carrera que va a darle una paliza a su archivo. –

+0

@R .. ¿Qué condición de carrera? debería decir "de nuevo a" wb "si falla con' errno == ENOENT' " – pmg

+0

Supongo que hay un sistema operativo multitarea donde otro proceso podría crear el archivo y llenarlo con datos después de que falle el primer' fopen' pero antes de que el segundo intento 'fopen'. Si OP está tratando con un sistema integrado o cualquier sistema cerrado donde se sabe que esto no sucederá, puede no ser un problema. –

4

Plain C no tiene una manera sensata de lograr lo que desea. Si está en un sistema POSIX o algo remotamente cercano, puede usar fd=open(FILENAME, O_CREAT|O_RDRW, 0666) y luego fdopen(fd, "rb+").

Editar: Otra cosa que podría intentar, con la llanura C:

f = fopen(FILENAME, "a+b"); 
if (!f) /* ... */ 
tmp = freopen(0, "r+b", f); 
if (tmp) f = tmp; 
else /* ... */ 
+0

Sí, supongo que eso funcionaría. Necesito esto para trabajar en puro ANSI C sin embargo. Todavía +1 para ti por la buena alternativa. – jbx

+0

¿Has probado la solución 'freopen'? No tengo idea si funciona en la práctica ('freopen' está mal especificado y en teoría podría ser inútil) pero podría estar bien. –

Cuestiones relacionadas