<p>I recently read a nice <a href="http://macdevelopertips.com/ruby/using-a-string-as-a-file-in-ruby.html" rel="noreferrer">post</a> on using <code>StringIO</code> in Ruby.  What the author doesn't mention, though, is that <code>StringIO</code> is just an "I."  There's no "O."  You <em>can't</em> do this, for example:</p>

<pre><code>s = StringIO.new
s &lt;&lt; 'foo'
s &lt;&lt; 'bar'
s.to_s
# =&gt; should be "foo\nbar"
# =&gt; really is ''`
</code></pre>

<p>Ruby really needs a StringBuffer just like the one Java has. StringBuffers serve two important purposes. First, they let you test the output half of what Ruby's StringIO does. Second, they are useful for building up long strings from small parts -- something that Joel reminds us over and over again is otherwise very very slow.</p>

<p>Is there a good replacement?</p>

<p>It's true that Strings in Ruby are mutable, but that doesn't mean we should always rely on that functionality.  If <code>stuff</code> is large, the performance and memory requirements of this, for example, is really bad.</p>

<pre><code>result = stuff.map(&amp;:to_s).join(' ')
</code></pre>

<p>The "correct" way to do this in Java is:</p>

<pre><code>result = StringBuffer.new("")
for(String s : stuff) {
  result.append(s);
}
</code></pre>

<p>Though my Java is a bit rusty.</p>

[{'answer_id': 10335, 'author': 'Mike Stone', 'author_id': 122, 'author_profile': 'https://Stackoverflow.com/users/122', 'pm_score': 2, 'selected': False, 'text': '<p>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.</p>\n\n<p>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:</p>\n\n<pre><code>first = "Mike"\nlast = "Stone"\nname = "#{first} #{last}"\n</code></pre>\n\n<p>These strings can also contain expressions, not just variables... such as:</p>\n\n<pre><code>str = "The count will be: #{count + 1}"\ncount = count + 1\n</code></pre>\n'}, {'answer_id': 10350, 'author': 'Mike Stone', 'author_id': 122, 'author_profile': 'https://Stackoverflow.com/users/122', 'pm_score': 8, 'selected': True, 'text': '<p>I looked at the ruby documentation for <code>StringIO</code>, and it looks like what you want is <a href="http://ruby-doc.org/stdlib/libdoc/stringio/rdoc/classes/StringIO.html#method-i-string" rel="noreferrer"><code>StringIO#string</code></a>, not <code>StringIO#to_s</code></p>\n\n<p>Thus, change your code to:</p>\n\n<pre><code>s = StringIO.new\ns &lt;&lt; \'foo\'\ns &lt;&lt; \'bar\'\ns.string\n</code></pre>\n'}, {'answer_id': 10358, 'author': 'palmsey', 'author_id': 521, 'author_profile': 'https://Stackoverflow.com/users/521', 'pm_score': 4, 'selected': False, 'text': '<p>Your example works in Ruby - I just tried it.</p>\n\n<pre><code>irb(main):001:0&gt; require \'stringio\'\n=&gt; true\nirb(main):002:0&gt; s = StringIO.new\n=&gt; #&lt;StringIO:0x2ced9a0&gt;\nirb(main):003:0&gt; s &lt;&lt; \'foo\'\n=&gt; #&lt;StringIO:0x2ced9a0&gt;\nirb(main):004:0&gt; s &lt;&lt; \'bar\'\n=&gt; #&lt;StringIO:0x2ced9a0&gt;\nirb(main):005:0&gt; s.string\n=&gt; "foobar"\n</code></pre>\n\n<p>Unless I\'m missing the reason you\'re using to_s - that just outputs the object id.</p>\n'}, {'answer_id': 1252057, 'author': 'Colin Curtin', 'author_id': 69464, 'author_profile': 'https://Stackoverflow.com/users/69464', 'pm_score': 5, 'selected': False, 'text': '<p>Like other IO-type objects in Ruby, when you write to an IO, the character pointer advances.</p>\n\n<pre><code>&gt;&gt; s = StringIO.new\n=&gt; #&lt;StringIO:0x3659d4&gt;\n&gt;&gt; s &lt;&lt; \'foo\'\n=&gt; #&lt;StringIO:0x3659d4&gt;\n&gt;&gt; s &lt;&lt; \'bar\'\n=&gt; #&lt;StringIO:0x3659d4&gt;\n&gt;&gt; s.pos\n=&gt; 6\n&gt;&gt; s.rewind\n=&gt; 0\n&gt;&gt; s.read\n=&gt; "foobar"\n</code></pre>\n'}, {'answer_id': 13276313, 'author': 'jmanrubia', 'author_id': 469697, 'author_profile': 'https://Stackoverflow.com/users/469697', 'pm_score': 5, 'selected': False, 'text': '<p>I did some benchmarks and the fastest approach is using the <code>String#&lt;&lt;</code> method. Using <code>StringIO</code> is a little bit slower.</p>\n\n<pre><code>s = ""; Benchmark.measure{5000000.times{s &lt;&lt; "some string"}}\n=&gt;   3.620000   0.100000   3.720000 (  3.970463)\n\n&gt;&gt; s = StringIO.new; Benchmark.measure{5000000.times{s &lt;&lt; "some string"}}\n=&gt;   4.730000   0.120000   4.850000 (  5.329215)\n</code></pre>\n\n<p>Concatenating strings using the <code>String#+</code> method is the slowest approach by many orders of magnitude:</p>\n\n<pre><code>s = ""; Benchmark.measure{10000.times{s = s + "some string"}}\n=&gt;   0.700000   0.560000   1.260000 (  1.420272)\n\ns = ""; Benchmark.measure{10000.times{s &lt;&lt; "some string"}}\n=&gt;   0.000000   0.000000   0.000000 (  0.005639)\n</code></pre>\n\n<p>So I think the right answer is that the equivalent to Java\'s <code>StringBuffer</code> is simply using <code>String#&lt;&lt;</code> in Ruby.</p>\n'}]
['https://Stackoverflow.com/questions/10323', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1190/']