Подтвердить что ты не робот

Вывод ftll в 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

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

518264
1024
201024
202048
402048
403072

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

4b9b3361

Ответ 1

В соответствии с документацией PHP для fgets(),

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

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

  • Он прочитал байты 1023 из той же строки.
  • Он достиг конца текущей строки.
  • Он дошел до конца файла.

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

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

И снова вы начнете следующий fgets() из 58 байт, чтобы прочитать до (58 + 1024 =) 1082 байт. Он будет продолжать этот путь.

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

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

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

Ответ 2

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

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

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

Ответ 3

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

<сильные > fgets()

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

Возвращает строку длиной до 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 при ошибке.

Ответ 4

Используйте функцию 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() имеют неожиданное (и, вероятно, непоследовательное) поведение.