• file_get_contents()のラッパーを作ろうとしてmaxlenをどうするか悩んだのでそれのメモ

file_get_contentsのパラメータ

  • マニュアル抜粋
  • maxlen省略時のデフォルト値が書いてない
string file_get_contents ( string $filename [, bool $use_include_path = false [, resource $context [, int $offset = -1 [, int $maxlen ]]]] )
maxlen

  読み込むデータの最大バイト数。 デフォルトは、ファイル終端に達するまで読み込みます。 
このパラメータは、フィルタが処理した後のストリームに適用されることに注意しましょう。

PHPのソースを確認

/* {{{ proto string file_get_contents(string filename [, bool use_include_path [, resource context [, long offset [, long maxlen]]]])
   Read the entire file into a string */
PHP_FUNCTION(file_get_contents)
{
 :
    long maxlen = PHP_STREAM_COPY_ALL;
 :
    if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
        RETURN_FALSE;
    }
 :
    if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
        RETVAL_STRINGL(contents, len, 0);
    } else if (len == 0) {
        RETVAL_EMPTY_STRING();
    } else {
        RETVAL_FALSE;
    }

    php_stream_close(stream);
}
  • デフォルト値としてPHP_STREAM_COPY_ALLが設定されている
#define PHP_STREAM_COPY_ALL          ((size_t)-1)
  • (size_t)-1 の値を調べる
  • 確認ソース
#include <stdio.h>
#define PHP_STREAM_COPY_ALL          ((size_t)-1)

int main() {
        printf("%d\n", PHP_STREAM_COPY_ALL);
        printf("%u\n", PHP_STREAM_COPY_ALL);
}
  • 結果
-1
4294967295

PHPで4294967295を渡せるか

  • 確認ソース
<?php
ini_set('display_errors', '1');
ini_set('error_log', '');
error_reporting(E_ALL);

var_dump(file_get_contents('/homepage/php/utf8.php',false,null,0,4294967295));
var_dump(PHP_INT_MAX);
var_dump((int)4294967295);
  • 結果。PHP_INT_MAXを越えているので無理か
Warning: file_get_contents(): length must be greater than or equal to zero in - on line 6
bool(false)
int(2147483647)
int(-1)

結論

  • 独自のデフォルト値を持って処理する
  • $contextのデフォルト値はnull
  • 作りたかった関数
<?php

/**
 * 複数ファイル名を指定して最初に読み込んだファイルの内容を返すfile_get_contents()の拡張
 *
 * @param mixed    $filename         データを読み込みたいファイルの名前。複数の場合は配列
 * @param bool     $use_include_path インクルードパスから探す(true|FILE_USE_INCLUDE_PATH)
 * @param resource $context          stream_context_create()で作成したコンテキストリソース
 * @param int      $offset           読み込みを開始するオフセット位置
 * @param int      $maxlen           読み込むデータの最大バイト数。 デフォルトはファイル終端まで
 *
 * @return string 読み込んだデータ。失敗した場合はFALSE
 */
function file_get_contents_ex($filename, $use_include_path = false, $context = null, $offset = -1, $maxlen = null)
{
    $files = is_array($filename) ? $filename : array($filename);
    $res = false;
    foreach ($files as $f) {
        if ($maxlen === null) {
            $res = @file_get_contents($f, $use_include_path, $context, $offset);
        } else {
            $res = @file_get_contents($f, $use_include_path, $context, $offset, $maxlen);
        }
        if ($res !== false) {
            break;
        }
    }
    return $res;
}

  • Prev
  • Next