PHPackages                             stubbles/streams - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. stubbles/streams

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

stubbles/streams
================

Input- and OutputStreams.

v11.0.0(5mo ago)03.8k1[2 issues](https://github.com/stubbles/stubbles-streams/issues)[1 PRs](https://github.com/stubbles/stubbles-streams/pulls)3BSD-3-ClausePHPPHP ^8.3CI passing

Since Jan 11Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/stubbles/stubbles-streams)[ Packagist](https://packagist.org/packages/stubbles/streams)[ Docs](http://stubbles.net/)[ RSS](/packages/stubbles-streams/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (7)Dependencies (6)Versions (8)Used By (3)

stubbles/streams
================

[](#stubblesstreams)

Input- and OutputStreams.

Build status
------------

[](#build-status)

[![Tests](https://github.com/stubbles/stubbles-streams/workflows/Tests/badge.svg)](https://github.com/stubbles/stubbles-streams/workflows/Tests/badge.svg)

[![Latest Stable Version](https://camo.githubusercontent.com/36906e389d53821a8cd5eddd8c7c2d2d205ed2f331ebcfdb76898ccbf03741e2/68747470733a2f2f706f7365722e707567782e6f72672f73747562626c65732f73747265616d732f76657273696f6e2e706e67)](https://packagist.org/packages/stubbles/streams) [![Latest Unstable Version](https://camo.githubusercontent.com/9a47596cb1fe5ca068071385526b24183512411d4b827828579e71977f984d19/68747470733a2f2f706f7365722e707567782e6f72672f73747562626c65732f73747265616d732f762f756e737461626c652e706e67)](//packagist.org/packages/stubbles/streams)

Installation
------------

[](#installation)

*stubbles/streams* is distributed as [Composer](https://getcomposer.org/)package. To install it as a dependency of your package use the following command:

```
composer require "stubbles/streams": "^11.0"

```

Requirements
------------

[](#requirements)

*stubbles/streams* requires at least PHP 8.3.

For using encoding and decoding decorated streams the PHP extension *iconv* is required.

For the `stubbles\streams\linesOf()` and `stubbles\streams\nonEmptyLinesOf()`functions the package *[stubbles/sequence](https://github.com/stubbles/stubbles-sequence)*is required.

Interfaces and methods
----------------------

[](#interfaces-and-methods)

*stubbles/streams* provides input and output streams for different kind of sources. All input streams implement the `stubbles\streams\InputStream`interface, all output streams the `stubbles\streams\OutputStream` interface. While input streams can be used to read data from a source, output streams can be used to write data to a certain source.

### Interfaces and their methods

[](#interfaces-and-their-methods)

#### Input stream methods

[](#input-stream-methods)

The input stream interface provides the following methods:

- `read($length = 8192)` - returns given amount of bytes
- `readLine($length = 8192)` - returns all characters up to given length until next line break
- `bytesLeft()` - returns the amount of bytes left to be read
- `eof()` - checks whether end of input was reached
- `close()` - closes the stream

#### Output stream methods

[](#output-stream-methods)

The output stream interface provides the following methods:

- `write($bytes)` - writes given bytes and returns amount of written bytes
- `writeLine($bytes)` - same as `write()`, but adds a line break at end of bytes
- `close()` - closes the stream

#### Seekable streams

[](#seekable-streams)

Some streams are seekable which means you can go from one position in the stream to another. Input streams which are seekable implement the `stubbles\streams\Seekable` interface. It provides the following methods:

- `seek(int $offset, Whence $whence = Whence::SET)` - sets internal stream pointer to given position depending on $whence, which has three allowed values which can be found in enum `stubbles\streams\Whence`: `Whence::SET`, `Whence::CURRENT` and `Whence::END`.
- `tell()` - returns the current position of the internal stream pointer

#### Copy from input to output stream

[](#copy-from-input-to-output-stream)

*Available since release 8.1.0*

The shortcut function `stubbles\streams\copy()` provides a simple way to copy everything what's in an input stream to an output stream:

```
copy($in)->to($out);
```

Please note that copying starts at the offset where the input stream currently is located, and changes the offset of the input stream to the end of the stream. In case a non-seekable input stream is copied it can not return to its initial offset.

### Decorating streams

[](#decorating-streams)

#### Encoding-related streams

[](#encoding-related-streams)

Sometimes it is necessary to decode input stream data into the internal encoding of the application. While Stubbles' internal encoding is UTF-8, all data read from input streams should be UTF-8 itself or at least converted to UTF-8 before returned from the input stream. To ease this, the `stubbles\streams\DecodingInputStream` class decorates another input stream given as first parameter on construction, and tries to decode the data read from the decorated input stream from the stream encoding to UTF-8 using `iconv()`. However you need to specify the charset of the decorated input stream as second parameter to the constructor:

```
$decodingInputStream = new DecodingInputStream($encodedInputStream, 'iso-8859-1');
```

*Note: since release 9.0.0 a third parameter can be used to influence what the data is being encoded to. The default is still UTF-8.*

Of course there must be a possibility to write back into the correct encoding. For this, the `stubbles\streams\EncodingOutputStream` class can be used. It tries to convert from internal UTF-8 into the encoding of the decorated output stream using `iconv()`.

```
$encodingOutputStream = new EncodingOutputStream($encodedOutputStream, 'iso-8859-1');
```

*Note: since release 9.0.0 a third parameter can be used to influence what the data is being encoded from. The default is still UTF-8.*

File related streams
--------------------

[](#file-related-streams)

To read data from a file one may use the `stubbles\streams\file\FileInputStream`class. Its constructor expects either a name of a file, or an already opened file pointer resource. If it is the name of the file the second parameter of the constructor sets the mode in which the file is opened, it defaults to *rb*(binary reading). The file input stream is a seekable stream.

To write data to a file one may use the `stubbles\streams\file\FileOutputStream`class. Similarly to the file input stream class its constructor expects either a name of a file, or an already opened file pointer resource. If it is the name of the file the second parameter of the constructor sets the mode in which the file is opened, it defaults to *wb* (binary writing).

Warning: the mode parameter accepts modes which might not make any sense with the stream class - e.g. the input stream allows *wb* as value for the mode parameter, but then you can not read from the given file, and vice versa for the output stream.

Memory streams
--------------

[](#memory-streams)

Sometimes it is helpful if one can read or write data into memory. For such purposes the `stubbles\streams\memory\MemoryInputStream` and `stubbles\streams\memory\MemoryOutputStream` exist. While the memory input stream class expects the content to be read from as string parameter for its constructor, the memory output stream does not expect a value on construction, but offers an additional method `buffer()` which returns all data written to this stream so far. Additionally, casting the `stubbles\streams\memory\MemoryOutputStream`to string will return the buffer (*available since release 4.0.0*).

The memory input stream is a seekable stream.

Filter streams
--------------

[](#filter-streams)

When reading from or writing data to a stream sometimes it may happen that not all data to read or not all data to be written is relevant for what you want to achieve. For example, a file you read may contain comment lines, and you don't want to ignore those comment lines. Normally, you would have the logic on what to ignore in your reading class:

```
while (!$inputStream->eof()) {
    $line = $inputStream->readLine();
    if (substr(0, 1, $line) !== '#') {
        $this->processLine($line);
    }
}
```

In this small example it may not be much work, but what if comment lines may also start with `//` or there may even be comments stretching over more than one line as we have in PHP with `/* comment over several lines ... */`. Now the logic might get a bit to complicated at this point. Stream filters to the rescue:

```
$filterStream = new FilteredInputStream(
        $inputStream,
        function($line) { return substr($line, 0, 1) !== '#'; }
);
while (!$filterStream->eof()) {
    $this->processLine($inputStream->readLine());
}
```

The second argument for `stubbles\streams\filter\FilteredInputStream` can be any `callable` which accepts a string as argument and returns `true` when this string should be passed through, and `false` when this string should be filtered. Please note that you can't filter single characters from the passed string, only characters as a whole.

The same applies to the `stubbles\streams\filter\FilteredOutputStream`, just that the filter is applied to the data that is written.

Input stream sequences
----------------------

[](#input-stream-sequences)

Because iterating over input streams with `while` can be quite cumbersome, *stubbles/streams* provides an input stream implementation which is also an instance of `\Iterator`.

```
$lines = new InputStreamIterator(new FileInputStream('somefile.txt'));
foreach ($lines as $line {
    processLine($line);
}
```

Each iteration step is a call to `readLine()` of the decorated input stream.

Please note: when the decorated stream is not an instance of `stubbles\streams\Seekable`it can be iterated only once, trying to rewind will do nothing.

Integration with *stubbles/sequence*
------------------------------------

[](#integration-with-stubblessequence)

Optionally iteration can be even more enhanced when the package *[stubbles/sequence](https://github.com/stubbles/stubbles-sequence)* is available.

This allows to use two functions which return an instance of `stubbles\sequence\Sequence` that allow all sequence operation on an input stream:

### `stubbles\streams\linesOf($input)`

[](#stubblesstreamslinesofinput)

The input can either be an instance of `stubbles\streams\InputStream` or a file name.

```
$lines = linesOf('somefile.txt')
        ->filter(/* callable which filters */)
        ->map(/* callable which maps the line to other content */);
foreach ($lines as $line) {
    processLine($line);
}
```

### `stubbles\streams\nonEmptyLinesOf($input)`

[](#stubblesstreamsnonemptylinesofinput)

Same as above, but already filters all empty lines.

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance82

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity83

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 73.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~601 days

Recently: every ~844 days

Total

7

Last Release

160d ago

Major Versions

v7.0.0 → v8.0.02016-07-20

v8.1.0 → v9.0.02019-11-08

v9.1.0 → v10.0.02023-12-31

v10.0.0 → v11.0.02025-11-30

PHP version history (5 changes)v7.0.0PHP &gt;=5.6.0

v8.0.0PHP ^7.0

v9.0.0PHP ^7.3

v10.0.0PHP ^8.2

v11.0.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/cde3f4e0a0e4454942288eb300c91644bd359cc3572d65b473e3484701fa4931?d=identicon)[mikey179](/maintainers/mikey179)

---

Top Contributors

[![mikey179](https://avatars.githubusercontent.com/u/190475?v=4)](https://github.com/mikey179 "mikey179 (36 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (13 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/stubbles-streams/health.svg)

```
[![Health](https://phpackages.com/badges/stubbles-streams/health.svg)](https://phpackages.com/packages/stubbles-streams)
```

###  Alternatives

[zhelyabuzhsky/yii2-sitemap

A Yii2 tool to generate sitemap.xml.

3439.7k](/packages/zhelyabuzhsky-yii2-sitemap)[amplifier/yii-amqp

AMQP adapter for Yii

2237.0k](/packages/amplifier-yii-amqp)[bigfork/htmleditorsrcset

Simple srcset integration with SilverStripe’s HTMLEditorField

1025.4k4](/packages/bigfork-htmleditorsrcset)[anasstouaticoder/magento2-module-instantconfigurationcopy

The InstantConfigurationCopy module provides easy way to copy configuration field information for admin in back office Magento 2.

163.8k](/packages/anasstouaticoder-magento2-module-instantconfigurationcopy)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
