Why doesn't Ruby have a real StringBuffer or StringIO?

后端 未结 5 527
情话喂你
情话喂你 2020-12-09 07:25

I recently read a nice post on using StringIO in Ruby. What the author doesn\'t mention, though, is that StringIO is just an \"I.\" There\'s no \

相关标签:
5条回答
  • 2020-12-09 07:46

    Your example works in Ruby - I just tried it.

    irb(main):001:0> require 'stringio'
    => true
    irb(main):002:0> s = StringIO.new
    => #<StringIO:0x2ced9a0>
    irb(main):003:0> s << 'foo'
    => #<StringIO:0x2ced9a0>
    irb(main):004:0> s << 'bar'
    => #<StringIO:0x2ced9a0>
    irb(main):005:0> s.string
    => "foobar"
    

    Unless I'm missing the reason you're using to_s - that just outputs the object id.

    0 讨论(0)
  • 2020-12-09 07:47

    Well, a StringBuffer is not quite as necessary in Ruby, mainly because Strings in Ruby are mutable... thus you can build up a string by modifying the existing string instead of constructing new strings with each concat.

    As a note, you can also use special string syntax where you can build a string which references other variables within the string, which makes for very readable string construction. Consider:

    first = "Mike"
    last = "Stone"
    name = "#{first} #{last}"
    

    These strings can also contain expressions, not just variables... such as:

    str = "The count will be: #{count + 1}"
    count = count + 1
    
    0 讨论(0)
  • 2020-12-09 07:58

    Like other IO-type objects in Ruby, when you write to an IO, the character pointer advances.

    >> s = StringIO.new
    => #<StringIO:0x3659d4>
    >> s << 'foo'
    => #<StringIO:0x3659d4>
    >> s << 'bar'
    => #<StringIO:0x3659d4>
    >> s.pos
    => 6
    >> s.rewind
    => 0
    >> s.read
    => "foobar"
    
    0 讨论(0)
  • 2020-12-09 08:03

    I looked at the ruby documentation for StringIO, and it looks like what you want is StringIO#string, not StringIO#to_s

    Thus, change your code to:

    s = StringIO.new
    s << 'foo'
    s << 'bar'
    s.string
    
    0 讨论(0)
  • 2020-12-09 08:04

    I did some benchmarks and the fastest approach is using the String#<< method. Using StringIO is a little bit slower.

    s = ""; Benchmark.measure{5000000.times{s << "some string"}}
    =>   3.620000   0.100000   3.720000 (  3.970463)
    
    >> s = StringIO.new; Benchmark.measure{5000000.times{s << "some string"}}
    =>   4.730000   0.120000   4.850000 (  5.329215)
    

    Concatenating strings using the String#+ method is the slowest approach by many orders of magnitude:

    s = ""; Benchmark.measure{10000.times{s = s + "some string"}}
    =>   0.700000   0.560000   1.260000 (  1.420272)
    
    s = ""; Benchmark.measure{10000.times{s << "some string"}}
    =>   0.000000   0.000000   0.000000 (  0.005639)
    

    So I think the right answer is that the equivalent to Java's StringBuffer is simply using String#<< in Ruby.

    0 讨论(0)
提交回复
热议问题