如何创建虚假/“虚拟”文件?

时间:2016-05-31 19:16:14

标签: php stream filestream

我试图在不使用内存或临时文件的情况下创建“虚拟”文件。 “虚拟”文件需要通过file_exists()检查,同时与requireinclude一起使用时不会出现任何错误或警告。

  

允许您实施自己的协议处理程序和流,以便与all the other filesystem functions一起使用(例如fopen()fread()等。)

...其中file_exists()就是其中之一。 The docs page州:

  

从PHP 5.0.0开始,此函数也可以与某些URL包装器一起使用。请参阅Supported Protocols and Wrappers以确定哪些包装器支持stat()系列功能。

我的尝试是构建一个自定义的虚拟文件包装器

class VirtualFileWrapper
{
    public $context;

    public function stream_open( $path, $mode, $options, &$opened_path )
    {
        return TRUE;
    }

    public function stream_stat()
    {
        var_dump( __METHOD__ );
        $data = [
            'dev'     => 0,
            'ino'     => getmyinode(),
            'mode'    => 'r',
            'nlink'   => 0,
            'uid'     => getmyuid(),
            'gid'     => getmygid(),
            'rdev'    => 0,
            'size'    => 0,
            'atime'   => time(),
            'mtime'   => getlastmod(),
            'ctime'   => FALSE,
            'blksize' => 0,
            'blocks'  => 0,
        ];
        return array_merge( array_values( $data ), $data );
    }
}

stream_wrapper_register( 'virtual', 'VirtualFileWrapper' );

$file = fopen( "virtual://foo", 'r+' );

// Executes VirtualFileWrapper::stream_stat()
fstat( $file );

// Executes no VirtualFileWrapper method
file_exists( $file );

fstat()函数执行该方法时,file_exists()不执行任何流类方法。

如何让虚拟流包装器工作(使用file_exists())?

我完全清楚tempnam( __DIR__, '' )将通过两者:

  • var_dump( tempnam( __DIR__, '' ) );返回true
  • require tempnam( __DIR__, '' );没有错误

但我不想使用临时文件,因为可能有更好的方法(性能明智)。

1 个答案:

答案 0 :(得分:5)

您似乎只需在url_stat()上实施公开VirtualFileWrapper方法,即可通过file_exists()支票。

要隐藏includerequire的警告和错误,您必须实施stream_read()stream_eof()方法:

class VirtualFileWrapper
{
    public $context;

    public function stream_open( $path, $mode, $options, &$opened_path )
    {
        return TRUE;
    }

    public function stream_stat()
    {
        var_dump( __METHOD__ );
        return [];
    }

    public function url_stat()
    {
        return array (
          0 => 0,
          1 => 0,
          2 => 0,
          3 => 0,
          4 => 0,
          5 => 0,
          6 => 0,
          7 => 0,
          8 => 0,
          9 => 0,
          10 => 0,
          11 => 0,
          12 => 0,
          'dev' => 0,
          'ino' => 0,
          'mode' => 0,
          'nlink' => 0,
          'uid' => 0,
          'gid' => 0,
          'rdev' => 0,
          'size' => 0,
          'atime' => 0,
          'mtime' => 0,
          'ctime' => 0,
          'blksize' => 0,
          'blocks' => 0
        );
    }

    public function stream_read(){
        return '';
    }

    public function stream_eof(){
        return '';
    }

}

stream_wrapper_register( 'virtual', 'VirtualFileWrapper' );

$file = fopen( "virtual://foo", 'r+' );

// Executes VirtualFileWrapper::stream_stat()
fstat( $file );

// Executes no VirtualFileWrapper method
file_exists("virtual://foo");

//Still no errors :-)!
require "virtual://foo";
include "virtual://foo";

注意传递file_exists()字符串,而不是您使用fopen()创建的资源。