Общий файл памяти в PHP

Я использую openssl_pkcs7_sign и openssl_pkcs7_encrypt для создания зашифрованных данных. Функции принимают только имена файлов. Я хотел бы сохранить временные файлы в общей памяти для повышения производительности. Я понимаю, что в Linux я могу file_put_contents('/dev/shm/xxx', data) , но это невозможно для Windows. Есть ли в PHP способ переноса? shmop_ ли функция shmop_ ? Благодарю.

PS: Или есть способ заставить эти функции принимать строки данных?

PS2: Пожалуйста, не предлагайте вызывать /usr/bin/openssl из PHP. Он не переносится.

Начиная с Windows 2000 доступны методы shmop (ранее shm_ ).

shmop_open использует уникальный целочисленный ключ для совместного использования области памяти. ftok можно использовать для создания уникального индекса на основе пути к файлу (обычно полный путь к файлу вашего скрипта). Любой экземпляр, который имеет один и тот же ключ, может использовать одну и ту же память.

http://php.net/manual/en/ref.shmop.php

Протестировано на PHP версии 5.3.3 от Zend Server CE System Windows NT CRYPE 6.1 build 7601 (Unknow Windows версия Business Edition с пакетом обновления 1) i586

 <?php $key = ftok(__FILE__, 't'); $memory = shmop_open($key, "c", 0600, 16 * 1024); $data = array('data' => 'value'); $bytes = shmop_write($memory, serialize($data), 0); $return = shmop_read($memory, 0, $bytes); print_r(unserialize($return)); ?> 

shmop_read / shmop_write хранит необработанные байты из строки, поэтому вам не нужно сериализовать его, но вам нужно будет написать длину строки где-нибудь. В моем примере создается область общей памяти 16 КБ, вы можете, конечно, ее размер, чтобы соответствовать файлу openssl, а также пространство, необходимое для хранения размера файла.

Хорошо, так что я бы предложил сделать это с оберткой файлового потока . Позвольте мне взломать быстрый пример:

 class staticStreamWrapper { public $context; protected static $data = array(); protected $path = ''; protected $pointer = 0; protected $writable = false; public function stream_close() {} public function stream_eof() { return $this->pointer >= strlen(static::$data[$this->path]); } public function stream_flush() {} public function stream_open($path, $mode, $options, &$opened_path) { switch ($mode[0]) { case 'r': if (!isset(static::$data[$path])) return false; $this->path = $path; $this->writable = isset($mode[1]) && $mode[1] == '+'; break; case 'w': static::$data[$path] = ''; $this->path = $path; $this->writable = true; break; case 'a': if (!isset(static::$data[$path])) static::$data[$path] = ''; $this->path = $path; $this->writable = true; $this->pointer = strlen(static::$data[$path]); break; case 'x': if (isset(static::$data[$path])) return false; $this->path = $path; $this->writable = true; break; case 'c': if (!isset(static::$data[$path])) static::$data[$path] = ''; $this->path = $path; $this->writable = true; break; default: return false; } $opened_path = $this->path; return true; } public function stream_read($count) { $bytes = min(strlen(static::$data[$this->path]) - $this->pointer, $count); $data = substr(static::$data[$this->path], $this->pointer, $bytes); $this->pointer += $bytes; return $data; } public function stream_seek($offset, $whence = SEEK_SET) { $len = strlen(static::$data[$this->path]); switch ($whence) { case SEEK_SET: if ($offset <= $len) { $this->pointer = $offset; return true; } break; case SEEK_CUR: if ($this->pointer + $offset <= $len) { $this->pointer += $offset; return true; } break; case SEEK_END: if ($len + $offset <= $len) { $this->pointer = $len + $offset; return true; } break; } return false; } public function stream_stat() { $size = strlen(static::$data[$this->path]); $time = time(); return array( 0 => 0, 'dev' => 0, 1 => 0, 'ino' => 0, 2 => 0777, 'mode' => 0777, 3 => 1, 'nlink' => 1, 4 => 0, 'uid' => 0, 5 => 0, 'gid' => 0, 6 => '', 'rdev' => '', 7 => $size, 'size' => $size, 8 => $time, 'atime' => $time, 9 => $time, 'mtime' => $time, 10 => $time, 'ctime' => $time, 11 => -1, 'blksize' => -1, 12 => -1, 'blocks' => -1, ); } public function stream_tell() { return $this->pointer; } public function stream_write($data) { if (!$this->writable) return 0; $size = strlen($data); $len = strlen(static::$data[$this->path]); if ($this->stream_eof()) { static::$data[$this->path] .= $data; } else { static::$data[$this->path] = substr_replace( static::$data[$this->path], $data, $this->pointer ); } $this->pointer += $size; return $size; } public function unlink($path) { if (isset(static::$data[$path])) { unset(static::$data[$path]); } return true; } } с class staticStreamWrapper { public $context; protected static $data = array(); protected $path = ''; protected $pointer = 0; protected $writable = false; public function stream_close() {} public function stream_eof() { return $this->pointer >= strlen(static::$data[$this->path]); } public function stream_flush() {} public function stream_open($path, $mode, $options, &$opened_path) { switch ($mode[0]) { case 'r': if (!isset(static::$data[$path])) return false; $this->path = $path; $this->writable = isset($mode[1]) && $mode[1] == '+'; break; case 'w': static::$data[$path] = ''; $this->path = $path; $this->writable = true; break; case 'a': if (!isset(static::$data[$path])) static::$data[$path] = ''; $this->path = $path; $this->writable = true; $this->pointer = strlen(static::$data[$path]); break; case 'x': if (isset(static::$data[$path])) return false; $this->path = $path; $this->writable = true; break; case 'c': if (!isset(static::$data[$path])) static::$data[$path] = ''; $this->path = $path; $this->writable = true; break; default: return false; } $opened_path = $this->path; return true; } public function stream_read($count) { $bytes = min(strlen(static::$data[$this->path]) - $this->pointer, $count); $data = substr(static::$data[$this->path], $this->pointer, $bytes); $this->pointer += $bytes; return $data; } public function stream_seek($offset, $whence = SEEK_SET) { $len = strlen(static::$data[$this->path]); switch ($whence) { case SEEK_SET: if ($offset <= $len) { $this->pointer = $offset; return true; } break; case SEEK_CUR: if ($this->pointer + $offset <= $len) { $this->pointer += $offset; return true; } break; case SEEK_END: if ($len + $offset <= $len) { $this->pointer = $len + $offset; return true; } break; } return false; } public function stream_stat() { $size = strlen(static::$data[$this->path]); $time = time(); return array( 0 => 0, 'dev' => 0, 1 => 0, 'ino' => 0, 2 => 0777, 'mode' => 0777, 3 => 1, 'nlink' => 1, 4 => 0, 'uid' => 0, 5 => 0, 'gid' => 0, 6 => '', 'rdev' => '', 7 => $size, 'size' => $size, 8 => $time, 'atime' => $time, 9 => $time, 'mtime' => $time, 10 => $time, 'ctime' => $time, 11 => -1, 'blksize' => -1, 12 => -1, 'blocks' => -1, ); } public function stream_tell() { return $this->pointer; } public function stream_write($data) { if (!$this->writable) return 0; $size = strlen($data); $len = strlen(static::$data[$this->path]); if ($this->stream_eof()) { static::$data[$this->path] .= $data; } else { static::$data[$this->path] = substr_replace( static::$data[$this->path], $data, $this->pointer ); } $this->pointer += $size; return $size; } public function unlink($path) { if (isset(static::$data[$path])) { unset(static::$data[$path]); } return true; } } 

Теперь вам нужно будет зарегистрировать обертку:

 stream_wrapper_register('static', 'staticStreamWrapper'); 

Таким образом, теперь вы можете рассматривать его как файл, даже если он никогда не оставляет PHP (он хранится как статическая переменная)!

 file_put_contents('static://foo.txt', 'this is my data'); file_get_contents('static://foo.txt'); // "this is my data" $f = fopen('static://foo.txt', 'r'); // should return a resource // etc...