2011-12-09 12 views
6

Hay muchas preguntas similares, pero nada que responda a esto específicamente después de buscar en Google bastante. Aquí va:¿Cuál es la mejor manera de truncar el comienzo de un archivo en C?

Digamos que tenemos un archivo (podría ser binarios, y mucho más grande también):

abcdefghijklmnopqrztuvwxyz

¿cuál es la mejor manera en C para "mover" un derecho más parte de este archivo a la izquierda, truncando el principio del archivo .. así, por ejemplo, "frente truncar" 7 bytes cambiaría el archivo en el disco sea:

hijklmnopqrztuvwxyz

Debo evitar los archivos temporales, y preferiría no utilizar un gran buffer para leer todo el archivo en la memoria. Un posible método que pensé es usar fopen con el indicador "rb +", y buscar y escribir constantemente para copiar bytes comenzando desde el desplazamiento al principio, luego establecer Endofarch para truncar al final. Eso parece ser una gran búsqueda (posiblemente ineficiente).

Otra forma sería abrir el mismo archivo dos veces, y usar fgetc y fputc con los punteros de archivo respectivos. ¿Esto es posible?

Si hay otras formas, me gustaría leerlas todas.

+0

Terminé abriendo el archivo dos veces (con dos punteros FILE). Esto fue muy rápido (~ 2 mb en un abrir y cerrar de ojos; no fue un punto de referencia). Usé ftruncate() con fileno() y ftell(). – snapfractalpop

Respuesta

3

No tiene que usar un tamaño de búfer enorme, y el kernel va a hacer el trabajo duro por usted, pero sí, leer un búfer completo desde el archivo y escribir más cerca del comienzo es el camino a hágalo si no puede permitirse hacer el trabajo más simple de crear un archivo nuevo, copiar lo que desea en ese archivo y luego copiar el archivo nuevo (temporal) sobre el anterior. No descartaría la posibilidad de que el método de copiar lo que desea a un archivo nuevo y luego mover el nuevo archivo en lugar de lo viejo o copiar lo nuevo a lo viejo sea más rápido que el proceso de mezcla que usted describe. Si el número de bytes que se eliminarán es un tamaño de bloque de disco, en lugar de 7 bytes, la situación podría ser diferente, pero probablemente no. La única desventaja es que el enfoque de copia requiere más espacio en el disco intermedio.

Su enfoque de esquema requerirá el uso de truncate() o ftruncate() para acortar el archivo a la longitud adecuada, suponiendo que se encuentre en un sistema POSIX. Si no tiene truncate(), tendrá que hacer la copia.

Tenga en cuenta que al abrir el archivo dos veces funcionará bien si se tiene cuidado de no darle una paliza el archivo al abrir para escritura - "r+b" usando el modo con fopen(), o evitar O_TRUNC con open().

+0

¡gracias por una excelente respuesta! el tamaño de los bloques para moverse puede ser sustancial (del orden de megabytes). Mi preocupación sobre cómo evitar los archivos temporales no es con espacio, sino con la persistencia de datos confidenciales. Quiero limitar el almacenamiento físico de bytes a un lugar en el disco (aunque la copia se elimine, los bytes aún pueden estar presentes). Por cierto, estoy en Linux.¿Hará el kernel el trabajo duro si estoy buscando cada byte, o qué sería un buffer óptimo si no fuera así? Me pregunto si la última opción daría como resultado lo mismo físicamente. – snapfractalpop

+0

Si realiza operaciones de lectura y escritura de un solo byte, hará algo (las E/S estándar o el kernel, o tal vez ambos) harán un gran trabajo. Trabajar en trozos de tamaño kilobyte (digamos 1, 2, 4, 8, 16, 32 trozos de KiB) sería más eficiente, sin estresar a todos los entornos menos empobrecidos. El núcleo se ocupará de alineaciones, etc. para usted, afortunadamente. –

+0

bien. ¡gracias de nuevo! – snapfractalpop

4

Puede mmap guardar el archivo en la memoria y luego memmove los contenidos. Tendría que truncar el archivo por separado.

+0

Entonces, ¿los pasos serían: 1) mmap 2) memmove 3) un-mmap (¿existe?) 4) truncar ? – snapfractalpop

+1

@snapfractalpop [ejemplo relacionado aquí] (http://pastebin.com/s1vSCvxA). Esta solución tiene potencial para ser realmente rápida, pero el tamaño del archivo está limitado por el tamaño del espacio de direcciones. No podrá truncar archivos grandes (> 4 GB) en sistemas de 32 bits. –

+2

@Banthar: es peor que eso: necesita una parte contigua del espacio de direcciones de su proceso lo suficientemente grande. Eso podría ser mucho menos de 4 GB, dependiendo de la fragmentación y otras asignaciones de memoria. – Joe

Cuestiones relacionadas