class IOStreams::Stream
Attributes
Public Class Methods
# File lib/io_streams/stream.rb, line 6 def initialize(io_stream) raise(ArgumentError, "io_stream cannot be nil") if io_stream.nil? raise(ArgumentError, "io_stream must not be a string: #{io_stream.inspect}") if io_stream.is_a?(String) @io_stream = io_stream @builder = nil end
Public Instance Methods
Returns [String] the last component of this path. Returns `nil` if no `file_name` was set.
Parameters:
suffix: [String] When supplied the `suffix` is removed from the file_name before being returned. Use `.*` to remove any extension. IOStreams.path("/home/gumby/work/ruby.rb").basename #=> "ruby.rb" IOStreams.path("/home/gumby/work/ruby.rb").basename(".rb") #=> "ruby" IOStreams.path("/home/gumby/work/ruby.rb").basename(".*") #=> "ruby"
# File lib/io_streams/stream.rb, line 257 def basename(suffix = nil) file_name = builder.file_name return unless file_name suffix.nil? ? ::File.basename(file_name) : ::File.basename(file_name, suffix) end
Copy from another stream, path, file_name
or IO instance.
Parameters:
stream [IOStreams::Path|String<file_name>|IO] The stream to read from. :convert [true|false] Whether to apply the stream conversions during the copy. Default: true :mode [:line, :array, :hash] When convert is `true` then use this mode to convert the contents of the file.
Examples:
# Copy and convert streams based on file extensions IOStreams.path
(“target_file.json”).copy_from(“source_file_name.csv.gz”)
# Copy “as-is” without any automated stream conversions IOStreams.path
(“target_file.json”).copy_from(“source_file_name.csv.gz”, convert: false)
# Advanced copy with custom stream conversions on source and target. source = IOStreams.path
(“source_file”).stream(encoding: “BINARY”) IOStreams.path
(“target_file.pgp”).option(:pgp, passphrase: “hello”).copy_from(source)
# File lib/io_streams/stream.rb, line 176 def copy_from(source, convert: true, mode: nil, **args) if convert stream = IOStreams.new(source) if mode writer(mode, **args) do |target| stream.each(mode) { |row| target << row } end else writer(**args) do |target| stream.reader { |src| IO.copy_stream(src, target) } end end else stream = source.is_a?(Stream) ? source.dup : IOStreams.new(source) dup.stream(:none).writer do |target| stream.stream(:none).reader { |src| IO.copy_stream(src, target) } end end end
# File lib/io_streams/stream.rb, line 196 def copy_to(target, **args) target = IOStreams.new(target) target.copy_from(self, **args) end
Returns [String] the directory for this file. Returns `nil` if no `file_name` was set.
If `path` does not include a directory name the “.” is returned.
IOStreams.path("test.rb").dirname #=> "." IOStreams.path("a/b/d/test.rb").dirname #=> "a/b/d" IOStreams.path(".a/b/d/test.rb").dirname #=> ".a/b/d" IOStreams.path("foo.").dirname #=> "." IOStreams.path("test").dirname #=> "." IOStreams.path(".profile").dirname #=> "."
# File lib/io_streams/stream.rb, line 275 def dirname file_name = builder.file_name ::File.dirname(file_name) if file_name end
Iterate over a file / stream returning one line at a time.
Example: Read a line at a time
IOStreams.path("file.txt").each(:line) do |line| puts line end
Example: Read a line at a time with custom options
IOStreams.path("file.csv").each(:line, embedded_within: '"') do |line| puts line end
Example: Read a row at a time
IOStreams.path("file.csv").each(:array) do |array| p array end
Example: Read a record at a time
IOStreams.path("file.csv").each(:hash) do |hash| p hash end
Notes:
-
Embedded lines (within double quotes) will be skipped if
-
The file name contains .csv
-
Or the embedded_within argument is set
-
# File lib/io_streams/stream.rb, line 93 def each(mode = :line, **args, &block) raise(ArgumentError, "Invalid mode: #{mode.inspect}") if mode == :stream # return enum_for __method__ unless block_given? reader(mode, **args) { |stream| stream.each(&block) } end
Returns [String] the extension for this file without the last period. Returns `nil` if no `file_name` was set.
If `path` is a dotfile, or starts with a period, then the starting dot is not considered part of the extension.
An empty string will also be returned when the period is the last character in the `path`.
IOStreams.path("test.rb").extension #=> "rb" IOStreams.path("a/b/d/test.rb").extension #=> "rb" IOStreams.path(".a/b/d/test.rb").extension #=> "rb" IOStreams.path("foo.").extension #=> "" IOStreams.path("test").extension #=> "" IOStreams.path(".profile").extension #=> "" IOStreams.path(".profile.sh").extension #=> "sh"
# File lib/io_streams/stream.rb, line 315 def extension extname&.sub(/^\./, "") end
Returns [String] the extension for this file including the last period. Returns `nil` if no `file_name` was set.
If `path` is a dotfile, or starts with a period, then the starting dot is not considered part of the extension.
An empty string will also be returned when the period is the last character in the `path`.
IOStreams.path("test.rb").extname #=> ".rb" IOStreams.path("a/b/d/test.rb").extname #=> ".rb" IOStreams.path(".a/b/d/test.rb").extname #=> ".rb" IOStreams.path("foo.").extname #=> "" IOStreams.path("test").extname #=> "" IOStreams.path(".profile").extname #=> "" IOStreams.path(".profile.sh").extname #=> ".sh"
# File lib/io_streams/stream.rb, line 295 def extname file_name = builder.file_name ::File.extname(file_name) if file_name end
Set/get the original file_name
# File lib/io_streams/stream.rb, line 202 def file_name(file_name = :none) if file_name == :none builder.file_name else builder.file_name = file_name self end end
Set the original file_name
# File lib/io_streams/stream.rb, line 212 def file_name=(file_name) builder.file_name = file_name end
Set/get the tabular format_options
# File lib/io_streams/stream.rb, line 217 def format(format = :none) if format == :none builder.format else builder.format = format self end end
Set the tabular format
# File lib/io_streams/stream.rb, line 227 def format=(format) builder.format = format end
Set/get the tabular format options
# File lib/io_streams/stream.rb, line 232 def format_options(format_options = :none) if format_options == :none builder.format_options else builder.format_options = format_options self end end
Set the tabular format_options
# File lib/io_streams/stream.rb, line 242 def format_options=(format_options) builder.format_options = format_options end
Set the options for an element within the stream for this file. If the relevant stream is not found for this file it is ignored. For example, if the file does not have a pgp extension then the pgp option is not relevant.
IOStreams.path
(“keep_safe.pgp”).option(:pgp, passphrase: “receiver_passphrase”).read
# In this case the file is not pgp so the `passphrase` option is ignored. IOStreams.path
(“keep_safe.enc”).option(:pgp, passphrase: “receiver_passphrase”).read
IOStreams.path(output_file_name)
.option(:pgp, passphrase: “receiver_passphrase”).read
# File lib/io_streams/stream.rb, line 36 def option(stream, **options) builder.option(stream, **options) self end
Adds the options for the specified stream as an option, but if streams have already been added it is instead added as a stream.
# File lib/io_streams/stream.rb, line 43 def option_or_stream(stream, **options) builder.option_or_stream(stream, **options) self end
Returns [Hash<Symbol:Hash>] the pipeline of streams with their options that will be applied when the reader or writer is invoked.
# File lib/io_streams/stream.rb, line 55 def pipeline builder.pipeline end
Read an entire file into memory.
Notes:
-
Use with caution since large files can cause a denial of service since this method will load the entire file into memory.
-
Recommend using instead `#reader` to read a block into memory at a time.
# File lib/io_streams/stream.rb, line 122 def read(*args) reader { |stream| stream.read(*args) } end
Returns a Reader
for reading a file / stream
# File lib/io_streams/stream.rb, line 101 def reader(mode = :stream, **args, &block) case mode when :stream stream_reader(&block) when :line line_reader(**args, &block) when :array row_reader(**args, &block) when :hash record_reader(**args, &block) else raise(ArgumentError, "Invalid mode: #{mode.inspect}") end end
Removes the named stream from the current pipeline. If the stream pipeline has not yet been built it will be built from the file_name
if present. Note: Any options must be set before calling this method.
# File lib/io_streams/stream.rb, line 62 def remove_from_pipeline(stream_name) builder.remove_from_pipeline(stream_name) self end
Return the options already set for either a stream or option.
# File lib/io_streams/stream.rb, line 49 def setting(stream) builder.setting(stream) end
Ignore the filename and use only the supplied streams.
See option
to set an option for one of the streams included based on the file name extensions.
Example:
IOStreams.path
(“tempfile2527”).stream(:zip).stream(:pgp, passphrase: “receiver_passphrase”).read
# File lib/io_streams/stream.rb, line 21 def stream(stream, **options) builder.stream(stream, **options) self end
Write entire string to file.
Notes:
-
Use with caution since preparing large amounts of data in memory can cause a denial of service since all the data for the file needs to be resident in memory before writing.
-
Recommend using instead `#writer` to write a block of memory at a time.
# File lib/io_streams/stream.rb, line 148 def write(data) writer { |stream| stream.write(data) } end
Returns a Writer
for writing to a file / stream
# File lib/io_streams/stream.rb, line 127 def writer(mode = :stream, **args, &block) case mode when :stream stream_writer(&block) when :line line_writer(**args, &block) when :array row_writer(**args, &block) when :hash record_writer(**args, &block) else raise(ArgumentError, "Invalid mode: #{mode.inspect}") end end
Private Instance Methods
# File lib/io_streams/stream.rb, line 321 def builder @builder ||= IOStreams::Builder.new end
# File lib/io_streams/stream.rb, line 329 def line_reader(embedded_within: nil, **args) embedded_within = '"' if embedded_within.nil? && builder.file_name&.include?(".csv") stream_reader do |io| yield IOStreams::Line::Reader.new(io, original_file_name: builder.file_name, embedded_within: embedded_within, **args) end end
# File lib/io_streams/stream.rb, line 370 def line_writer(**args, &block) return block.call(io_stream) if io_stream&.is_a?(IOStreams::Line::Writer) writer do |io| IOStreams::Line::Writer.stream(io, original_file_name: builder.file_name, **args, &block) end end
Iterate over a file / stream returning each line as a hash, one at a time.
# File lib/io_streams/stream.rb, line 354 def record_reader(delimiter: nil, embedded_within: nil, **args) line_reader(delimiter: delimiter, embedded_within: embedded_within) do |io| yield IOStreams::Record::Reader.new( io, original_file_name: builder.file_name, format: builder.format, format_options: builder.format_options, **args ) end end
# File lib/io_streams/stream.rb, line 393 def record_writer(delimiter: $/, **args, &block) return block.call(io_stream) if io_stream&.is_a?(IOStreams::Record::Writer) line_writer(delimiter: delimiter) do |io| IOStreams::Record::Writer.stream( io, original_file_name: builder.file_name, format: builder.format, format_options: builder.format_options, **args, &block ) end end
Iterate over a file / stream returning each line as an array, one at a time.
# File lib/io_streams/stream.rb, line 341 def row_reader(delimiter: nil, embedded_within: nil, **args) line_reader(delimiter: delimiter, embedded_within: embedded_within) do |io| yield IOStreams::Row::Reader.new( io, original_file_name: builder.file_name, format: builder.format, format_options: builder.format_options, **args ) end end
# File lib/io_streams/stream.rb, line 378 def row_writer(delimiter: $/, **args, &block) return block.call(io_stream) if io_stream&.is_a?(IOStreams::Row::Writer) line_writer(delimiter: delimiter) do |io| IOStreams::Row::Writer.stream( io, original_file_name: builder.file_name, format: builder.format, format_options: builder.format_options, **args, &block ) end end
# File lib/io_streams/stream.rb, line 325 def stream_reader(&block) builder.reader(io_stream, &block) end
# File lib/io_streams/stream.rb, line 366 def stream_writer(&block) builder.writer(io_stream, &block) end