Similarly, File and String both include the Enumerable mixin, so in a lot of cases you can read from an object without caring what type it is. This is a good example of Ruby's duck typing.
Just remember that, unlike a string, you can't iterate over a file multiple times without calling rewind:
StringIO comes in when the Enumerable methods and << aren't enough. If a method you're writing needs to use methods specific to IO, you can accept a string as input and wrap it in a StringIO. The class also comes in handy when you need to call a method someone else wrote, not anticipating that anyone would ever need to call it with anything other than a file:
When you write a method that accepts a file as an argument, you can silently accommodate callers who pass in strings by wrapping in a StringIO any string that gets passed in:
A StringIO object is always open for both reading and writing:
Memory access is faster than disk access, but for large amounts of data (more than about 10 kilobytes), StringIO objects are slower than disk files. If speed is your aim, your best bet is to write to and read from temp files using the tempfile module. Or you can do what the open-uri library does: start off by writing to a StringIO and, if it gets too big, switch to using a temp file.
内存访问速度比磁盘要会,但是对于大量数据,stringio对象要比磁盘文件要慢。比较好的方法是使用tempfile模板写入并从临时文件中读出。可以想open-uri库那样,开始用stringio,如果数据过大,在使用tempfile。
#Here's a string:
poem = %{The boy stood on the burning deck
Whence all but he had fled
He'd stayed above to wash his neck
Before he went to bed}
#and a file containing that string:
output = open("poem", "w")
output.write(poem)
output.close
input = open("poem")
#will give the same result when you call an Enumerable method:
poem.grep /ed$/
# => ["Whence all but he had fled\n", "Before he went to bed"]
input.grep /ed$/
# => ["Whence all but he had fled\n", "Before he went to bed"]
Just remember that, unlike a string, you can't iterate over a file multiple times without calling rewind:
input.grep /ed$/ # => []
input.rewind
input.grep /ed$/
# => ["Whence all but he had fled\n", "Before he went to bed"]
StringIO comes in when the Enumerable methods and << aren't enough. If a method you're writing needs to use methods specific to IO, you can accept a string as input and wrap it in a StringIO. The class also comes in handy when you need to call a method someone else wrote, not anticipating that anyone would ever need to call it with anything other than a file:
def fifth_byte(file)
file.seek(5)
file.read(1)
end
fifth_byte("123456")
# NoMethodError: undefined method `seek' for "123456":String
fifth_byte(StringIO.new("123456")) # => "6"
When you write a method that accepts a file as an argument, you can silently accommodate callers who pass in strings by wrapping in a StringIO any string that gets passed in:
def file_operation(io)
io =
StringIO(io) if io.respond_to? :to_str && !io.is_a? StringIO
#Do the file operation…
end
A StringIO object is always open for both reading and writing:
s = StringIO.new
s << "A string"
s.read # => ""
s << ", and more."
s.rewind
s.read # => "A string, and more."
Memory access is faster than disk access, but for large amounts of data (more than about 10 kilobytes), StringIO objects are slower than disk files. If speed is your aim, your best bet is to write to and read from temp files using the tempfile module. Or you can do what the open-uri library does: start off by writing to a StringIO and, if it gets too big, switch to using a temp file.
内存访问速度比磁盘要会,但是对于大量数据,stringio对象要比磁盘文件要慢。比较好的方法是使用tempfile模板写入并从临时文件中读出。可以想open-uri库那样,开始用stringio,如果数据过大,在使用tempfile。