System I/O reference
IOSystem
Class Overview
The [IOSystem](lib/cabriolet/system/io_system.rb) class provides a factory for creating I/O handles with platform abstraction.
Location: [lib/cabriolet/system/io_system.rb](lib/cabriolet/system/io_system.rb)
Instance Methods
FileHandle
Class Overview
Standard file system handle implementation.
Location: [lib/cabriolet/system/file_handle.rb](lib/cabriolet/system/file_handle.rb)
Instance Methods
read(size = nil)
Reads data from file.
Parameters: * size (Integer, nil) - Bytes to read (nil = read all)
Returns: String (binary) or nil at EOF
Example:
# Read 1024 bytes
chunk = handle.read(1024)
# Read all remaining
all_data = handle.read write(data)
Writes data to file.
Parameters: * data (String) - Data to write
Returns: Integer - Bytes written
seek(offset, whence = IO::SEEK_SET)
Seeks to position.
Parameters: * offset (Integer) - Offset in bytes * whence (Integer) - Seek mode
Whence values: * IO::SEEK_SET (0) - Absolute position * IO::SEEK_CUR (1) - Relative to current * IO::SEEK_END (2) - Relative to end
Returns: Integer - New position
Example:
# Seek to absolute position
handle.seek(1000)
# Seek forward 100 bytes
handle.seek(100, IO::SEEK_CUR)
# Seek to end
handle.seek(0, IO::SEEK_END)MemoryHandle
Class Overview
In-memory handle implementation for binary data.
Location: [lib/cabriolet/system/memory_handle.rb](lib/cabriolet/system/memory_handle.rb)
Custom Handle Implementation
Required Methods
To create a custom handle, implement:
class CustomHandle
def read(size)
# Read up to size bytes
end
def write(data)
# Write data, return bytes written
end
def seek(offset, whence = IO::SEEK_SET)
# Seek to position, return new position
end
def tell
# Return current position
end
def eof?
# Return true if at end
end
def size
# Return total size
end
def close
# Clean up resources
end
endExample: Network Handle
class NetworkHandle
def initialize(url)
@url = URI(url)
@position = 0
@size = fetch_size
@buffer = String.new(encoding: Encoding::BINARY)
end
def read(size)
# Fetch data on demand
while @buffer.bytesize - @position < size && !eof?
fetch_chunk
end
data = @buffer[@position, size]
@position += data.bytesize if data
data
end
def seek(offset, whence = IO::SEEK_SET)
case whence
when IO::SEEK_SET
@position = offset
when IO::SEEK_CUR
@position += offset
when IO::SEEK_END
@position = @size + offset
end
@position
end
def tell
@position
end
def eof?
@position >= @size
end
def size
@size
end
def close
@buffer.clear
end
private
def fetch_size
# HTTP HEAD request to get Content-Length
# ...
end
def fetch_chunk
# HTTP GET with Range header
# ...
end
endUsage Patterns
File Operations
# Standard file reading
handle = Cabriolet::System::FileHandle.new('archive.cab', 'rb')
# Read header
signature = handle.read(4)
# Seek to specific offset
handle.seek(100)
# Read data
data = handle.read(1024)
handle.closeMemory Operations
# Load file to memory
data = File.binread('archive.cab')
handle = Cabriolet::System::MemoryHandle.new(data)
# Process in memory
decompressor = Cabriolet::CAB::Decompressor.new(handle)
files = decompressor.extract_to_memory('file.txt')Mixed Operations
io_system = Cabriolet::System::IOSystem.new
# Some files from disk
file_handle = io_system.open('disk_archive.cab', 'rb')
# Some from memory
memory_data = download_from_network
io_system.register_memory_file('network_archive.cab', memory_data)
memory_handle = io_system.open('network_archive.cab', 'rb')
# Process both the same way
[file_handle, memory_handle].each do |handle|
decompressor = Cabriolet::CAB::Decompressor.new(handle)
decompressor.extract_all("output_#{handle.object_id}")
handle.close
endThread safety
-
IOSystem: Thread-safe for concurrent
opencalls -
FileHandle: Not thread-safe, use one per thread
-
MemoryHandle: Not thread-safe, use one per thread
Use mutex for shared handles:
mutex = Mutex.new
handle = Cabriolet::System::FileHandle.new('archive.cab', 'rb')
threads = 10.times.map do
Thread.new do
mutex.synchronize do
data = handle.read(1024)
# Process data
end
end
end
threads.each(&:join)
handle.closePerformance considerations
-
Buffer sizes: Larger buffers = fewer syscalls
-
Sequential access: Much faster than random seeking
-
Memory handles: Faster than file I/O, but use more RAM
-
Custom handles: Profile to ensure performance
-
Resource cleanup: Always close handles