class ActiveFedora::FileIO

IO like object for reading Fedora files. Use ActiveFedora::FileIO.new(fedora_file) to create one. You can then call read on it or use it with IO.copy_stream and the like.

@Note The stream will always be in binmode and return ASCII-8BIT content.

Attributes

pos[R]

Public Class Methods

new(fedora_file) click to toggle source

@param [ActiveFedora::File] the file which is wrapped in this IO object.

# File lib/active_fedora/file_io.rb, line 13
def initialize(fedora_file)
  @fedora_file = fedora_file
  @closed = false
  rewind # this initialises various variables
end

Public Instance Methods

binmode() click to toggle source
# File lib/active_fedora/file_io.rb, line 25
def binmode
  # Do nothing, just return self. The stream is essentially always in binmode.
  self
end
binmode?() click to toggle source
# File lib/active_fedora/file_io.rb, line 30
def binmode?
  true
end
close() click to toggle source

Closes the file. No further action can be taken on the file.

# File lib/active_fedora/file_io.rb, line 83
def close
  @closed = true
  @stream_fiber = nil
  nil
end
length()
Alias for: size
read(amount = nil, buf = nil) click to toggle source

Read bytes from the file. See IO.read for more information. @param [Integer] the number of bytes to read. If nil or omitted, the

entire contents will be read.

@param [String] a string in which the contents are read. Can be omitted. @return [String] the read bytes. If number of bytes to read was not

specified then always returns a String, possibly an empty
one. If number of bytes was specified then the returned
string will always be at least one byte long. If no bytes
are left in the file returns nil instead.
# File lib/active_fedora/file_io.rb, line 44
def read(amount = nil, buf = nil)
  raise(IOError, "closed stream") if @closed

  buf ||= ''.force_encoding("ASCII-8BIT")
  buf.clear

  if amount.nil?
    read_to_buf(nil, buf) # read the entire file, returns buf
  elsif amount.negative?
    raise(ArgumentError, "negative length #{amount} given")
  elsif amount.zero?
    ''
  else
    read_to_buf(amount, buf)
    # if amount was specified but we reached eof before reading anything
    # then we must return nil
    buf.empty? ? nil : buf
  end
end
rewind() click to toggle source

Rewinds the io object to the beginning. Read will return bytes from the start of the file again.

# File lib/active_fedora/file_io.rb, line 67
def rewind
  raise(IOError, "closed stream") if @closed
  @pos = 0
  @buffer = nil
  @stream_fiber = Fiber.new do
    @fedora_file.stream.each do |chunk|
      Fiber.yield chunk
    end
    @stream_fiber = nil
    # last value from Fiber is the return value of the block which should be nil
  end
  0
end
size() click to toggle source
# File lib/active_fedora/file_io.rb, line 19
def size
  @fedora_file.size
end
Also aliased as: length

Private Instance Methods

consume_buffer(count = nil) click to toggle source
# File lib/active_fedora/file_io.rb, line 96
def consume_buffer(count = nil)
  if count.nil? || count >= @buffer.length
    @pos += @buffer.length
    @buffer .tap do
      @buffer = nil
    end
  else
    @buffer.slice!(0, count) .tap do |slice|
      @pos += slice.length
    end
  end
end
fill_buffer() click to toggle source
# File lib/active_fedora/file_io.rb, line 109
def fill_buffer
  return true if @buffer.present?
  # Ruby Net library doesn't seem to like it if we modify the returned
  # chunk in any way, hence dup.
  @buffer = @stream_fiber.try(:resume).try(:dup)
  @buffer.try(:force_encoding, 'ASCII-8BIT')
  !@buffer.nil?
end
read_to_buf(amount, buf) click to toggle source
# File lib/active_fedora/file_io.rb, line 91
def read_to_buf(amount, buf)
  buf << consume_buffer(amount.nil? ? nil : (amount - buf.length)) while (amount.nil? || buf.length < amount) && fill_buffer
  buf
end