Есть ли способ доступа к строке в качестве дескриптора файла в php?

Я на сервере, где я ограничен PHP 5.2.6, что означает, что str_getcsv недоступен для меня. Я использую вместо fgetcsv, который требует «Правильный указатель на файл, успешно открытый fopen (), popen () или fsockopen ()." для работы.

Мой вопрос заключается в следующем: существует ли способ доступа к строке в качестве дескриптора файла?

Другой вариант – записать строку в текстовый файл, а затем получить доступ к ней через fopen() а затем использовать fgetcsv , но я надеюсь, что есть способ сделать это напрямую, как в perl.

Если вы посмотрите в примечаниях пользователя на странице руководства для str_getcsv , вы найдете эту заметку от 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 для документации, в частности, об обертке php://temp stream.

Конечно, вы должны проверить, что он работает нормально для вас – но, по крайней мере, это должно дать вам представление о том, как достичь этого 😉

Чтобы ответить на ваш общий вопрос, да, вы можете обрабатывать переменную как поток файлов.

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

Конечно, для вашего конкретного примера существуют более простые методы потока, которые можно использовать.

Я в ужасе, что никто не ответил на это решение:

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

?>

Вы можете использовать ручки потока, такие как память php: //, чтобы добиться того, что вам нужно. Просто откройте, перемотайте, перемотайте, и вы сможете использовать fgetcsv.

К сожалению, это невозможно. Вы не можете обрабатывать строку, как будто это поток из файла. Вы действительно должны сначала записать строку в файл, а затем открыть файл, используя fopen .

И теперь для очевидной части вы рассмотрели вопрос о модернизации?