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



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

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:



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

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



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

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)


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

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)


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

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



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

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



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

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,
    )
    @current_entry_io = StringIO.new(decompressed, "rb")
  end

  @current_entry_io.read(size)
end

#rewindObject

Rewind the stream



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

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