fgets — вывод ftell в функцию php

Вот мой код:

<?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);
}
?>

Результат как ниже:

    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

Content-Length может не совпадать с моим — 518264, он будет динамически изменяться при выполнении кода, это не имеет значения для обсуждения.
Почему результат не следующий?

518264
1024
201024
202048
402048
403072

пожалуйста, объясните действие файлового указателя на функции fgets, ftell и fseek.

18

Решение

Согласно документации PHP для fgets (),

Чтение заканчивается, когда прочитана длина — 1 байт, или новая строка (которая включена в возвращаемое значение), или EOF (что наступит раньше).

Вот длина это второй параметр, который вы использовали при вызове fgets(), который 1024. Итак, ваш призыв к fgets() закончит чтение, когда произойдет любое из следующего:

  1. Это прочитал +1023 байты из той же строки.
  2. Он достиг конца текущей строки.
  3. Это достигло конца файла.

Итак, в вашем случае, когда fgets() читает первую строку, она достигла конца первой строки после прочтения 16 байт, и это будет позиция указателя файла при вызове ftell() рядом с ним. ftell () возвращает текущую позицию указателя файла в файле.

Когда вы находитесь в следующей строке, вызывая fgets()снова (повторяется while цикл), ваша начальная позиция в файле сейчас 16 (в частности, не 1024), и вы можете прочитать до (16 + 1024) 1040 байты (не до 2048). Опять же, если ваша следующая строка имеет только 42 байты, это fgets() закончится чтение в 58 байты, которые будут позицией указателя файла при вызове ftell() снова.

И снова вы собираетесь начать дальше fgets() от 58 байты, для чтения до (58 + 1024 =) 1082 байт. Так будет и дальше.

Эффект fseek()
fseek() используется для перемещения файлового указателя на определенную позицию в файле, установленную $ офсет (2-й параматер). Согласно документации PHP для FSEEK (), значения 3-го параметра могут быть —

SEEK_SETУстановите позицию, равную байту смещения.
SEEK_CURУстановить положение в текущее местоположение плюс смещение.
SEEK_ENDУстановить позицию в конец файла плюс смещение.

Итак, по fseek($handle,200000,SEEK_CUR); Вы устанавливаете указатель файла на 200000 + текущая позиция. Например, он перейдет на 200016, когда это было в 16.

7

Другие решения

Параметр длины в fgets указывает максимальную длину. PHP документация состояния:

Чтение заканчивается, когда прочитана длина — 1 байт, или новая строка (которая включена в возвращаемое значение), или EOF (что наступит раньше). Если длина не указана, он будет продолжать чтение из потока, пока не достигнет конца строки.

В вашем случае первая строка содержит <!DOCTYPE html>, который объясняет результат 16, данный ftell,

10

Три функции доступны для установки и определения позиции указателя файла для данного файла.

fgets ()

Получает строку из указателя файла. было бы принять 1024 в качестве длины линии. Если большинство строк в файле имеют размер более 8 КБ, для вашего сценария более эффективно использовать максимальную длину строки.

Возвращает строку длиной до 1 байта, прочитанную из файла, на который указывает дескриптор. Если в указателе файла больше нет данных для чтения, то FALSE возвращается

ftell ()

Встроенная функция: pos = ftell (fid)

Возвращает позицию указателя файла как количество символов от начала файла, указанного дескриптором файла fid,

FSEEK ()

Встроенная функция: fseek (fid, offset)
Встроенная функция: fseek (fid, offset, origin)

Установите указатель файла на смещение местоположения в файле fid.

Указатель позиционируется смещенными символами от начала координат, которые могут быть одной из предопределенных переменных SEEK_CUR (current position), SEEK_SET (beginning), или же SEEK_END (end of file) или строки "cof", "bof" or "eof". Если источник не указан, предполагается SEEK_SET. смещение может быть положительным, отрицательным или нулевым, но не все комбинации начала и смещения могут быть реализованы.

fseek возвращает 0 в случае успеха и -1 в случае ошибки.

3

Используйте функцию PHP stream_get_meta_data() чтобы узнать, доступен ли открываемый вами поток:

$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)`

Поток не доступен для поиска. Это означает, что функции fseek(), ftell() а также rewind() иметь неожиданное (и, вероятно, противоречивое) поведение.

3
По вопросам рекламы [email protected]