Jump to content


Photo

Reservar espacio en disco mediante un fichero cambiando su tamaño


  • Please log in to reply
6 replies to this topic

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 24 August 2010 - 04:53 AM

En ocasiones nos hace falta reservar espacio en el HD en forma de un archivo vacío pero que ocupe cierto espaco en el disco.

En ANSI C disponemos de la función chsize. La API de Windows nos permite realizar la misma operación con archivos reservando tamaño incluso mayor que 4.294.967.295 bytes. En este caso no disponemos de una función directa, así que propongo una como esta:



cpp
  1. BOOL SetFileSize(char* FileName, __int64 Size)
  2. {
  3.   bool Result = false;
  4.   LONG Hi = LONG(Size >> 32);
  5.   DWORD Attributes = GetFileAttributes(FileName);
  6.   if(Attributes == -1) Attributes = FILE_ATTRIBUTE_NORMAL;
  7.   SetFileAttributes(FileName, FILE_ATTRIBUTE_NORMAL);
  8.   HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  9.   if(hFile != HANDLE(-1)){
  10.     if(SetFilePointer(hFile, (LONG)Size, &Hi, FILE_BEGIN) != INVALID_SET_FILE_POINTER){
  11.       Result = SetEndOfFile(hFile);
  12.     }
  13.     CloseHandle(hFile);
  14.   }
  15.   SetFileAttributes(FileName, Attributes);
  16.   return Result;
  17. }



En delphi sería algo así:



delphi
  1. function SetFileSize(FileName: String; Size: int64): boolean;
  2. var
  3.   Hi: DWORD;
  4.   Attributes: DWORD;
  5.   hFile: THandle;
  6.   R: integer;
  7. begin
  8.   Hi:= DWORD(Size shr 32);
  9.   Result:= false;
  10.   Attributes:= GetFileAttributes(PCHAR(FileName));
  11.   if(Attributes = DWORD(-1)) then Attributes:= FILE_ATTRIBUTE_NORMAL;
  12.   SetFileAttributes(PCHAR(FileName), FILE_ATTRIBUTE_NORMAL);
  13.   hFile:= CreateFile(PCHAR(FileName), GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  14.   if hFile <> THandle(-1) then
  15.   begin
  16.     if SetFilePointer(hFile, DWORD(Size), @Hi, FILE_BEGIN) <> DWORD(-1) then
  17.     begin
  18.       Result:= SetEndOfFile(hFile);
  19.     end;
  20.     CloseHandle(hFile);
  21.   end;
  22.   SetFileAttributes(PCHAR(FileName), Attributes);
  23. end;


Esta función trunca o amplia el fichero si existe o lo crea, en caso contrario.

Que le saqueís partido.


Saludos.

  • 0

#2 seoane

seoane

    Advanced Member

  • Administrador
  • 1259 posts
  • LocationEspaña

Posted 24 August 2010 - 07:55 AM

Por cierto, cuando se incrementa el tamaño del fichero usando SetFilePointer todos los bytes añadidos se inicializan a cero. Aunque no lo pone en la documentación, esto es cierto, podéis comprobarlo.

Sin embargo cuando creas un fichero de 2Gigas usando este método, aunque todo se incializa a cero, no escribe nada en disco, asi que me pregunto como lo hace ¿tendré que investigarlo?  ^o|
  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14460 posts
  • LocationMéxico

Posted 24 August 2010 - 08:24 AM

Vaya, me parece muy interesante e ingenioso poder reservar espacio de disco para archivos que aún no se crean :)

Salud OS
  • 0

#4 seoane

seoane

    Advanced Member

  • Administrador
  • 1259 posts
  • LocationEspaña

Posted 24 August 2010 - 12:43 PM

Ya he resuelto el enigma  :)

Al parecer ntfs diferencia entre el tamaño de fichero, y el tamaño de datos "validos". Es decir cuando hacemos crecer un fichero usando SetFilePointer, ntfs "recuerda" que esos bytes extra estan sin inicializar y cuando se intentan leer devuelve simplemente 0.

Pero podemos ver un ejemplo de esto usando la consola de windows:

Primero creamos un fichero de 4 MB


delphi
  1. fsutil file createnew test.txt 4194304



Si comprobamos su contenido vemos que leemos solo ceros


delphi
  1. more < test.txt



Ahora le decimos al sistema que todos los datos del fichero son validos


delphi
  1. fsutil file setvaliddata test.txt 4194304



Y volvemos a comprobar el contenido del fichero


delphi
  1. more < test.txt



Ahora vemos que el fichero esta lleno de datos a simple vista aleatorios ... aunque no tanto  ;)

Para hacer lo anterior se tiene que estar usando la consola como administrador así que en Windows Vista y 7 es necesario abrir la consola con la opción "Run as administrator". La razón de que se necesiten permisos de administrador es muy sencilla, la seguridad. Solo hay que pensar en que si hacemos esto mismo con un fichero de, por ejemplo, 20 GB y luego lo examinamos encontraremos datos de ficheros que han sido borrados con anterioridad, incluso de otros usuarios, por eso solamente el administrador puede tener acceso a este tipo de datos.
  • 0

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14460 posts
  • LocationMéxico

Posted 24 August 2010 - 12:46 PM

Ah  vaya, sólo 5 horas para resolver el enigma  (b) (b) (b)

Que perseverante eres amigo Domingo :)

Salud OS
  • 0

#6 seoane

seoane

    Advanced Member

  • Administrador
  • 1259 posts
  • LocationEspaña

Posted 24 August 2010 - 12:51 PM

Ah  vaya, sólo 5 horas para resolver el enigma


Me llevo mas tiempo del que esperaba, pero tenía ir a trabajar. No me pude coger la tarde libre para resolver el enigma  :D  (b)
  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14460 posts
  • LocationMéxico

Posted 24 August 2010 - 01:29 PM


Ah  vaya, sólo 5 horas para resolver el enigma


Me llevo mas tiempo del que esperaba, pero tenía ir a trabajar. No me pude coger la tarde libre para resolver el enigma  :D  (b)


No, pues así ni quien diga nada, :) (b) (b) (b)

Salud OS
  • 0




IP.Board spam blocked by CleanTalk.