2010-02-16 65 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, .......); 

>

相關問題