Class: Omnizip::Zip::InputStream

Inherits:
Object
  • Object
show all
Includes:
Formats::Zip::Constants
Defined in:
lib/omnizip/zip/input_stream.rb

Overview

Rubyzip-compatible InputStream class Provides streaming read API for ZIP archives

Constant Summary

Constants included from Formats::Zip::Constants

Formats::Zip::Constants::ATTR_ARCHIVE, Formats::Zip::Constants::ATTR_DIRECTORY, Formats::Zip::Constants::CENTRAL_DIRECTORY_SIGNATURE, Formats::Zip::Constants::COMPRESSION_BZIP2, Formats::Zip::Constants::COMPRESSION_DEFLATE, Formats::Zip::Constants::COMPRESSION_DEFLATE64, Formats::Zip::Constants::COMPRESSION_IMPLODED, Formats::Zip::Constants::COMPRESSION_LZMA, Formats::Zip::Constants::COMPRESSION_PPMD, Formats::Zip::Constants::COMPRESSION_REDUCED_1, Formats::Zip::Constants::COMPRESSION_REDUCED_2, Formats::Zip::Constants::COMPRESSION_REDUCED_3, Formats::Zip::Constants::COMPRESSION_REDUCED_4, Formats::Zip::Constants::COMPRESSION_SHRUNK, Formats::Zip::Constants::COMPRESSION_STORE, Formats::Zip::Constants::COMPRESSION_ZSTANDARD, Formats::Zip::Constants::DATA_DESCRIPTOR_SIGNATURE, Formats::Zip::Constants::END_OF_CENTRAL_DIRECTORY_SIGNATURE, Formats::Zip::Constants::FLAG_DATA_DESCRIPTOR, Formats::Zip::Constants::FLAG_ENCRYPTED, Formats::Zip::Constants::FLAG_STRONG_ENCRYPTION, Formats::Zip::Constants::FLAG_UTF8, Formats::Zip::Constants::LOCAL_FILE_HEADER_SIGNATURE, Formats::Zip::Constants::MAX_COMMENT_LENGTH, Formats::Zip::Constants::UNIX_DIR_PERMISSIONS, Formats::Zip::Constants::UNIX_EXTRA_FIELD_TAG, Formats::Zip::Constants::UNIX_FILE_PERMISSIONS, Formats::Zip::Constants::UNIX_SYMLINK_PERMISSIONS, Formats::Zip::Constants::VERSION_BZIP2, Formats::Zip::Constants::VERSION_DEFAULT, Formats::Zip::Constants::VERSION_DEFLATE, Formats::Zip::Constants::VERSION_LZMA, Formats::Zip::Constants::VERSION_MADE_BY_UNIX, Formats::Zip::Constants::VERSION_MADE_BY_WINDOWS, Formats::Zip::Constants::VERSION_ZIP64, Formats::Zip::Constants::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE, Formats::Zip::Constants::ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE, Formats::Zip::Constants::ZIP64_EXTRA_FIELD_TAG, Formats::Zip::Constants::ZIP64_LIMIT

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_path_or_io) ⇒ InputStream

Initialize input stream

Parameters:

  • file_path_or_io (String, IO)

    File path or IO object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/omnizip/zip/input_stream.rb', line 30

def initialize(file_path_or_io)
  if file_path_or_io.is_a?(String)
    @file_path = file_path_or_io
    @io = ::File.open(file_path_or_io, "rb")
    @owns_io = true
  else
    @io = file_path_or_io
    @owns_io = false
  end

  @current_entry = nil
  @current_entry_io = nil
  @current_index = 0
  @closed = false
  @hit_nil = false

  # Find and parse central directory for efficient access
  parse_central_directory
end

Class Method Details

.open(file_path_or_io) {|stream| ... } ⇒ InputStream

Open an input stream

Parameters:

  • file_path_or_io (String, IO)

    File path or IO object

Yields:

  • (stream)

    Block to read from the stream

Returns:



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/omnizip/zip/input_stream.rb', line 14

def self.open(file_path_or_io, &block)
  stream = new(file_path_or_io)

  if block
    begin
      yield(stream)
    ensure
      stream.close
    end
  else
    stream
  end
end

Instance Method Details

#closeObject

Close the stream



107
108
109
110
111
112
113
# File 'lib/omnizip/zip/input_stream.rb', line 107

def close
  return if @closed

  @current_entry_io = nil
  @io.close if @owns_io
  @closed = true
end

#closed?Boolean

Check if stream is closed

Returns:

  • (Boolean)


116
117
118
# File 'lib/omnizip/zip/input_stream.rb', line 116

def closed?
  @closed
end

#eof?Boolean Also known as: eof

Check if at end of file Returns true if the NEXT call to get_next_entry would return nil

Returns:

  • (Boolean)


122
123
124
# File 'lib/omnizip/zip/input_stream.rb', line 122

def eof?
  @current_index >= @all_entries.size
end

#get_next_entryEntry?

Get next entry in the archive

Returns:

  • (Entry, nil)

    Next entry or nil if no more entries



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/omnizip/zip/input_stream.rb', line 52

def get_next_entry
  # Check if we can fetch another entry
  if @current_index >= @all_entries.size
    # Mark that get_next_entry returned nil
    @hit_nil = true
    return nil
  end

  # Close previous entry data if open
  @current_entry_io = nil

  # Get next entry from our parsed list
  header = @all_entries[@current_index]
  @current_index += 1

  # Successfully got an entry - clear the nil flag
  @hit_nil = false

  # Position at entry data
  position_at_entry_data(header)

  @current_entry = Entry.new(header)
  @current_entry
end

#read(size = nil) ⇒ String?

Read from current entry

Parameters:

  • size (Integer, nil) (defaults to: nil)

    Number of bytes to read (nil for all)

Returns:

  • (String, nil)

    Data read or nil if no current entry



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/omnizip/zip/input_stream.rb', line 80

def read(size = nil)
  return nil unless @current_entry

  # Initialize entry IO if needed
  unless @current_entry_io
    compressed_data = @io.read(@current_entry.compressed_size)
    decompressed = decompress_data(
      compressed_data,
      @current_entry.compression_method,
      @current_entry.size,
    )
    require "stringio"
    @current_entry_io = StringIO.new(decompressed, "rb")
  end

  @current_entry_io.read(size)
end

#rewindObject

Rewind the stream



99
100
101
102
103
104
# File 'lib/omnizip/zip/input_stream.rb', line 99

def rewind
  @current_index = 0
  @current_entry = nil
  @current_entry_io = nil
  @hit_nil = false
end