Skip to content
This repository has been archived by the owner on Jan 16, 2019. It is now read-only.

Filter streams

Frank Kleine edited this page Aug 5, 2014 · 2 revisions

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:

Applies to releases >= 4.0.0. For releases < 4.0.0 please see below.

$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 or a predicate. The same applies to the stubbles\streams\filter\FilteredOutputStream, just that the filter is applied to the data that is written.

Applies to releases < 4.0.0

$filterStream = new FilteredInputStream($inputStream, new CommentFilter());
while (!$filterStream->eof()) {
    $this->processLine($inputStream->readLine());
}

The logic which line to pass out of the stream is now encapsulated in the CommentFilter class and thus much easier to test. The comment filter class in turn only has to implement the net\stubbles\streams\filter\StreamFilter interface with one little method:

/**
 * Decides whether data should be filtered or not.
 *
 * @param string $data
 * @return bool
 */
public function shouldFilter($data);

Here, $data is the data just read from the underlying stream (or should be written to the underlying stream). The return value of this method signalizes whether this data should be filtered (return value true) or not (return value false).

With this filter in place, the net\stubbles\streams\filter\FilteredInputStream and net\stubbles\streams\filter\FilteredOutputStream can be put to use. Both have two constructor arguments: the input or output stream to decorate, and the filter to apply. While the FilteredInputStream will use the filter to decide which data to pass on to the caller, the FilteredOutputStream in turn decides which passed data should be written to the decorated output stream.

In case you like to combine several different filters net\stubbles\streams\filter\CompositeStreamFilter can combine an arbitrary list of filters and then be passed as stream filter instance to the filtering streams.

Clone this wiki locally