Tengo un problema acerca del archivo de modo de abrir con fopen().

En mi caso, quiero buscar el cursor libremente, puede ser incluso más allá de EOF a veces. Lo que es más, también quiero anexar en lugar de truncar el archivo existente. Traté de abrir el archivo en a+ modo; sin embargo, no puedo buscar el archivo de cursor libremente. Cada vez que busco el cursor más allá de EOF, de la nueva llegada de datos se agregará al final del archivo, no la posición en la que se especifica. Mientras que, si está abierto en w+ modo, el archivo existente se trunca. Hay una solución perfecta para este problema?


ACTUALIZACIÓN:

Un punto no se especifica claramente es que el archivo no puede existir siempre; tengo que crear un nuevo archivo en ese caso.

De hecho, quiero proceso de un archivo de configuración. No sé si es una buena práctica aplicar como este. O debo primer lugar vacío de un archivo de configuración. Así que no hay necesidad de preocuparse por el archivo del caso no existe?

A continuación es el fragmento de código:

FILE *f = fopen(FILE_PATH, "wb+");
struct record r;
if (f) {
    if (fread((void *)&r, 1, sizeof(struct record), f) {
        /* File exists, do the normal flow */
    } else {
        if (feof(f)) {
            /* File is newly created, do some initialization */
        }
    }
} else {
    /* issue a warning */
}
  • Puedes publicar el código relevante aquí?
  • Tengo curiosidad.. ¿por qué usted está buscando para buscar/escritura más allá de EF?
  • Yo uso un archivo para emular el disco duro. Los datos se leen y escriben en trozos. Por lo que inicialmente el archivo está vacío, los datos pueden caer detrás de EOF

3 Comentarios

  1. 6

    Usted tendrá que lidiar con el posiblemente archivo que no existe en dos etapas, en primer lugar, asumiendo que está allí y, a continuación, tratar con su ausencia:

    if ((f = fopen(filename, "rb+") == 0)
        f = fopen(filename, "wb+");
    if (f == 0)
        ...report error...

    La "rb+" modo no se puede abrir un archivo que no existe (pero por lo demás se comporta como quieras). Si el archivo no existe, entonces "wb+" hace lo que usted desea en su lugar (a pesar de que todavía podía fallar, por ejemplo, si el archivo existe pero no tiene permiso para escribir en él). Usted tiene la esperanza de que no ha sido sometido a un TOCTOU (Momento de la llegada, Tiempo de Uso) ataque con el doble intento.

    Un enfoque alternativo utiliza el 3-argumento la versión de la open() sistema de llamada con las banderas apropiadas para abrir un descriptor de archivo y, a continuación, utiliza fdopen() para crear un archivo de secuencia del archivo descriptor:

    #include <fcntl.h>
    
    int fd;
    if ((fd = open(filename, O_RDRW | O_CREAT, 0644)) >= 0)
        f = fdopen(fd, "rb+");

    Bastante preciso de control sobre open() con las banderas.

    • Normalmente, usted puede pasar 0666 como los bits de permiso y confianza al usuario establecer el umask. Esto también significa que el usuario puede establecer el umask, en lugar de tener que chmod los archivos manualmente después.
    • El fdopen enfoque es el único seguro.
    • Eso es válida la observación – si usted la confianza de tus usuarios, para saber lo que es una umask es. Yo trabajo en seguridad; que no me fío de mis usuarios. No tenemos un contexto más amplio. Tomo nota de que si existe el archivo, los permisos será invariable, por lo que si el usuario quiere que cualquiera pueda editar su configuración, se puede establecer que el público y los permisos de escritura de grupo. Yo no se cuanto permite que otras personas (otras personas) para modificar la configuración de mi como seguro, por lo tanto la deliberada (pero sin comentar a) el uso de 0644 en lugar de 0666.
    • Que (open() más fdopen()), que sería el mecanismo que yo uso, pero el archivo de los descriptores de fair play en los contextos donde yo trabajo. Si el estándar es el uso de secuencias de archivo solo, luego el doble intento es la aproximación más cercana a la correcta, TOCTOU problemas y de todos.
    • He aquí una variante más seguro: el uso de fopen con "ab+" para crear el archivo en el caso de que no exista, a continuación, cierre y vuelva a intentarlo desde el principio.
    • Cómo es que seguro que "rb+" y "wb+" si se produce un error?
    • El uso de 0666 va a coincidir con el comportamiento de fopen, que utiliza 0666 (al menos glibc hace). Si su umask es incorrecto, tiene problemas más grandes de todos modos.
    • En el caso de que "rb+" error de que el archivo fue creado por otra persona, inmediatamente después, la posterior "wb+" se trunca el archivo. El uso de "ab+" el lugar para crear el archivo de evitar el truncamiento, y en la siguiente ronda, el "rb+" obtendrá el ahora-archivo existente.

  2. 2

    El archivo modos están claramente documentados para fopen (prueba man 3 fopen en Unix/Linux/mac OS X).

    r+ Abierto para la lectura y la escritura. La secuencia se coloca al principio del archivo.

    • El "rb+" o "r+" modo de falla cuando el archivo no existe; en ese caso, usted tiene que volver y probar otra vez con "wb+" o "w+", con la esperanza de que no ha sido sometido a un TOCTOU (Momento de la llegada, Tiempo de Uso) de ataque.
    • Si desea modificar, si existe; de lo contrario, crear vacío» semántica en POSIX, fopen no es útil. Usted necesitará open seguido por fdopen.
  3. -1

    Hola, puede utilizar «w+» a leer y a escribir por el fseek, escribí una pequeña demostración del programa, escribir datos a un archivo y usar el fseek para hacer de cada uno de los intervalos de datos algunas de bytes, y a continuación, lea:

    #include <stdio.h>
    #include <unistd.h>
    
    #define FILE_PATH "seek_test.txt"
    #define STEP_SIZE 64
    
    void set_data(FILE* fp)
    {
        int i = 0;
        fseek(fp, 0, SEEK_SET);
    
        for ( ; i < 20; ++i)
        {
            fprintf(fp, "%d", i);
            fseek(fp, STEP_SIZE, SEEK_CUR);
        }
    }
    
    void get_data(FILE* fp)
    {
        int i = 0;
        fseek(fp, 0, SEEK_SET);
    
        for ( ; i < 20; ++i)
        {
            fscanf(fp, "%d", &i);
            fprintf(stderr, "Cur Step: %5ld, value = %4d\n", i * STEP_SIZE, i);
            fseek(fp, STEP_SIZE, SEEK_CUR);
        }
    }
    
    int main(int argc, char* argv[])
    {
        FILE* fp = fopen(FILE_PATH, "w+");
        if (fp == NULL)
        {
            printf("fopen Error\n");
            exit(0);
        }
    
        set_data(fp);
        get_data(fp);
    
        return 0;
    }

    ===============================
    resultado de la siguiente manera:

    Cur Paso: 0, valor = 0

    Cur Paso: 64, valor = 1

    Cur Paso: 128, valor = 2

    Cur Paso: 192, valor = 3

    Cur Paso: 256, valor = 4

    Cur Paso: 320, valor = 5

    Cur Paso: 384, valor = 6

    Cur Paso: 448, valor = 7

    Cur Paso: 512, valor = 8

    Cur Paso: 576, valor = 9

    Cur Paso: 640, valor = 10

    Cur Paso: 704, valor = 11

    Cur Paso: 768, valor = 12

    Cur Paso: 832, valor = 13

    Cur Paso: 896, valor = 14

    Cur Paso: 960, valor = 15

    Cur Paso: 1024, valor = 16

    Cur Paso: 1088, valor = 17

    Cur Paso: 1152, valor = 18

    Cur Paso: 1216, valor = 19

    =============================

    • Gracias, todavía no puede satisfacer todas las necesidades. Finalmente me tome Jonathan respuesta.
    • Esto se trunca el archivo.

Dejar respuesta

Please enter your comment!
Please enter your name here