2009-01-18 27 views
15

Necesito crear archivos grandes relativamente grandes (1-8 GB). ¿Cuál es la forma más rápida de hacerlo en Windows usando C o C++? Necesito crearlos sobre la marcha y la velocidad es realmente un problema. El archivo se usará para la emulación de almacenamiento, es decir, tendrá acceso aleatorio en diferentes compensaciones y necesito que todo el almacenamiento sea preasignado pero no inicializado, actualmente estamos escribiendo todo el almacenamiento con datos ficticios y está tardando demasiado.Creación de archivos grandes en Windows

Gracias.

Respuesta

26

Utilice la API de Win32, CreateFile, SetFilePointerEx, SetEndOfFile y CloseHandle. En ese mismo orden.

El truco está en la función SetFilePointerEx. De MSDN:

en cuenta que no es un error para ajustar el puntero del archivo en una posición más allá de el final del archivo. El tamaño del archivo no aumenta hasta que llame a la función SetEndOfFile, WriteFile o WriteFileEx.

El explorador de Windows hace lo mismo al copiar un archivo de una ubicación a otra. Hace esto para que el disco no necesite reasignar el archivo para un disco fragmentado.

+0

Probado, funciona como se esperaba gracias Brian. – Ilya

+0

Esto funcionará rápido solo en NTFS y exFAT, no en FAT32, FAT16 .. Esto se debe a que este sistema de archivos tiene un "tamaño inicializado" –

+0

'SetEndOfFile()' puede provocar retrasos graves al escribir en el archivo. Si escribe en el medio del archivo, Windows pondrá a cero todos los bloques que aún no se han escrito, hasta la ubicación de la escritura. Consulte http://blogs.msdn.com/b/oldnewthing/archive/2011/09/22/10215053.aspx (Y personalmente puedo confirmar esto. He sido testigo del efecto al escribir una aplicación de evaluación comparativa IO). –

2

Echa un vistazo memory mapped files.

Se corresponden mucho con el caso de uso que describa, alto rendimiento y acceso aleatorio.

Creo que no es necesario que se creen como archivos de gran tamaño. Simplemente establece un tamaño máximo grande en ellos y se expandirán cuando escriba en partes que no haya tocado anteriormente.

+1

El uso de archivos mapeados en memoria también presenta más complicaciones: los errores se informan mediante excepciones estructuradas en lugar de valores de retorno de función, y no podrá asignar un archivo completo de 8 GB a la memoria en Windows de 32 bits porque solo tiene 2 GB de espacio de direcciones virtuales (o 3 GB si tiene suerte). – bk1e

+0

Definitivamente necesitará usar una ventana (o varias si está utilizando muchas partes del archivo de forma independiente) para asignar lo relevante a la memoria. No es como si tuviera el archivo completo accesible si usa el archivo estándar IO de todos modos. Simplemente lo hice usando fseeks en lugar de cambiar lo que está mapeado en la memoria. – Laserallan

0

Si está utilizando NTFS entonces sparse files son el camino a seguir:

Un archivo en el que gran parte de los datos es ceros se dice que contiene un conjunto de datos dispersos . Los archivos como estos normalmente son muy grandes, por ejemplo, un archivo que contiene datos de imagen para ser procesados ​​ o una matriz dentro de una base de datos de alta velocidad . El problema con los archivos que contienen conjuntos de datos dispersos es que la mayoría del archivo no contiene datos útiles y, debido a esto, son un uso ineficiente de espacio en disco.

La compresión de archivos en el archivo 0FS es una solución parcial al problema . Todos los datos en el archivo que es no explícitamente escrito están explícitamente establecidos en cero. Compactos de compresión de archivos estos rangos de ceros. Sin embargo, un inconveniente de la compresión de archivos es que el tiempo de acceso puede aumentar debido a la compresión y descompresión de datos .

Soporte para archivos dispersos se introduce en el sistema de archivos NTFS como otra forma para hacer uso de espacio en disco de forma más eficiente .Cuando la funcionalidad de archivo está habilitada, el sistema no asigna espacio en el disco duro a un archivo, excepto en las regiones donde contiene datos distintos de cero. Cuando se intenta una operación de escritura donde una gran cantidad de los datos en el búfer es ceros, los ceros no se escriben en el archivo . En su lugar, el sistema de archivos crea una lista interna que contiene las ubicaciones de los ceros en el archivo , y esta lista se consulta durante todas las operaciones de lectura. Cuando se realiza una operación de lectura en áreas del archivo donde se encuentran ceros, el sistema de archivos devuelve el número apropiado de ceros en la memoria intermedia asignado para la operación de lectura . De esta forma, el mantenimiento de el archivo disperso es transparente para todos los procesos que acceden a él, y es más eficiente que la compresión para este escenario particular de .

+2

No, él tiene que asignar previamente las extensiones. –

0

Uso "fsutil" comando:

E: \ VirtualMachines> fsutil archivo createnew Uso: fsutil archivo createnew como son: fsutil archivo createnew C: \ fichprueba.txt 1000

Reagds

PD es para Windows: Solución 2000/XP/7

1

Bueno this no es malo, pero lo que busca es SetFileValidData

Como MSDN EFS:

La función SetFileValidData le permite evite llenar datos con ceros cuando escribe de forma no secuencial en un archivo.

Así que esto siempre deja los datos del disco tal como están, SetFilePointerEx debe establecer todos los datos en ceros, por lo que la asignación grande tarda un tiempo.

+1

Tenga en cuenta que 'SetFileValidData' es un gran riesgo de seguridad, por lo que necesita un proceso con privilegios para poder utilizar esta función también. La solución propuesta por Laserallan (archivos mapeados en memoria) es mucho más preferible si tiene suficiente espacio de direcciones. Crear una asignación de un tamaño arbitrario es tanto rápido como seguro. – Damon

0

Soy consciente de que su pregunta está etiquetada con Windows, y Brian R. Bondy le dio la mejor respuesta a su pregunta si sabe con certeza que no tendrá que transferir su aplicación a otras plataformas. Sin embargo, si tiene que portar su aplicación a otras plataformas, puede hacer algo más parecido a lo que Adrian Cornish propuso como respuesta a la pregunta "¿Cómo crear un archivo de tamaño" x "?" encontrado en How to create file of "x" size?.

FILE *fp=fopen("myfile", "w"); 
fseek(fp, 1024*1024, SEEK_SET); 
fputc('\n', fp); 
fclose(fp); 

Por supuesto, hay un toque adicional. La respuesta propuesta por Adrian Cornish hace uso de la función fseek que tiene la siguiente firma.

int fseek (FILE * stream, long int offset, int origin); 

El problema es que desea crear un archivo muy grande, con un tamaño de archivo que está más allá del alcance de un entero de 32 bits. Necesitas usar el equivalente de 64 bits de fseek. Desafortunadamente, en diferentes plataformas tiene diferentes nombres.

El archivo de cabecera LargeFileSupport.h encontrado en http://mosaik-aligner.googlecode.com/svn-history/r2/trunk/src/CommonSource/Utilities/LargeFileSupport.h ofrece una solución a este problema.

Esto le permitiría escribir la siguiente función.

#include "LargeFileSupport.h" 
/* Include other headers. */ 

bool createLargeFile(const char * filename, off_type size) 
{ 
    FILE *fp = fopen(filename, "w"); 
    if (!fp) 
    { 
     return false; 
    } 
    fseek64(fp, size, SEEK_SET); 
    fputc('\n', fp); 
    fclose(fp); 
} 

Pensé que podría agregar esto en caso de que la información te sea útil.