Post by Manuel GomezPost by Sergio Perea# buffer contiene una linea
fwrite($DescriptoFicheroSalida, $buffer, 4096);
Has probado con type fichero
mejor con tail -n 100 fichero y ves si se ha grabado el final
En un mensaje anterior, Sergio dijo que usaba un sistema de ficheros
NTFS por lo que seguramente usará Windows y tail no le funcionará.
Además, no creo que sea que el fichero esté corrupto, sino que el editor
que usa Sergio para leer el archivo no admite ficheros de más de 2Gb.
Sergio, has puesto código incompleto, sólo dices cómo abres el fichero y
como escribes (fopen, fwrite), pero no pones el código intermedio. Esto es
MUY importante. Verás: si abres el fichero con modo "w+", me juego el cuello
a que luego haces un fseek para poner el puntero de escritura al final del
archivo, ¿me equivoco? Usar la función fseek es muy peligroso para este tipo
de archivos mayores de 2Gigas. Asegurate de usar lo siguiente, para
posicionar el puntero:
fseek( $fp, 0, SEEK_END );
De otra forma, estarás usando funciones no válidas para ficheros
enormes. Por ejemplo, esto SI que corromperá el fichero:
fseek( $fp, $tamano_archivo, SEEK_SET );
Tanto Windows como Linux (usando sistemas de ficheros NTFS o ext2/3) son
suficientemente capaces de manejar sin problema ficheros de muuuuchos gigas.
El problema viene con las aplicaciones y por el uso de "int". El tipo de
dato "int" a veces nos olvidamos que su valor máximo son 2Gigas (INT_MAX),
subiendo a 4Gigas si es sin signo (UINT_MAX). (2^31 y 2^32
respectivamente en plataformas de 32 bits). Para manejar ficheros de este
tamaño, hay que usar datos de tipo "long long int" (usando C).
Esto se hace patente viendo el manual de PHP en la página de la función
"filesize" en la que se dice textualmente:
"Nota: Dado que el tipo entero de PHP tiene signo y muchas plataformas usan
enteros de 32 bits, filesize() puede devolver resultados inesperados para
archivos con un tamaño mayor de 2GB. Para archivos entre 2GB y 4GB de
tamaño, esto puede resolverse por lo general usando sprintf("%u",
filesize($archivo))."
Osea, que como me temía PHP usa internamente "int" para representar
valores enteros, en lugar de "long" o "long long". Lo que es peor, en la
página sobre tipos de datos, se especifica claramente:
"El tamaño de un entero es dependiente de la plataforma, aunque un valor
máximo de aproximadamente dos billones es el valor usual (lo que es un valor
de 32 bits con signo). PHP no soporta enteros sin signo."
Resumiendo que me estoy yendo por las ramas, mejor abre el fichero con
modo "a" o "a+", o usa la funcion "error_log" para escribir ficheros de log,
de esta forma debería ser seguro que no se corrompe el archivo.
Como última recomendación, asegurate de que el fichero está corrupto.
Simplemente abriendo el archivo en un editor no lo puedes asegurar porque no
puedes saber si ese editor admite ficheros mayores de 2Gigas. Para estar mas
seguro haz un programa en C u otro lenguaje usando tipos de datos y
funciones correctas para ficheros enormes.
De todas formas, ficheros de log de 2 gigas o más son prácticamente
intratables. Deberías usar alguna forma de partir esos ficheros de log por
ejemplo agrupando la información por días, horas, etc.
Referencias:
- Manual de PHP: Función "filesize":
http://es2.php.net/manual/es/function.filesize.php
- Manual de PHP: Tipos / Enteros:
http://es2.php.net/manual/es/language.types.integer.php
- Manual de PHP: Función "error_log":
http://es2.php.net/manual/es/function.error-log.php
Saludos.
Jose Miguel.