class CompositeReadIO

Concatenate together multiple IO objects into a single, composite IO object for purposes of reading as a single stream.

Usage:

crio = CompositeReadIO.new(StringIO.new('one'), StringIO.new('two'), StringIO.new('three'))
puts crio.read # => "onetwothree"

Public Class Methods

new(*ios) click to toggle source

Create a new composite-read IO from the arguments, all of which should respond to read in a manner consistent with IO.

# File lib/composite_io.rb, line 18
def initialize(*ios)
  @ios = ios.flatten
end

Public Instance Methods

read(amount = nil, buf = nil) click to toggle source

Read from the IO object, overlapping across underlying streams as necessary.

# File lib/composite_io.rb, line 23
def read(amount = nil, buf = nil)
  buffer = buf || ''
  done = if amount; nil; else ''; end
  partial_amount = amount

  loop do
    result = done

    while !@ios.empty? && (result = @ios.first.read(partial_amount)) == done
      @ios.shift
    end

    result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
    buffer << result if result
    partial_amount -= result.length if partial_amount && result != done

    break if partial_amount && partial_amount <= 0
    break if result == done
  end

  if buffer.length > 0
    buffer
  else
    done
  end
end