stream = $stream; $metaData = $this->metaData(); $this->canRead = in_array($metaData['mode'], self::READABLE); $this->canWrite = in_array($metaData['mode'], self::WRITEABLE); $this->canSeek = $metaData['seekable']; } public function getResource() { return $this->stream; } private function stat(): array { return fstat($this->stream); } public function getPosition(): int { return ftell($this->stream); } public function getLength(): int { if(!$this->canSeek()) return -1; return $this->stat()['size']; } public function setLength(int $length): void { ftruncate($this->stream, $length); } private function metaData(): array { return stream_get_meta_data($this->stream); } public function canRead(): bool { return $this->canRead; } public function canWrite(): bool { return $this->canWrite; } public function canSeek(): bool { return $this->canSeek; } public function hasTimedOut(): bool { return $this->metaData()['timed_out']; } public function isBlocking(): bool { return $this->metaData()['blocked']; } public function isEnded(): bool { return feof($this->stream); } public function readChar(): ?string { $char = fgetc($this->stream); if($char === false) return null; return $char; } public function readLine(): ?string { return ($line = fgets($this->stream)) === false ? null : $line; } public function read(int $length): ?string { $buffer = fread($this->stream, $length); if($buffer === false) return null; return $buffer; } public function seek(int $offset, int $origin = Stream::START): int { return fseek($this->stream, $offset, $origin); } public function write(string $buffer, int $length = -1): void { if($length >= 0) fwrite($this->stream, $buffer, $length); else fwrite($this->stream, $buffer); } public function writeChar(string $char): void { fwrite($this->stream, $char, 1); } public function flush(): void { fflush($this->stream); } public function close(): void { try { fclose($this->stream); } catch(\Error $ex) {} } public function copyTo(Stream $other): void { if($other instanceof GenericStream) { stream_copy_to_stream($this->stream, $other->stream); } else parent::copyTo($other); } public function __toString(): string { return stream_get_contents($this->stream); } }