<?php class BufferedFileReader { private mixed $handle; private bool $temporary; private function __construct( mixed $handle, bool $temporary ) { $this->handle = $handle; $this->temporary = $temporary; } public static function open( string $path ): self { return new self( fopen( $path, 'rb' ), false ); } public static function createTemp(): self { return new self( tmpfile(), true ); } public function __destruct() { if( $this->isOpen() ) { fclose( $this->handle ); } } public function isOpen(): bool { return is_resource( $this->handle ); } public function read( int $length ): string { return $this->isOpen() && !feof( $this->handle ) ? (string)fread( $this->handle, $length ) : ''; } public function write( string $data ): bool { return $this->temporary && $this->isOpen() && fwrite( $this->handle, $data ) !== false; } public function seek( int $offset, int $whence = SEEK_SET ): bool { return $this->isOpen() && fseek( $this->handle, $offset, $whence ) === 0; } public function tell(): int { return $this->isOpen() ? (int)ftell( $this->handle ) : 0; } public function eof(): bool { return $this->isOpen() ? feof( $this->handle ) : true; } public function rewind(): void { if( $this->isOpen() ) { rewind( $this->handle ); } } }