Clearing StringIO

I'm working with StringIO to write some test code and it is behaving strangely. Check out this example:

irb(main):001:0> require "stringio"
=> true
irb(main):002:0> fake_file = StringIO.new
=> #<StringIO:0x3119cc>
irb(main):003:0> fake_file.puts "This is a test."
=> nil
irb(main):004:0> fake_file.string
=> "This is a test.\n"
irb(main):005:0> fake_file.truncate(0)
=> 0
irb(main):006:0> fake_file.string
=> ""
irb(main):007:0> fake_file.puts " <= Junk!"
=> nil
irb(main):008:0> fake_file.string
=> "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 <= Junk!\n"

Is that a bug? Yuck.

I hand my "fake_file" off to some code to play with, but keep a reference for my testing purposes. At times, I need to clear the accumulated output, but as you can see truncate() is giving me fits.

Can anyone suggest how I might clear the StringIO object, without replacing it?

Thanks.

James Edward Gray II

I'm working with StringIO to write some test code and it is behaving
strangely. Check out this example:

irb(main):001:0> require "stringio"
=> true
irb(main):002:0> fake_file = StringIO.new
=> #<StringIO:0x3119cc>
irb(main):003:0> fake_file.puts "This is a test."
=> nil
irb(main):004:0> fake_file.string
=> "This is a test.\n"
irb(main):005:0> fake_file.truncate(0)
=> 0
irb(main):006:0> fake_file.string
=> ""
irb(main):007:0> fake_file.puts " <= Junk!"
=> nil
irb(main):008:0> fake_file.string
=> "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 <=
Junk!\n"

Is that a bug? Yuck.

I hand my "fake_file" off to some code to play with, but keep a
reference for my testing purposes. At times, I need to clear the
accumulated output, but as you can see truncate() is giving me fits.

Can anyone suggest how I might clear the StringIO object, without
replacing it?

I think #truncate simply memset()s the buffer but it does not
change the position of the file pointer, so you would probably
need to #seek 0, as well.

Thanks.

James Edward Gray II

E

···

Le 26/4/2005, "James Edward Gray II" <james@grayproductions.net> a écrit:

--
template<typename duck>
void quack(duck& d) { d.quack(); }

this is consistent with file behaviour:

[ahoward@localhost ~]$ env PAGER=cat man truncate | grep pointer
        The file pointer is not changed.

try:

   irb(main):005:0> fake_file.truncate(fake_file.rewind)

hth.

-a

···

On Wed, 27 Apr 2005, James Edward Gray II wrote:

I'm working with StringIO to write some test code and it is behaving
strangely. Check out this example:

irb(main):001:0> require "stringio"
=> true
irb(main):002:0> fake_file = StringIO.new
=> #<StringIO:0x3119cc>
irb(main):003:0> fake_file.puts "This is a test."
=> nil
irb(main):004:0> fake_file.string
=> "This is a test.\n"
irb(main):005:0> fake_file.truncate(0)
=> 0

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
although gold dust is precious, when it gets in your eyes, it obstructs
your vision. --hsi-tang

===============================================================================

Saynatkari wrote:

I think #truncate simply memset()s the buffer but it does not
change the position of the file pointer, so you would probably
need to #seek 0, as well.

Very odd. From the man page:

http://www.opengroup.org/onlinepubs/009695399/functions/truncate.html

truncate - truncate a file to a specified length

The truncate() function shall cause the regular file named by path to have a size which shall be equal to length bytes.

If the file previously was larger than length, the extra data is discarded. If the file was previously shorter than length, its size is increased, and the extended area appears as if it were zero-filled.

And on Linux:

http://linux.com.hk/PenguinWeb/manpage.jsp?name=truncate&section=2

Cheers,
--binkley

Thanks for the tip.

James Edward Gray II

···

On Apr 26, 2005, at 2:18 PM, Saynatkari wrote:

I think #truncate simply memset()s the buffer but it does not
change the position of the file pointer, so you would probably
need to #seek 0, as well.

[ahoward@localhost ~]$ env PAGER=cat man truncate | grep pointer
       The file pointer is not changed.

This is highly system-dependent (although I am unable to tell if the behavior has standardized over time):

http://www.faqs.org/faqs/unix-faq/faq/part3/section-3.html

<<
For systems which support the ftruncate function, there are
       three known behaviours:

       BSD 4.2 - Ultrix, SGI, LynxOS
               - truncation doesn't grow file
               - truncation doesn't move file pointer

       BSD 4.3 - SunOS, Solaris, OSF/1, HP/UX, Amiga
               - truncation can grow file
               - truncation doesn't move file pointer

       Cray - UniCOS 7, UniCOS 8
               - truncation doesn't grow file
               - truncation changes file pointer
>>

Cheers,
--binkley

···

Ara.T.Howard@noaa.gov wrote:

Saynatkari wrote:

I think #truncate simply memset()s the buffer but it does not
change the position of the file pointer, so you would probably
need to #seek 0, as well.

rewind is slightly better than seek 0

···

--
Best regards,

Alexey Verkhovsky

Ruby Forum: http://ruby-forum.org (moderator)
RForum: http://rforum.andreas-s.net (co-author)
Instiki: http://instiki.org (maintainer)