SoloCodigo

Programación General => C/C++ => Mensaje iniciado por: maxstepin en Lunes 19 de Octubre de 2009, 12:20

Título: fseek
Publicado por: maxstepin en Lunes 19 de Octubre de 2009, 12:20
hola.

fseek(archivo, 0, SEEK_END);
        printf("ntamaño del archivo %lu", (ftell(archivo)));

este codigo me indica el tamaño de un determinado archivo. lo he probado y funciona solo en archivos pequeños. cuando lo pruebo en archivos de 4GB o mas, se imprime 0 como resultado. hay veces que en archivos de 3,5GB si da un resultado, pero es incorrecto.

como podria averiguar el tamaño de archivos de 4GB o mas? hay algun limite para el tamaño de archivo?

saludos. :lol:
Título: Re: fseek
Publicado por: m0skit0 en Lunes 19 de Octubre de 2009, 12:39
Todo depende del sistema operativo y del sistema de ficheros. Hay sistemas de ficheros que no soportan ficheros de más de 2 GB o más de 4 GB... Esto implica que, aunque ftell() en el estándar POSIX devuelva long, es probable que sistemas que no cumplan el estándar 100% no devuelvan long (o ponga long pero en realidad usen int internamente, es imposible saber sin tener el código fuente del SO).
Título: Re: fseek
Publicado por: Eternal Idol en Lunes 19 de Octubre de 2009, 12:51
long es muchas veces 4 bytes.

http://en.wikipedia.org/wiki/Integer_(computer_science (http://en.wikipedia.org/wiki/Integer_(computer_science" onclick="window.open(this.href);return false;))

GetFileSizeEx (http://msdn.microsoft.com/en-us/library/aa364957(VS.85).aspx) en Windows.
Título: Re: fseek
Publicado por: maxstepin en Lunes 19 de Octubre de 2009, 13:02
Cita de: "m0skit0"
Todo depende del sistema operativo y del sistema de ficheros. Hay sistemas de ficheros que no soportan ficheros de más de 2 GB o más de 4 GB... Esto implica que, aunque ftell() en el estándar POSIX devuelva long, es probable que sistemas que no cumplan el estándar 100% no devuelvan long (o ponga long pero en realidad usen int internamente, es imposible saber sin tener el código fuente del SO).

perdona, no especifique. OS: windows 7 x86, compilador: Mingw32.
sistema de archivos: NTFS, si hay archivos de 8 GB (tranquilamente) en este sistema de ficheros, fseek deberia funcionar correctamente tambien, no? o a lo mejor el problema es ftell?

igual, en mi sistema un long pesa lo mismo que un int (?), no deberia ser de 8 bytes?

la funcion de la API, GetFileSizeEx, solo funcionara en sistemas windows, pero que funcion de libreria estandar me puede ayudar?, ya sabes por lo de la portabilidad.

saludos :comp:
Título: Re: fseek
Publicado por: m0skit0 en Lunes 19 de Octubre de 2009, 13:12
Cita de: "maxstepin"
la funcion de la API, GetFileSizeEx, solo funcionara en sistemas windows, pero que funcion de libreria estandar me puede ayudar?
Ya te digo que Windows no cumple los estándares, así que si programas para Windows, mejor olvídate de la portabilidad.
Título: Re: fseek
Publicado por: maxstepin en Lunes 19 de Octubre de 2009, 13:27
Cita de: "m0skit0"
Cita de: "maxstepin"
la funcion de la API, GetFileSizeEx, solo funcionara en sistemas windows, pero que funcion de libreria estandar me puede ayudar?
Ya te digo que Windows no cumple los estándares, así que si programas para Windows, mejor olvídate de la portabilidad.
Entonces, si programo bajo Linux, me puedo olvidar de una funcion que me diga el tamaño de un archivo de 8 GB? o su sistema de archivos(de Linux) no soporta archvos de 8 GB?

algun dia tengo pensado codificar para UNIX/Linux, pero primero aprender bajo windows, o si no estoy perdido.
Título: Re: fseek
Publicado por: m0skit0 en Lunes 19 de Octubre de 2009, 13:30
Cita de: "maxstepin"
si programo bajo Linux, me puedo olvidar de una funcion que me diga el tamaño de un archivo de 8 GB?
Linux sí conforma más a POSIX (aunque no totalmente), así que ftell() debería funcionar bien.
Título: Re: fseek
Publicado por: maxstepin en Lunes 19 de Octubre de 2009, 14:01
La unica solucion bajo windows es usar getfilesizeex? no hay nada mas?
Título: Re: fseek
Publicado por: r0d en Lunes 19 de Octubre de 2009, 14:26
Una solucion portable y que estara incluida probablemente en el proximo estandar c++1x: boost::filesystem (http://www.boost.org/doc/libs/1_40_0/libs/filesystem/doc/index.htm)
Título: Re: fseek
Publicado por: m0skit0 en Lunes 19 de Octubre de 2009, 14:30
Cita de: "maxstepin"
La unica solucion bajo windows es usar getfilesizeex? no hay nada mas?
Pues va a ser que no. Quejas al de la foto.
Título: Re: fseek
Publicado por: maxstepin en Lunes 19 de Octubre de 2009, 15:27
Cita de: "m0skit0"
Cita de: "maxstepin"
La unica solucion bajo windows es usar getfilesizeex? no hay nada mas?
Pues va a ser que no. Quejas al de la foto.
ese soy yo. a que soy guapo?
Título: Re: fseek
Publicado por: Eternal Idol en Lunes 19 de Octubre de 2009, 18:08
A ver, que yo sepa en x86 un long ocupa 4 bytes y el standard dice unicamente cual es el tamaño minimo que debe tener (32 bits, 4 bytes). ¿Esto existe por casualidad? Apostaria a que los que crearon la funcion (que es ANSI C) hace siglos no esperaban archivos de mas de 4GB  :clown:

http://www.mkssoftware.com/docs/man3/ftell.3.asp (http://www.mkssoftware.com/docs/man3/ftell.3.asp" onclick="window.open(this.href);return false;)

Mas referencias:
"On many (but not all) C and C++ implementations, a long is larger than an int. Today's most popular desktop platforms, such as Windows and Linux, run primarily on 32 bit processors and most compilers for these platforms use a 32 bit int which has the same size and representation as a long."

http://home.att.net/~jackklein/c/inttypes.html#long (http://home.att.net/~jackklein/c/inttypes.html#long" onclick="window.open(this.href);return false;)
http://software.intel.com/en-us/article ... re-and-os/ (http://software.intel.com/en-us/articles/size-of-long-integer-type-on-different-architecture-and-os/" onclick="window.open(this.href);return false;)
Título: Re: fseek
Publicado por: m0skit0 en Martes 20 de Octubre de 2009, 13:38
Cita de: "Eternal Idol"
A ver, que yo sepa en x86 un long ocupa 4 bytes
¿Sí? Que yo sepa un int ocupa 4 bytes (modo protegido)  :huh:
Título: Re: fseek
Publicado por: Eternal Idol en Martes 20 de Octubre de 2009, 13:50
Cita de: "m0skit0"
¿Sí? Que yo sepa un int ocupa 4 bytes (modo protegido)  :huh:

Si y en cuanto a tamaño son lo mismo, ver referencias.
Título: Re: fseek
Publicado por: maxstepin en Martes 20 de Octubre de 2009, 16:24
i que tal :

Código: C
  1.  
  2. #include <stdio.h>
  3. #include <sys/stat.h> /* Para la estructura stat */
  4. #include <unistd.h>
  5.  
  6. main(int argc, char **argv)
  7. {
  8.     struct stat64 buf;
  9.  
  10.     printf("%sn",argv[1]);
  11.  
  12.     if ( stat64(argv[1], &buf) == -1 )
  13.     {
  14.         perror(argv[1]);
  15.         getchar();
  16.         exit(-1);
  17.     }
  18.     else
  19.     {
  20.         printf("Tamaño del archivo %s %d bytes.n",argv[1],buf.st_size);
  21.     }
  22.     getchar();
  23. }
  24.  

en stat(), a secas si que funciona, pero no se como hacer para usar stat64(), crear un puntero a una estructura stat64? me tira error: undefined reference to stat64.

GetFileSize, es una solucion que no me convence, lejos de la portabilidad, es un codigo poco elegante, se depende demasiado de la API. :bad:
Título: Re: fseek
Publicado por: Eternal Idol en Martes 20 de Octubre de 2009, 22:58
¿Esa funcion es standard? Sino lo es entonces es un codigo poco elegante ...
Título: Re: fseek
Publicado por: su - en Miércoles 21 de Octubre de 2009, 03:40
Si y no:
Cita de: "man stat64"
TRANSITIONAL DESCRIPTION (NOW DEPRECATED)
     The fstat64, lstat64 and stat64 routines are equivalent to their corre-
     sponding non-64-suffixed routine, when 64-bit inodes are in effect.  They
     were added before there was support for the symbol variants, and so are
     now deprecated.  Instead of using these, set the _DARWIN_USE_64_BIT_INODE
     macro before including header files to force 64-bit inode support.
Eso es en Darwin, pero no me estrañaria que otros sistemas operativos digan lo mismo, es mas, Open Group no lo documenta, asi que no es POSIX.
Mejor usar stat y compilador de 64 bits.
Título: Re: fseek
Publicado por: Eternal Idol en Miércoles 21 de Octubre de 2009, 08:43
Si no hay funcion standard entonces da lo mismo usar un servicio de un S.O. en particular (ademas que estos suelen ser mas potentes y con #ifdef se soluciona cualquier problema de portabilidad del codigo).
Título: Re: fseek
Publicado por: diego.martinez en Miércoles 21 de Octubre de 2009, 16:14
buenas:

yo lo que suelo hacer para portabilidad es usar el patrón factory y crear una clase para win32 y otra para unix.

entonces simplemente uso la api en uno y la stat en el otro.

suerte.
Título: Re: fseek
Publicado por: Eternal Idol en Miércoles 21 de Octubre de 2009, 17:25
Cita de: "diego.martinez"
yo lo que suelo hacer para portabilidad es usar el patrón factory y crear una clase para win32 y otra para unix.

Una buena solucion para C++  :beer:

Cita de: "diego.martinez"
entonces simplemente uso la api en uno y la stat en el otro.

¿Pero stat no es capaz de devolver el tamaño de un archivo de mas de 4GB, verdad?
Título: Re: fseek
Publicado por: su - en Jueves 22 de Octubre de 2009, 02:41
Cita de: "Eternal Idol"
¿Pero stat no es capaz de devolver el tamaño de un archivo de mas de 4GB, verdad?
Si estas en una maquina de 64 bits, si que puede... en 32 bits se supone que tambien, no se si en el Glibc actual arreglaron el problema, pero aqui lo documentan muy bien. (http://www.suse.de/~aj/linux_lfs.html)
Cita de: "Eternal Idol"
Si no hay funcion standard entonces da lo mismo usar un servicio de un S.O. en particular (ademas que estos suelen ser mas potentes y con #ifdef se soluciona cualquier problema de portabilidad del codigo).
Me explique mal  :nosweat:
stat (http://www.opengroup.org/onlinepubs/000095399/functions/stat.html) si es estandar, pero stat64 no lo es.
Título: Re: fseek
Publicado por: Eternal Idol en Jueves 22 de Octubre de 2009, 10:15
Cita de: "su -"
Si estas en una maquina de 64 bits, si que puede... en 32 bits se supone que tambien, no se si en el Glibc actual arreglaron el problema, pero aqui lo documentan muy bien. (http://www.suse.de/~aj/linux_lfs.html)

Si, pero en una de 32 bits no, el standard no lo soporta. Ahi lo que documentan es la API que tiene las funciones esas que terminan en 64 (ftello64 por ejemplo esta mencionada) pero no son standard.

Cita de: "su -"
Me explique mal  :nosweat:
stat (http://www.opengroup.org/onlinepubs/000095399/functions/stat.html) si es estandar, pero stat64 no lo es.

Exacto, no hay funcion standard que te sirva para obtener el tamaño de un archivo de mas de 4GB en un Windows o GNULinux de 32 bits, de una manera u otra tenes que recurrir a funciones no standard (VC++ soporta _stat64 por cierto, con guion bajo por no ser standard).
Título: Re: fseek
Publicado por: maxstepin en Jueves 22 de Octubre de 2009, 19:00
Cita de: "Eternal Idol"
Exacto, no hay funcion standard que te sirva para obtener el tamaño de un archivo de mas de 4GB en un Windows o GNULinux de 32 bits, de una manera u otra tenes que recurrir a funciones no standard (VC++ soporta _stat64 por cierto, con guion bajo por no ser standard).
Pero el fichero <sys/stat.h> existe en la carpeta include de Mingw, quiero decir que no me lo he bajado de ningun sitio. SI viene de serie con el compilador, no es una libreria estandar?
en dicho fichero de cabecera esta declarado el prototipo de la funcion stat64.
Código: C
  1. _CRTIMP int __cdecl __MINGW_NOTHROW _stat64 (const char*, struct __stat64*);
  2.  
stat(), si que he podido usarla, y en archivos de mas de 4 GB no funciona, hay desboramiento de memoria.
Si compilo esta version:
Código: C
  1.  
  2. #include <stdio.h>
  3. #include <sys/stat.h> /* Para la estructura stat */
  4. #include <unistd.h>
  5.  
  6. main(int argc, char **argv)
  7. {
  8.     struct stat64 buf;
  9.  
  10.     printf("%sn",argv[1]);
  11.  
  12.     if ( stat64(argv[1], &buf) == -1 )
  13.     {
  14.         perror(argv[1]);
  15.         getchar();
  16.         exit(-1);
  17.     }
  18.     else
  19.     {
  20.         printf("Tamaño del archivo %s %d bytes.n",argv[1],buf.st_size);
  21.     }
  22.     getchar();
  23. }
  24.  
Me tira este error:
+statmain.c|66|error: storage size of 'buf' isn't known|
Título: Re: fseek
Publicado por: Eternal Idol en Jueves 22 de Octubre de 2009, 19:38
No, no es standard, supongo que es parte de esa API que menciono su- y MinGW tiene la costumbre de usar la CRT del VC++.

En la MSDN (http://msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx).

No logro que haga el enlazado pero asi deberia compilar:
Código: C++
  1. struct __stat64 buf;
  2.  
Título: Re: fseek
Publicado por: maxstepin en Lunes 26 de Octubre de 2009, 01:28
todo lo hago desde el ide.
he probado "struct __stat64" sin resultados satisfactorios
Título: Re: fseek
Publicado por: Eternal Idol en Lunes 26 de Octubre de 2009, 10:44
¿Que IDE usas?

Ahora si, al fin, logre hacerlo con gcc usando este codigo:

Código: C++
  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <sys/stat.h> /* Para la estructura stat */
  4. #include <unistd.h>
  5.  
  6. struct _mstat64 {
  7.         _dev_t     st_dev;
  8.         _ino_t     st_ino;
  9.         unsigned short st_mode;
  10.         short      st_nlink;
  11.         short      st_uid;
  12.         short      st_gid;
  13.         _dev_t     st_rdev;
  14.         __int64    st_size;
  15.         __time64_t st_atime;
  16.         __time64_t st_mtime;
  17.         __time64_t st_ctime;
  18.         };
  19.  
  20. extern "C"
  21. {
  22.   _CRTIMP int __cdecl /*__MINGW_NOTHROW*/ _stat64 (const char*, struct _mstat64*);
  23. };
  24.  
  25. int main(int argc, char **argv)
  26. {
  27.     struct _mstat64 buf;
  28.     memset(&buf, 0, sizeof(buf));
  29.  
  30.     printf("%sn",argv[1]);
  31.  
  32.     if ( _stat64(argv[1], &buf) == -1 )
  33.     {
  34. //        perror(argv[1]);
  35.         getchar();
  36. //        exit(-1);
  37.     }
  38.     else
  39.     {
  40.         printf("Tamaño del archivo %s %I64d bytes.n", argv[1], buf.st_size);
  41.     }
  42.     getchar();
  43. return 0;
  44. }
  45.  

La estructura que viene con el MinGW NO me funciona, por eso tuve que definir _mstat64 que es la que viene en el VC++ en realidad ...
Título: Re: fseek
Publicado por: maxstepin en Lunes 26 de Octubre de 2009, 16:14
Cita de: "Eternal Idol"
¿Que IDE usas?
Codeblocks, y de compilador Mingw TDM's GCC/mingw32 Builds, de la siguiente pagina:

http://www.tdragon.net/recentgcc/ (http://www.tdragon.net/recentgcc/" onclick="window.open(this.href);return false;)

Creo que han tocado algo en la estructura de directorios, pero hasta ahora todo compilaba sin problemas.


Gracias por el esfuerzo, sos groso. primero lo he compilado como C, me tiraba error, al cabo de un rato lo he probado como C++ y listo.
Resultados: buenisimos, devuelve el tamaño exacto de archivos de 7GB, y los mas importante sin usar la API. Este codigo me puede sevir para programar un File Splitter and Joiner, para conocer el tamaño del archivo origen.

Como siempre, buena ayuda, te doy las gracias y te dejo un saludo.
Título: Re: fseek
Publicado por: Eternal Idol en Lunes 26 de Octubre de 2009, 16:20
De nadas  :comp:
Título: Re: fseek
Publicado por: maxstepin en Lunes 26 de Octubre de 2009, 16:23
Ah, casi se me pasa. la funcion:

Código: C++
  1. memset(&buf, 0, sizeof(buf));
  2.  

es esta? --> C:MinGWincludestring.h (1 hits)
   Line 40: _CRTIMP void* __cdecl __MINGW_NOTHROW   memset (void*, int, size_t);

sirve para guardar en el free store la variable buf? :o
gracias
Título: Re: fseek
Publicado por: Eternal Idol en Lunes 26 de Octubre de 2009, 17:06
http://www.cplusplus.com/reference/clib ... ng/memset/ (http://www.cplusplus.com/reference/clibrary/cstring/memset/" onclick="window.open(this.href);return false;)

Llena un bloque de memoria con un valor determinado, lo habia puesto mientras probaba y despues no lo borre  :devil: En este caso ponemos la estructura toda a 0, es una buena practica, especialmente con cadenas.
Título: Re: fseek
Publicado por: maxstepin en Lunes 26 de Octubre de 2009, 22:22
Cierto, hay que mantener buenos habitos de programacion :good: