使用phar流写入PharData文件



当我尝试这个时:

$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
file_put_contents('phar://./phar.tar/test/foo.txt', 'bar');

我得到以下错误:

警告:file_put_contents(phar://./phar.tar/test/foo.txt): failed to .打开流:无法创建phar './phar.tar',文件扩展名(或组合)无法识别或目录不存在

我能够使用file_get_contents,但不应该file_put_contents工作了吗?


为了让事情更奇怪,我尝试了@hakre在他的评论中建议的想法,它有效!

$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
if (file_exists('./phar.phar') !== true)
{
    symlink('./phar.tar', './phar.phar');
}
file_put_contents('phar://./phar.phar/test/foo.txt', 'bar');
var_dump(file_get_contents('phar://./phar.tar/test/foo.txt')); // string(3) "bar"

介绍

我认为这基本上与您正在处理Phar::TAR文件有关,因为

file_put_contents("phar://./test.tar/foo.txt", "hello world");
                                  ^
                                  |+---- Note this tar

返回

警告:file_put_contents(phar://./test.tar/foo.txt): failed to open stream: Cannot create phar './test.tar',文件扩展名(或组合)不可识别或目录不存在

,

file_put_contents("phar://./test.phar/foo.txt", "hello world"); // Works file
                                  ^
                                  |+---- Note This phar

返回
//No Errors

知道问题

如果您查看PHP文档中的详细示例,就会发现这是过去2 years中已知的问题,给出的示例如下

例子
$p = new PharData(dirname(__FILE__) . '/phartest.zip', 0, 'phartest', Phar::ZIP);
$p->addFromString('testfile.txt', 'this is just some test text');
// This works
echo file_get_contents('phar://phartest.zip/testfile.txt');
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt');
$context = stream_context_create(array(
        'phar' => array(
                'compress' => Phar::ZIP
        )
));
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt', 0, $context);
// This works but only with 'r' readonly mode.
$f = fopen('phar://C:\Inetpub\wwwroot\PACT\test\phartest.zip\testfile.txt', 'r');
工作替代

不要使用.tar.zip有您的文件extension,但设置压缩在PHP DOC

我是什么意思?

$context = stream_context_create(array(
        'phar' => array(
                'compress' => Phar::GZ //set compression
        )
));
file_put_contents('phar://sample.phar/somefile.txt', "Sample Data", 0, $context);
                                   ^
                                   |= Use phar not tar

我真的认为你应该坚持PharData是可实现的,被证明是有效的。制作

的唯一方法

我必须使用file_put_contents

然后编写自己的包装器并将其注册为stream_wrapper_register,这里是一个简单的概念教授

stream_wrapper_register("alixphar", "AlixPhar");
file_put_contents('alixphar://phar.tar/test/foo.txt', 'hey'); 
                         ^
                         |+-- Write with alixphar
echo file_get_contents('alixphar://phar.tar/test/foo.txt'),PHP_EOL;
echo file_get_contents('phar://phar.tar/test/foo.txt'),PHP_EOL;

输出
hey     <----- alixphar
hey     <----- phar

注意:这个类不应该在生产环境中使用…它只是一个示例,可能会失败一些测试用例

class AlixPhar {
    private $pos;
    private $stream;
    private $types;
    private $dir;
    private $pharContainer, $pharType, $pharFile, $pharDir = null;
    private $fp;
    function __construct() {
        $this->types = array(
                "tar" => Phar::TAR,
                "zip" => Phar::ZIP,
                "phar" => Phar::PHAR
        );
        // your phar dir to help avoid using path before the phar file
        $this->dir = __DIR__;
    }
    private function parsePath($path) {
        $url = parse_url($path);
        $this->pharContainer = $url['host'];
        $this->pharType = $this->types[pathinfo($this->pharContainer, PATHINFO_EXTENSION)];
        if (strpos($url['path'], ".") !== false) {
            list($this->pharDir, $this->pharFile, , ) = array_values(pathinfo($url['path']));
        } else {
            $this->pharDir = $url['path'];
        }
    }
    public function stream_open($path, $mode, $options, &$opened_path) {
        $this->parsePath($path);
        $this->stream = new PharData($this->dir . "/" . $this->pharContainer, 0, null, $this->pharType);
        if (! empty($this->pharDir))
            $this->stream->addEmptyDir($this->pharDir);
        if ($mode == "rb") {
            $this->fp = fopen("phar://" . $this->pharContainer . "/" . $this->pharDir . "/" . $this->pharFile, $mode);
        }
        return true;
    }
    public function stream_write($data) {
        $this->pos += strlen($data);
        $this->stream->addFromString($this->pharDir . "/" . $this->pharFile, $data);
        return $this->pos;
    }
    public function stream_read($count) {
        return fread($this->fp, $count);
    }
    public function stream_tell() {
        return ftell($this->fp);
    }
    public function stream_eof() {
        return feof($this->fp);
    }
    public function stream_stat() {
        return fstat($this->fp);
    }
}

我有一些答案,希望能帮到你。

首先,对于file_put_contents(),我注意到一些奇怪之处。首先,我所做的是按照你发布的链接的例子。我能够添加$context变量,但仍然有错误。对我来说,将文件名更改为phar.phar效果很好。也许phar://处理程序无法理解.tar扩展名?

无论如何,这似乎是工作代码- ,但我不推荐它

$context = stream_context_create(array('phar' =>
                                array('compress' => Phar::GZ)),
                                array('metadata' => array('user' => 'cellog')));
file_put_contents('phar://./phar.phar/test/foo.txt', 'bar', 0, $context);

请使用this

使用我-我是推荐

$phar = new PharData('./phar.tar', 0, null, Phar::TAR);
$phar->addEmptyDir('test');
$phar->addFile('./bar', 'foo.txt');

如果你真的需要使用file_put_contents()代替,也许有一个不同的问题存在,也许我们可以帮助解决。谢谢,祝你好运!

我还有一些其他的方法,我认为它们更整洁。他们避免自定义包装器、符号链接或为了使用addFile函数而创建额外的文件。

选择

使用与file_put_contents类似的addFromString函数。下面的代码创建一个TAR归档文件,向其中添加一个文件并对其进行压缩。

$phar = new PharData("./archive.tar", 0, null, Phar::TAR);
$phar->addFromString('out/fileA.txt','The quick brown fox jumped over the lazy dog');
$phar->compress(Phar::GZ); # Creates archive.tar.gz

选项B

如果出于某种原因确实需要使用file_put_contents。您可以使用它创建PHAR归档,然后重新打开它并将其转换为另一种归档类型。

file_put_contents('phar://archive2.phar/out/fileB.txt', "Colourless green ideas sleep furiously");
$tarphar = new Phar('archive2.phar');
$tar = $tarphar->convertToData(Phar::TAR); # Creates archive2.tar
$zip = $tarphar->convertToData(Phar::ZIP); # Creates archive2.zip
$tgz = $tarphar->convertToData(Phar::TAR, Phar::GZ, '.tar.gz'); # Creates archive2.tar.gz

相关内容

  • 没有找到相关文章

最新更新