2010-02-16 7 views
9

Jestem na serwerze, gdzie jestem ograniczony do PHP 5.2.6, co oznacza, że ​​str_getcsv nie jest dla mnie dostępna. Używam, zamiast fgetcsv, który wymaga "Prawidłowy wskaźnik pliku do pliku pomyślnie otwarty przez fopen(), popen() lub fsockopen()." działać dalej.Czy istnieje sposób dostępu do ciąg znaków jako filehandle w php?

Moje pytanie brzmi: czy istnieje sposób dostępu do ciągu znaków jako uchwytu pliku?

Moja druga opcja to napisanie łańcucha do pliku tekstowego, a następnie dostęp do niego przez fopen(), a następnie użycie fgetcsv, ale mam nadzieję, że jest sposób na zrobienie tego bezpośrednio, jak w Perlu.

Odpowiedz

20

Jeśli spojrzeć w uwagach użytkowników na stronie podręcznika dla str_getcsv znajdziesz this note from daniel, która proponuje tę funkcję (cytując):

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

Wydaje się, że robi dokładnie to, co o które prosiłeś: używa strumienia, który wskazuje na tymczasową uchwyt pliku w pamięci, aby użyć na nim fgetcsv.


Zobacz dokumentację dotyczącą między innymi otoki strumieniowej .


Oczywiście, należy sprawdzić, czy to działa OK dla ciebie - ale przynajmniej powinno to daje wyobrażenie o tym, jak to osiągnąć ;-)

+1

Zrobiłbym to dwa razy, gdyby mógł - zawsze wydajesz się mieć miejsce na odpowiedzi. Muszę częściej czytać notatki użytkownika. – Erik

+0

Dzięki :-) ;;; Notatki użytkowników dość często dostarczają ciekawych informacji :-) * (Cóż, jeśli jeden z nich ma problem, prawdopodobnie ktoś wcześniej już miał ten sam problem ^^) * –

+0

Warto zauważyć, po przeczytaniu , możesz po prostu użyć 'php: // memory' - jedyną zaletą' php: // temp' jest, gdy plik przekroczy określony rozmiar, zapisze się na dysku; jeśli masz mniejszy rozmiar pliku, pozostaje on całkowicie w pamięci. – Erik

-3

Niestety, to nie jest możliwe. Nie możesz traktować łańcucha tak, jakby był strumieniem z pliku. Musiałbyś najpierw napisać ciąg do pliku, a następnie otworzyć ten plik, używając fopen.

A teraz dla oczywistej części, czy rozważałeś ulepszenie?

+0

klient-serwer, a nie mój serwer. Współdzielone środowisko hostingowe, yadda yadda yadda ... Używam najnowszej wersji na MY box, ofc. – Erik

+1

Nawet w przypadku strumieni? http: //www.php.net/streams – Franz

+0

:) Nie wiedziałem o tym, dziękuję za link! Przypuszczam, że każdego dnia uczysz się czegoś nowego. Oczywiście modernizacja nadal będzie najlepszym rozwiązaniem. – Aistina

0

można użyć uchwytów strumieniowych na przykład php://memory, aby osiągnąć to, czego szukasz. Po prostu otwórz, zapisz, przewiń i powinieneś móc używać fgetcsv.

6

Aby odpowiedzieć na ogólne pytanie, tak można traktować zmienną jako strumień plików.

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

Poniżej znajduje się kopiowania i wklejania z kilku różnych uwag dotyczących podręcznika PHP (więc nie mogę wypowiedzieć się, jak gotowa produkcja jest):

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

oczywiście na swój szczególny przykład, istnieją prostsze metody strumieniowania, które można wykorzystać.

+0

Dobra odpowiedź, a technicznie najczystsze rozwiązanie. Zapisywanie do pliku po prostu wydaje się błędne! –

+0

Niestety będziesz musiał użyć zmiennej globalnej. dlaczego nie użyjesz kontekstu, aby dodać możliwość użycia dowolnej zmiennej, nie tylko globalnej. – mAsT3RpEE

6

Jestem przerażona, że ​​nikt nie odpowiedział na to rozwiązanie:

<?php 

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

echo stream_get_contents($fp); 

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

?> 

i pamięć głodny idealne rozwiązanie:

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

>