有没有办法在PHP中访问字符串作为文件句柄?

时间:2010-02-16 21:50:41

标签: php csv filehandle

我在服务器上,我只限于PHP 5.2.6,这意味着我无法使用str_getcsv。我正在使用,而不是fgetcsv,它需要“一个有效的文件指针,指向由fopen(),popen()或fsockopen()成功打开的文件。”继续经营。

我的问题是:有没有办法将字符串作为文件句柄访问?

我的另一个选择是将字符串写入文本文件,然后通过fopen()访问它然后使用fgetcsv,但我希望有一种方法可以直接执行此操作,例如的Perl。

5 个答案:

答案 0 :(得分:20)

如果您查看str_getcsv手册页上的用户备注,您会找到this note from daniel,它会建议此功能(引用)

<?php
if (!function_exists('str_getcsv')) {
    function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") {
        $fiveMBs = 5 * 1024 * 1024;
        $fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+');
        fputs($fp, $input);
        rewind($fp);

        $data = fgetcsv($fp, 1000, $delimiter, $enclosure); //  $escape only got added in 5.3.0

        fclose($fp);
        return $data;
    }
}
?>

它似乎完全符合您的要求:它使用一个流,指向内存中的临时文件句柄,在其上使用fgetcsv


有关php://temp流包装器等的文档,请参阅PHP input/output streams


当然,你应该测试它对你有用 - 但是,至少,这应该让你知道如何实现这个目标; - )

答案 1 :(得分:7)

我很震惊没有人回答这个问题:

<?php

$string = "I tried, honestly!";
$fp     = fopen('data://text/plain,' . $string,'r');

echo stream_get_contents($fp);

#fputcsv($fp, .......);

?>

内存饥渴的完美解决方案:

<?php

class StringStream
{
    private   $Variable = NULL;
    protected $fp       = 0;

    final public function __construct(&$String, $Mode = 'r')
    {
        $this->$Variable = &$String;

        switch($Mode)
        {
            case 'r':
            case 'r+':
                $this->fp = fopen('php://memory','r+');
                fwrite($this->fp, @strval($String));
                rewind($this->fp);
                break;

            case 'a':
            case 'a+':
                $this->fp = fopen('php://memory','r+');
                fwrite($this->fp, @strval($String));
                break;

            default:
                $this->fp = fopen('php://memory',$Mode);
        }
    }

    final public function flush()
    {
        # Update variable
        $this->Variable = stream_get_contents($this->fp);
    }

    final public function __destruct()
    {
        # Update variable on destruction;
        $this->Variable = stream_get_contents($this->fp);
    }

    public function __get($name)
    {
        switch($name)
        {
            case 'fp': return $fp;
            default:   trigger error('Undefined property: ('.$name.').');
        }

        return NULL;
    }
}

$string = 'Some bad-ass string';
$stream = new StringStream($string);

echo stream_get_contents($stream->fp);
#fputcsv($stream->fp, .......);

&GT;

答案 2 :(得分:6)

要回答您的一般问题,是的,您可以将变量视为文件流。

http://www.php.net/manual/en/function.stream-context-create.php

以下是对PHP手册中的一些不同注释的复制和粘贴(因此我无法保证生产准备就绪):

<?php
class VariableStream {
    private $position;
    private $varname;
    public function stream_open($path, $mode, $options, &$opened_path) {
        $url = parse_url($path);
        $this->varname = $url["host"];
        $this->position = 0;
        return true;
    }
    public function stream_read($count) {
        $p=&$this->position;
        $ret = substr($GLOBALS[$this->varname], $p, $count);
        $p += strlen($ret);
        return $ret;
    }
    public function stream_write($data){
        $v=&$GLOBALS[$this->varname];
        $l=strlen($data);
        $p=&$this->position;
        $v = substr($v, 0, $p) . $data . substr($v, $p += $l);
        return $l;
    }
    public function stream_tell() {
        return $this->position;
    }
    public function stream_eof() {
        return $this->position >= strlen($GLOBALS[$this->varname]);
    }
    public function stream_seek($offset, $whence) {
        $l=strlen(&$GLOBALS[$this->varname]);
        $p=&$this->position;
        switch ($whence) {
            case SEEK_SET: $newPos = $offset; break;
            case SEEK_CUR: $newPos = $p + $offset; break;
            case SEEK_END: $newPos = $l + $offset; break;
            default: return false;
        }
        $ret = ($newPos >=0 && $newPos <=$l);
        if ($ret) $p=$newPos;
        return $ret;
    }
}

stream_wrapper_register("var", "VariableStream");
$csv = "foo,bar\ntest,1,2,3\n";

$row = 1;
if (($handle = fopen("var://csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}
?>

当然,对于您的特定示例,可以使用更简单的流方法。

答案 3 :(得分:0)

您可以使用php://memory之类的流句柄来实现您所追求的目标。只需打开,fwrite,倒带,你应该可以使用fgetcsv。

答案 4 :(得分:-3)

不幸的是,这是不可能的。您不能将字符串视为来自文件的流。您确实必须先将字符串写入文件,然后使用fopen打开所述文件。

现在,显而易见的是,你考虑升级吗?