2010-02-16 16 views
9

Tôi đang ở trên một máy chủ mà tôi bị giới hạn ở PHP 5.2.6 có nghĩa là str_getcsv không có sẵn cho tôi. Tôi đang sử dụng, thay vào đó fgetcsv yêu cầu "Một con trỏ tệp hợp lệ cho một tệp được mở thành công bởi fopen(), popen() hoặc fsockopen()." để hoạt động.Có cách nào để truy cập chuỗi ký tự dưới dạng tệp bằng tay trong php không?

Câu hỏi của tôi là: có cách nào để truy cập chuỗi dưới dạng xử lý tệp không?

Tùy chọn khác của tôi là viết chuỗi ra tệp văn bản và sau đó truy cập thông qua fopen() và sau đó sử dụng fgetcsv, nhưng tôi hy vọng có cách để thực hiện việc này trực tiếp, như trong perl.

Trả lời

20

Nếu bạn có một cái nhìn trong các ghi chú của người dùng trên trang hướng dẫn cho str_getcsv, bạn sẽ tìm thấy this note from daniel, trong đó đề xuất chức năng này (trích dẫn):

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

Nó dường như được làm chính xác những gì bạn đã yêu cầu: nó sử dụng một luồng, trỏ đến một tập tin tạm thời trong bộ nhớ, để sử dụng fgetcsv trên đó.


Xem PHP input/output streams để biết tài liệu về, trong số những người khác, trình bao bọc luồng php://temp.


Tất nhiên, bạn nên kiểm tra rằng nó hoạt động OK cho bạn - nhưng, ít nhất, điều này sẽ cung cấp cho bạn một ý tưởng về làm thế nào để đạt được điều này ;-)

+1

Tôi sẽ upvote này hai lần nếu có thể - bạn luôn luôn có vẻ có chỗ trên câu trả lời. Tôi cần phải đọc ghi chú người dùng thường xuyên hơn. – Erik

+0

Cảm ơn :-) ;;; Những người sử dụng ghi chú khá thường xuyên mang lại một số thông tin thú vị :-) * (Vâng, nếu một trong những sử dụng có một vấn đề, rất có thể là ai đó đã có cùng một vấn đề trước ^^) * –

+0

Điều thú vị cần lưu ý, sau khi đọc một số , bạn chỉ có thể sử dụng 'php: // memory' - lợi thế duy nhất cho' php: // temp' là sau khi tệp vượt quá kích thước được chỉ định, nó sẽ ghi vào đĩa; nếu bạn ở dưới kích thước tệp đó, nó sẽ nằm hoàn toàn trong bộ nhớ. – Erik

-3

Thật không may, điều đó là không thể. Bạn không thể xử lý chuỗi như thể đó là luồng từ tệp. Bạn thực sự sẽ phải viết chuỗi đầu tiên vào một tập tin, và sau đó mở tập tin nói bằng cách sử dụng fopen.

Và bây giờ cho phần hiển nhiên, bạn đã cân nhắc nâng cấp chưa?

+0

máy chủ của khách hàng, chứ không phải máy chủ của tôi. Chia sẻ môi trường lưu trữ, yadda yadda yadda ... Tôi đang chạy phiên bản mới nhất trên hộp MY, ofc. – Erik

+1

Thậm chí không có luồng? http: //www.php.net/suối – Franz

+0

:) Không biết về những người, nhờ liên kết! Tôi cho rằng bạn học một cái gì đó mới mỗi ngày. Rõ ràng mặc dù nâng cấp vẫn sẽ là giải pháp tốt nhất. – Aistina

0

Bạn có thể sử dụng tay cầm suối chẳng hạn như php://memory để đạt được những gì bạn đang theo dõi. Chỉ cần mở, fwrite, rewind, và bạn sẽ có thể sử dụng fgetcsv.

6

Để trả lời câu hỏi chung của bạn, có bạn có thể coi biến là luồng tệp.

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

Sau đây là một sao chép và dán từ một vài ý kiến ​​khác nhau về hướng dẫn PHP (vì vậy tôi không thể xác minh cho cách sản xuất sẵn sàng nó là):

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

Tất nhiên, đối với bạn ví dụ cụ thể, có các phương thức luồng đơn giản hơn có thể được sử dụng.

+0

Câu trả lời hay và kỹ thuật là giải pháp sạch nhất. Viết vào một tập tin đầu tiên có vẻ sai! –

+0

Thật không may bạn sẽ phải sử dụng một biến toàn cầu. tại sao bạn không sử dụng ngữ cảnh để thêm khả năng sử dụng bất kỳ biến nào không chỉ là các hình cầu. – mAsT3RpEE

6

Tôi sợ hãi mà chưa ai trả lời giải pháp này:

<?php 

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

echo stream_get_contents($fp); 

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

?> 

Và nhớ đói giải pháp hoàn hảo:

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

>

Các vấn đề liên quan