2012-01-16 7 views
5

Necesito acceder a un archivo de más de 2 gb utilizando C. Durante una ejecución del programa, se leerá un número variable de bytes del archivo y se guardará la ubicación de la siguiente posición. Durante la siguiente ejecución del programa, se lee la posición del archivo y se leen una cantidad de bytes a partir de esa ubicación.Acceso a archivos grandes En C

La complicación es que ocasionalmente el archivo puede 'comprimirse' copiándolo en un nuevo archivo, menos cualquier byte que ya haya sido leído (creo que copiar es la única manera de hacerlo). El número de bytes eliminados de esta manera también se guardará.

Necesito conocer la posición actual del archivo desde el inicio original para sincronizar con otro archivo. Esto debería ser fácil porque es justo (current_offset + deleted_bytes).

La razón por la que no es fácil es que fseek solo usa índices int largos que limitan el archivo a 2gb y fsetpos utiliza una estructura fpos_t para el índice de posición, que no es un número y no puede convertirse de atrás hacia adelante a uno. No conozco ninguna forma de usar un índice int largo largo para el posicionamiento de archivos, que sería la solución ideal.

¿Qué debo hacer?

+2

¿Qué plataforma? 'ftello()' y 'fseeko()' podrían ser una opción. –

+0

ftello y fseeko cumplirán con POSIX.1, pero el> 2GB también es un problema dependiente del sistema de archivos. –

Respuesta

6

En Windows puede usar _lseeki64() para hacer búsquedas de 64 bits.

Para la compatibilidad con Linux, también se puede añadir -D_FILE_OFFSET_BITS=64 en tiempo de compilación, y luego hacer esto en una de sus cabeceras:

#ifdef __MINGW32__ // or whatever you use to find out you're compiling on windows 
#define lseek _lseeki64 
#endif 

a continuación, utilizar lseek() todas partes, como de costumbre. Esto funciona porque Windows ignora el indicador _FILE_OFFSET_BITS y Linux no verá la redefinición de lseek.

También hay _fseeki64() si prefiere una versión FILE*, y no son equivalentes de 64 bits y tell()ftell() funciones también (_telli64() y _ftelli64()).

+0

Creo que eso es lo que necesito. ¡Gracias! – user1151125

+0

De nada. Otra nota sobre cómo hacerlo portátil: no puedo recordar si Windows declara 'off_t', por lo que también podría necesitar' #define off_t __int64' en Windows (para que pueda escribir código en [la interfaz 'lseek()'] (http : //www.kernel.org/doc/man-pages/online/pages/man2/lseek.2.html)). Pero no estoy 100% seguro, tal vez 'off_t' se defina en algún lugar ahora. –

+0

@TimothyJones ¿Cómo se configura _file_offset_bits en Windows? Estoy compilando desde Visual Studio 2008 en una máquina con Windows 7 de 32 bits. Intenté seguir este ejemplo http://coding.derkeiler.com/Archive/C_CPP/comp.lang.c/2006-12/msg03560.html pero obtengo el siguiente error c2371: 'off_t': redefinición; diferentes tipos básicos – savi

1

agregar la opción de compilación -D_FILE_OFFSET_BITS=64, lo que hace fopen, fseek, etc. off_t convertido en 64 bits y utilizable para la manipulación de archivos de más de 2 GB de tamaño. Consulte Large File Support in Linux para obtener más información.

+0

Excelente solución. Desafortunadamente, debería haber mencionado que estoy usando Windows y Visual Studio. – user1151125

+0

Supongo que no pensé en una solución específica para el compilador. Busqué en la documentación de Visual Studio y encontré SetFilePointer que usa índices de 64 bits en Windows. Sin embargo, esperaba hacer que mi código fuera más portátil que eso. Tal vez deba aprender a usar #ifdef para detectar en qué plataforma está y tener una lista completa de directivas de compilación o algo así. – user1151125

+0

Dejaré la respuesta en caso de que sea útil para usuarios de Linux/OS X. Un Makefile le permitirá determinar las opciones de compilación por plataforma. –