fscanf - php fseek big files
La salida de ftell en función php (4)
El parámetro de longitud de fgets indica una longitud máxima. La fgets() declara:
La lectura finaliza cuando se ha leído 1 bytes, o una nueva línea (que se incluye en el valor de retorno), o un EOF (lo que ocurra primero). Si no se especifica una longitud, seguirá leyendo desde el flujo hasta que llegue al final de la línea.
En su caso, la primera línea contiene <!DOCTYPE html>
, que explica el resultado de 16 dado por ftell
.
Aquí está mi código:
<?php
$url="http://www.sina.com.cn";
$handle = @fopen($url, "r");
$len=get_headers($url,true);
print_r($len);
echo $len[''Content-Length'']."/n";
if ($handle) {
while (($buffer = fgets($handle,1024)) !== false) {
echo ftell($handle)."/n";
fseek($handle,200000,SEEK_CUR);
echo ftell($handle)."/n";
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail/n";
}
fclose($handle);
}
?>
El resultado es el siguiente:
Array
(
[0] => HTTP/1.1 200 OK
[Content-Type] => text/html
[Vary] => Accept-Encoding
[X-Powered-By] => shci_v1.03
[Server] => nginx
[Date] => Thu, 24 Dec 2015 04:03:39 GMT
[Last-Modified] => Thu, 24 Dec 2015 04:01:28 GMT
[Expires] => Thu, 24 Dec 2015 04:04:39 GMT
[Cache-Control] => max-age=60
[Age] => 32
[Content-Length] => 518264
[X-Cache] => HIT from xidan33-99.sina.com.cn
[Connection] => close
)
518264
16
200016
200058
400058
400065
518264
La longitud del contenido tal vez no sea la misma que la mía - 518264, se cambiará dinámicamente cuando ejecute el código, no importa para la discusión. ¿Por qué el resultado no es el siguiente?
518264
1024
201024
202048
402048
403072
por favor explique la acción del puntero de archivo en fgets y funciones ftell y fseek.
Hay tres funciones disponibles para configurar y determinar la posición del puntero de archivo para un archivo determinado.
fgets ()
Obtiene una línea desde el puntero del archivo. supondría 1024 como la longitud de la línea. Si la mayoría de las líneas en el archivo son más grandes que 8KB, es más eficiente en recursos para su script especificar la longitud máxima de la línea.
Devuelve una cadena de hasta longitud: 1 bytes leídos del archivo al que apunta el identificador. Si no hay más datos para leer en el puntero del archivo, se devuelve FALSE
.
ftell ()
Función incorporada: pos = ftell (fid)
Devuelve la posición del puntero del archivo como el número de caracteres desde el principio del archivo especificado por el descriptor de archivo fid
.
fseek ()
Función fseek (fid, offset)
: fseek (fid, offset)
Función fseek (fid, offset, origin)
: fseek (fid, offset, origin)
Establezca el puntero del archivo en el desplazamiento de ubicación dentro del archivo fid.
El puntero se posiciona en caracteres de desplazamiento desde el origen, que puede ser una de las variables predefinidas SEEK_CUR (current position), SEEK_SET (beginning),
o SEEK_END (end of file)
o cadenas "cof", "bof" or "eof".
Si se omite el origen, se asume SEEK_SET. el desplazamiento puede ser positivo, negativo o cero, pero no todas las combinaciones de origen y desplazamiento pueden realizarse.
fseek
devuelve 0 en caso de éxito y -1 en caso de error.
Según la documentación de PHP para fgets() ,
La lectura finaliza cuando se ha leído 1 bytes, o una nueva línea (que se incluye en el valor de retorno), o un EOF (lo que ocurra primero).
Aquí la longitud es el segundo parámetro que ha utilizado al llamar a fgets()
, que es 1024 . Por lo tanto, su llamada a fgets()
terminará la lectura cuando suceda algo de lo siguiente:
- Ha leído 1023 bytes desde la misma línea.
- Ha llegado al final de la línea actual.
- Ha llegado al final del archivo.
Entonces, en su caso, cuando fgets()
lee la primera línea, llega al final de la primera línea después de leer 16 bytes, y esa será la posición del puntero del archivo cuando sea llamado por ftell()
lado. ftell() devuelve la posición actual del puntero del archivo en el archivo.
Cuando esté en la siguiente línea llamando a fgets()
nuevamente (iterado por el bucle while), su posición inicial en el archivo ahora es 16 (notablemente no 1024) y puede leer hasta (16 + 1024) 1040 bytes (no hasta 2048). Nuevamente, si su próxima línea tiene solo 42 bytes, este fgets()
terminará la lectura en 58 bytes, que será la posición del puntero del archivo cuando sea llamado por ftell()
nuevamente.
Y de nuevo, iniciará los próximos fgets()
desde 58 bytes, para leer hasta (58 + 1024 =) 1082 bytes. Continuará de esta manera.
Efecto de fseek()
fseek()
se utiliza para mover el puntero del archivo a una posición específica en el archivo según lo establecido por $ offset (2º parámetro). De acuerdo con la documentación de PHP para fseek() , los valores del tercer parámetro pueden ser:
SEEK_SET
- Establece la posición igual a los bytes de desplazamiento.
SEEK_CUR
: establecer la posición en la ubicación actual más el desplazamiento.
SEEK_END
- Establece la posición al final del archivo más el desplazamiento.
Entonces, por fseek($handle,200000,SEEK_CUR);
está configurando el puntero del archivo para que esté en 200000 + la posición actual. Por ejemplo, se moverá a 200016 cuando estaba en 16.
Use la función stream_get_meta_data()
PHP para averiguar si la secuencia que abrió se puede buscar:
$url="http://www.sina.com.cn";
$handle = @fopen($url, "r");
$meta_data = stream_get_meta_data($handle);
var_dump($meta_data[''seekable'']);
// It prints `bool(false)`
La corriente no es buscable. Esto significa que las funciones fseek()
, ftell()
y rewind()
tienen un comportamiento inesperado (y probablemente inconsistente).