diff --git a/src/main/php/io/streams/StreamTransfer.class.php b/src/main/php/io/streams/StreamTransfer.class.php index b2b8d03b7..6d5926265 100755 --- a/src/main/php/io/streams/StreamTransfer.class.php +++ b/src/main/php/io/streams/StreamTransfer.class.php @@ -41,21 +41,26 @@ public function __construct(InputStream $in, OutputStream $out) { public function transferAll() { $r= 0; while ($this->in->available()) { - $r+= $this->out->write($this->in->read()); + $chunk= $this->in->read(); + $this->out->write($chunk); + $r+= strlen($chunk); } return $r; } /** * Transmit all available input from in, yielding control after each chunk. + * Uses default chunk size of 8192 bytes. * + * @param int $size * @return iterable * @throws io.IOException */ - public function transmit() { + public function transmit($size= 8192) { while ($this->in->available()) { - $this->out->write($this->in->read()); - yield; + $chunk= $this->in->read($size); + $this->out->write($chunk); + yield strlen($chunk); } } @@ -71,15 +76,15 @@ public function close() { try { $this->in->close(); } catch (IOException $e) { - $errors.= 'Could not close input stream: '.$e->getMessage().', '; + $errors.= ', Could not close input stream: '.$e->getMessage(); } try { $this->out->close(); } catch (IOException $e) { - $errors.= 'Could not close output stream: '.$e->getMessage().', '; + $errors.= ', Could not close output stream: '.$e->getMessage(); } if ($errors) { - throw new IOException(rtrim($errors, ', ')); + throw new IOException(substr($errors, 2)); } } diff --git a/src/test/php/io/unittest/StreamTransferTest.class.php b/src/test/php/io/unittest/StreamTransferTest.class.php index 9ad36754e..b97a1c065 100755 --- a/src/test/php/io/unittest/StreamTransferTest.class.php +++ b/src/test/php/io/unittest/StreamTransferTest.class.php @@ -2,7 +2,7 @@ use io\IOException; use io\streams\{InputStream, MemoryInputStream, MemoryOutputStream, OutputStream, StreamTransfer}; -use test\{Assert, Test}; +use test\{Assert, Test, Values}; class StreamTransferTest { @@ -49,9 +49,10 @@ public function transfer_all() { $out= new MemoryOutputStream(); $s= new StreamTransfer(new MemoryInputStream('Hello'), $out); - $s->transferAll(); + $size= $s->transferAll(); Assert::equals('Hello', $out->bytes()); + Assert::equals(5, $size); } #[Test] @@ -64,6 +65,21 @@ public function transmit() { Assert::equals('Hello', $out->bytes()); } + #[Test, Values([[0, []], [1, [1]], [1024, [1024]], [1025, [1024, 1]], [2077, [1024, 1024, 29]]])] + public function transmit_chunks($length, $chunks) { + $out= new MemoryOutputStream(); + $data= str_repeat('*', $length); + + $s= new StreamTransfer(new MemoryInputStream($data), $out); + $transmitted= []; + foreach ($s->transmit(1024) as $yield) { + $transmitted[]= $yield; + } + + Assert::equals($data, $out->bytes()); + Assert::equals($chunks, $transmitted); + } + #[Test] public function nothing_available_after_transfer() { $in= new MemoryInputStream('Hello');