2010-02-16 112 views
9

我在一台服务器上,我只限于PHP 5.2.6,这意味着str_getcsv不可用。我正在使用,而不是fgetcsv,它需要“有效的文件指针指向由fopen(),popen()或fsockopen()成功打开的文件。”操作。有没有办法在php中作为文件句柄来访问字符串?

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

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

回答

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

如果可以的话,我会赞成这两次 - 你似乎总是有答案。我需要更频繁地阅读用户笔记。 – Erik 2010-02-16 22:05:09

+0

谢谢:-) ;;;用户注释经常会带来一些有趣的信息:-) *(好吧,如果其中一个使用有问题,可能是其他人在^^之前就已经有了同样的问题)* – 2010-02-16 22:12:39

+0

有趣的是,在做了一些阅读之后,你可以使用'php:// memory' - 对'php:// temp'唯一的好处是在文件超过指定大小后,它会写入光盘;如果你在这个文件大小下,它完全保留在内存中。 – Erik 2010-02-16 23:34:32

-3

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

而现在明显的部分,你有没有考虑升级?

+0

客户端的服务器,而不是我的服务器。共享主机环境,yadda yadda yadda ...我正在运行MY box上的最新版本,ofc。 – Erik 2010-02-16 21:55:02

+1

甚至没有流? HTTP://www.php。网络/流 – Franz 2010-02-16 21:58:20

+0

:)不知道这些,谢谢你的链接!我想你每天都会学到新的东西。显然,升级仍然是最好的解决方案。 – Aistina 2010-02-16 22:30:38

0

可以使用流控的想法例如php://memory以实现您的目标。只需打开,fwrite,倒带,你应该可以使用fgetcsv。

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); 
} 
?> 

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

+0

很好的答案,技术上最干净的解决方案。首先写入文件似乎是错误的! – 2010-02-16 22:41:22

+0

不幸的是,你将不得不使用一个全局变量。为什么不使用上下文来添加使用任何变量而不仅仅是全局变量的能力。 – mAsT3RpEE 2014-01-30 06:59:53

6

我吓坏了,没有人回答了这个解决方案:

<?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, .......); 

>

相关问题