Ir al contenido


Foto

Conocer Longitud de un archivo mayor que 4.294.967.295 bytes


  • Por favor identifícate para responder
10 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 14 junio 2010 - 07:52

Para conocer la longitud de un archivo mayor que 4.294.967.295 bytes podemos usar la siguiente función que propongo:



delphi
  1. function _GetFileSize(hFile: THandle): int64;
  2. var
  3.   lo, hi: Cardinal;
  4. begin
  5.   lo:= Windows.GetFileSize(hFile, @hi);
  6.   Result:= hi;
  7.   Result:= (Result shl 32) or lo;
  8. end;



La versión C/C++:


cpp
  1. __int64 _GetFileSize(HANDLE hFile)
  2. {
  3.   DWORD hi;
  4.   DWORD lo = GetFileSize(hFile, &hi);
  5.   __int64 R = hi;
  6.   return (R << 32) | lo;
  7. }



Saludos.
  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 14 junio 2010 - 08:24

Esa unidad Windows trae muy buenas funciones, la cuestión es saber para que sirven :) (y)

Salud OS
  • 0

#3 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 14 junio 2010 - 08:34

Hola, tengo una preguntonta... esos casi 4GB se debe al sistema de archivos FAT32 ¿no es cierto? Ahora con NTFS supuestamente el límite debería ser 16 TB.

No estoy bien familiarizado de como vendrá la mano con la API de Windows y si es que hubo algún cambio en ésta desde Windows Vista y superiores...

¿La implementación de esta función se debe a que la API GetFileSize todavía está basada en FAT32?¿No fue "adaptada" para NTFS?

No termino de entender la magia de la matemática que se aplica en el código.

Lo que más me llama la atención es que no se hace una comprobación de GetLastError y/o si el valor es 0xFFFFFFFF. Esto lo digo por lo que leo en MSDN.

Por último, ahora me asalta la duda, ¿Que diferencia hay entre GetFileSize y GetFileSizeEx?

Si alguien me saca estas dudas me haría un poquito menos ignorante.

Saludos,
  • 0

#4 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 14 junio 2010 - 08:39

Bueno en general, todas las funciones que terminan con Ex son funciones extendidas de la función base, es decir, cuenta con opciones avanzadas.

Salud OS
  • 0

#5 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 14 junio 2010 - 08:59

Bueno, al menos eso indica la teoría... Ex indica que viene con algo más... Pero en este caso rompe el molde. Lo único que veo de diferente es la forma de tratar el error, con la versión Ex si la función funciona bien regresa un valor distinto de cero, en otro caso devuelve cero y debe verificarse en GetLastError para saber más del error.

La API tiene igual cantidad de parámetros y del mismo tipo, por ello yo me pregunto ¿Que diferencia hay, exceptuando la que he mencionado?  ^o|

Saludos,
  • 0

#6 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 14 junio 2010 - 09:03

Pues  de la ayuda podemos ver una situación interesante y como esa debe haber mas situaciones que la función base carece.

If the function fails and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get extended error information, call GetLastError. When lpFileSizeHigh is NULL, the results returned for large files are ambiguous, and you will not be able to determine the actual size of the file. It is recommended that you use GetFileSizeEx instead.

Si la función falla y lpFileSizeHigh es NULL, el valor de retorno es INVALID_FILE_SIZE. Para obtener información adicional sobre el error, llamar a GetLastError. Cuando lpFileSizeHigh es NULL, los resultados devueltos para archivos de gran tamaño son ambiguas, y usted no será capaz de determinar el tamaño real del archivo. Se recomienda que utilice GetFileSizeEx lugar.

*************************************************************************************

Note that if the return value is INVALID_FILE_SIZE (0xffffffff), an application must call GetLastError to determine whether the function has succeeded or failed. The reason the function may appear to fail when it has not is that lpFileSizeHigh could be non-NULL or the file size could be 0xffffffff. In this case, GetLastError will return NO_ERROR (0) upon success. Because of this behavior, it is recommended that you use GetFileSizeEx instead.

Tenga en cuenta que si el valor de retorno es INVALID_FILE_SIZE (0xffffffff), una aplicación debe llamar a GetLastError para determinar si la función ha tenido éxito o ha fracasado. La razón de la función puede aparecer un error cuando se tiene no es que lpFileSizeHigh podría ser que no sea NULL o el tamaño del archivo puede ser 0xffffffff. En este caso, GetLastError devolverá NO_ERROR (0) en el éxito. Debido a este comportamiento, se recomienda que utilice GetFileSizeEx lugar.


Salud OS

Edito: La verdad me dió flojera traducir y utilicé el traductor de google :)
  • 0

#7 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 15 junio 2010 - 05:33

Hola, tengo una preguntonta... esos casi 4GB se debe al sistema de archivos FAT32 ¿no es cierto? Ahora con NTFS supuestamente el límite debería ser 16 TB.


En realidad ambas API son bastante similares en cuanto a su funcionalidad. GetFileSizeEx es mas moderna.

El problema de los 4 GB se debe a que un entero, int o integer en un sistema de 32 bits, es de 32 bits y por lo tanto no puede representar números mayores a 4.294.967.295. La API GetFileSize nos entrega el dato en dos DWORD, la parte alta y baja de un int64, con los que reconstruimos el valor.

GetFileSizeEx trabaja con un puntero a un LARGE_INTEGER que en realidad es un entero de 64 bits o dicho de otra forma un int64. De esta forma obtenemos el resultado directamente. Algunos compiladores antiguos no permiten el uso directo de la nueva API teniendola que importar.

Saludos.


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 15 junio 2010 - 06:40

La implementación con la API GetFileSizeEx podría ser así:



delphi
  1. function GetFileSizeEx(hFile: THandle; var Data: int64): boolean; stdcall; external 'Kernel32.dll' name 'GetFileSizeEx';
  2.  
  3. implementation
  4.  
  5.  
  6. function _GetFileSize(hFile: THandle): int64;
  7. begin
  8.   if not GetFileSizeEx(hFile, Result) then Result:= 0;
  9. end;



O en C:


cpp
  1. __int64 _GetFileSize(HANDLE hFile)
  2. {
  3.     __int64 S;
  4.     if (!GetFileSizeEx(hFile, (PLARGE_INTEGER)&S)) S=0;
  5.     return S;
  6. }



Saludos.

  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 junio 2010 - 08:28

Eliseo, eso ya lo había leído y parte de eso lo había comentado  ;) en los post anteriores.

Gracias escafandra, no había pensado en que se debe al limite de un integer. Directamente asocié el número al sistema FAT32. Aquí es donde debo decirme: LOL  :

Ya me queda claro el porqué de su diferencia y la "extraña" operación que realizas. ¡"Sumas" ambas partes! Tengo que ponerme a estudiar mejor las operaciones de bits... siempre han sido mi debilidad.

Habría que aclarar que el tipo Int64, al menos en la arquitectura de 32 bits, técnicamente no existe... aunque el compilador nos engaña y nos haga creer que en realidad es un entero de 64: se trata de dos integer, en uno almacena la parte alta y en otro la baja.
En últimas, estamos en la misma :D

Saludos,
  • 0

#10 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 15 junio 2010 - 08:48

Eliseo, eso ya lo había leído y parte de eso lo había comentado  ;) en los post anteriores.


:embarrassed: :lipsrsealed:

Salud OS
  • 0

#11 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 junio 2010 - 03:58



:embarrassed: :lipsrsealed:

Salud OS

No lo dije con mala intención amigo. No se me ponga triste.
El que se siente tonto y mal soy yo... por no haber razonado bien el porqué de los 4.294.967.295 bytes y la "compleja" operación matemática.

Saludos,
  • 0




IP.Board spam blocked by CleanTalk.