Writing
Determine if Writable
The isWritable()
determines if a stream is writable or not.
$a = FileStream::open('people.txt', 'r+b');
$b = FileStream::open('contacts.txt', 'rb');
echo $a->isWritable(); // true
echo $b->isWritable(); // false
Write
Use the write()
method to write data to the stream.
The method returns amount of bytes written to the stream.
$stream = FileStream::openTemporary();
$bytes = $stream->write('abc');
echo $bytes; // 3
Behind the scene, PHP's fwrite()
is used for writing data to the stream.
Write Formatted
If you want to write data using a specific format, then you can use the writeFormatted()
method.
The method accepts a $format
argument, as specified by PHP's fprintf()
, and an arbitrary amount of values.
Similar to write()
, this method also returns the amount of bytes written to the stream.
$stream = FileStream::openTemporary();
$greetings = 'Hi there';
$name = 'John';
$bytes = $stream->writeFormatted('%s <<%s>>', $greetings, $name);
echo $bytes; // 16
echo (string) $stream; // Hi there <<John>>
Put
Alternatively, you can use the put()
method to write data to a stream. This method is a "fluent" version of write()
.
$stream = FileStream::openTemporary()
->put('a')
->put('b')
->put('c');
echo (string) $stream; // abc
Put Formatted
putFormatted()
is a "fluent" version of the writeFormatted()
method.
$stream = FileStream::openTemporary();
$a = 'Hi there';
$b = 'John';
$c = 'Smith'
$stream
->putFormatted('%s ', $a)
->putFormatted('<<%s ', $b)
->putFormatted('%s>>', $c);
echo (string) $stream; // Hi there <<John Smith>>
Append
The append()
method is able to add data, at the end of the stream, if the stream is seekable. If the stream is not seekable, then a StreamNotSeekable
exception will be thrown.
The method accepts four arguments:
$data
: Data to be appended.int|null $length
: (optional) Maximum bytes to append. By default, all bytes left in$data
are appended.int $offset
: (optional) The offset where to start to copy data (offset on$data
).int|null $maximumMemory
: (optional) Maximum amount of bytes, before writing to a temporary file. (Defaults to 2 MB if not specified).
The $maximumMemory
argument is relevant when $data
is a pure string, or numeric. If that is the case, then the append()
method will wrap the $data
into a "temporary" stream internally, before reading from it.
$stream = FileStream::open('people.txt', 'r+b')
->append("\nJohn");
Behind the scene, PHP's stream_copy_to_stream()
is used to append.
Append Resource
To append data from a resource, pass in the resource as the $data
argument.
$resource = fopen('contacts.txt', 'r');
$stream = FileStream::open('people.txt', 'r+b')
->append($resource);
Append Stream
You may also append directly from another stream.
$from = FileStream::open('contacts.txt', 'r');
$stream = FileStream::open('people.txt', 'r+b')
->append($from);
Caution
When pure PSR-7 StreamInterface
is appended
If you choose to append from pure "PSR stream" (a stream that inherits from StreamInterface
, but not from \Aedart\Contracts\Streams\Stream
), then the given "data" stream is automatically detached.
$stream = FileStream::open('people.txt', 'r+b')
->append($psrStream);
// Attempt using "psr stream" after it was appended...
$psrStream->rewind(); // Invalid - Exception is thrown
The reason for this behavior is due to the limitation of PSR-7's defined StreamInterface
. There is no safe way to obtain a reference to the underlying resource, without detaching it. PHP's native stream_copy_to_stream()
can therefore not be applied.
Workaround
See copyFrom()
.
Copy
In situations when you wish to copy the stream, then you can use the copy()
method.
This method will create a new "temporary" stream via openTemporary()
.
It accepts optional $length
and $offset
as arguments.
$stream = FileStream::open('my-file.txt', 'r+b')
->put('abc')
->positionToStart();
$copyA = $stream->copy();
$copyB = $stream
->positionToStart()
->copy(1, 1);
echo $copyA; // abc
echo $copyB; // b
Note
The initial stream's position is affected by the copy()
method.
Behind the scene, PHP's stream_copy_to_stream()
is used for the copy operation.
Copy To Target
If you wish to copy a stream into a specific target stream, then use the copyTo()
method.
It accepts a $target
stream, $length
and $offset
as optional arguments.
$stream = FileStream::open('my-file.txt', 'r+b')
->put('abc')
->positionToStart();
$target = FileStream::open('target.txt', 'r+b');
$copy = $stream->copyTo($target, 1, 1);
echo ($copy === $target); // true
echo (string) $copy; // b
Copy From
Available since v7.4.x
Alternatively, you may also copy data from an existing resource or stream.
$target = FileStream::openMemory()
->copyFrom($existing);
Similar to the copyTo()
method, this method accepts a $source
stream, a $length
and an $offset
argument.
The $source
argument accepts the following types:
resource
\Aedart\Contracts\Streams\Stream
\Psr\Http\Message\StreamInterface