[Boost-users] [iostreams] Closing a filtering_ostream

726 views
Skip to first unread message

Paul Giaccone

unread,
Oct 4, 2005, 12:35:34 PM10/4/05
to Boost...@lists.boost.org
How do you close a filtering_ostream object once you have finished
writing to it?

In my program below, I would expect the file "hello.bz2" to have been
written once the close() function has been called, but it is not the
case. The contents are not actually written until I exit the scope in
which the filtering_ostream object is defined (at which point the
destructor presumably does the job). (The file "some_text.txt" contains
just the text "hello world!" so I would expect it not to be written
until the file is closed.)

I would like to be able to do this explicitly and not have to rely on
the destruction of the object - could you explain how can this be done?

Another question: what should the second parameter to close() be? I've
used BOOST_IOS::trunc here, but is there some other more appropriate value?

Thanks,

Paul Giaccone


#include <fstream>
#include <iostream>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>

int main(void)
{
{
boost::iostreams::filtering_ostream out;
out.push(boost::iostreams::bzip2_compressor());
out.push(boost::iostreams::file_sink("hello.bz2", BOOST_IOS::trunc));
std::ifstream input_stream("some_text.txt");
boost::iostreams::copy(input_stream, out);
input_stream.close();

if (!boost::iostreams::flush(out))
{
std::cerr << "failed to write file" << std::endl;
}

boost::iostreams::close(out, BOOST_IOS::_Dummy_enum_val);
} //exiting scope closes the stream; close() seems not to

boost::iostreams::filtering_istream in;
in.push(boost::iostreams::bzip2_decompressor());
in.push(boost::iostreams::file_source("hello.bz2"));
boost::iostreams::copy(in, std::cout);
std::cout.flush();

return 0;
}

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Paul Giaccone

unread,
Oct 5, 2005, 7:37:21 AM10/5/05
to boost...@lists.boost.org
Paul Giaccone wrote:

>How do you close a filtering_ostream object once you have finished
>writing to it?
>
>
I tried calling out.reset() to the filtering_ostream object. This has
the desired effect, as the data is written to file before "out" falls
out of scope, but then when the end of the scope is reached, my program
crashes in the destructor.

If this is not the right way to flush the stream, what should I be doing
instead? I tried strict_sync() but this returned false because it looks
as though the compressor is not flushable (although I could not find
anything about this in the documentation).

I am working in Visual Studio .NET 7.1.

Call stack:

> MyProgram.exe!std::locale::locale(const std::locale &
_Right={...}) Line 231 + 0x29 C++
MyProgram.exe!std::basic_streambuf<char,std::char_traits<char>
>::pubimbue(const std::locale & _Newlocale={...}) Line 77 + 0xf C++
MyProgram.exe!std::basic_ios<char,std::char_traits<char>
>::imbue(const std::locale & _Loc={...}) Line 96 + 0x17 C++

MyProgram.exe!boost::io::basic_ios_locale_saver<char,std::char_traits<char>
>::restore() Line 241 + 0x1e C++

MyProgram.exe!boost::io::basic_ios_locale_saver<char,std::char_traits<char>
>::~basic_ios_locale_saver<char,std::char_traits<char> >() Line 238 +
0x2b C++

MyProgram.exe!boost::archive::basic_text_oprimitive<std::basic_ostream<char,std::char_traits<char>
>
>::~basic_text_oprimitive<std::basic_ostream<char,std::char_traits<char>
> >() Line 105 + 0xf C++

MyProgram.exe!boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::~text_oarchive_impl<boost::archive::text_oarchive>()
Line 72 + 0x80 C++
MyProgram.exe!boost::archive::text_oarchive::~text_oarchive() Line
89 + 0x34 C++
MyProgram.exe!MyClass::save(const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
filename={...}) Line 173 + 0x16 C++

Paul Giaccone

Alan M. Carroll

unread,
Oct 5, 2005, 9:26:22 AM10/5/05
to boost...@lists.boost.org
At 06:37 AM 10/5/2005, you wrote:
>Paul Giaccone wrote:
>
>>How do you close a filtering_ostream object once you have finished
>>writing to it?

Since you've noted that the destructor has the behavior you want, why not put the filtering_ostream in a scoped_ptr and .reset(0) the pointer when you're done with it?

Jonathan Turkanis

unread,
Oct 6, 2005, 2:10:42 PM10/6/05
to boost...@lists.boost.org
Alan M. Carroll wrote:
> At 06:37 AM 10/5/2005, you wrote:
>> Paul Giaccone wrote:
>>
>>> How do you close a filtering_ostream object once you have finished
>>> writing to it?
>
> Since you've noted that the destructor has the behavior you want, why
> not put the filtering_ostream in a scoped_ptr and .reset(0) the
> pointer when you're done with it?

This is not necessary: pop() and reset() both flush and close the current device
and then destroy it.

--
Jonathan Turkanis
www.kangaroologic.com

Jonathan Turkanis

unread,
Oct 6, 2005, 2:09:33 PM10/6/05
to boost...@lists.boost.org
Paul Giaccone wrote:
> Paul Giaccone wrote:
>
>> How do you close a filtering_ostream object once you have finished
>> writing to it?
>>
>>
> I tried calling out.reset() to the filtering_ostream object. This has
> the desired effect, as the data is written to file before "out" falls
> out of scope, but then when the end of the scope is reached, my
> program crashes in the destructor.

Could you post the program (or a simplified version)? When I add reset() to the
program in your previous message, it works fine.

> If this is not the right way to flush the stream, what should I be
> doing instead? I tried strict_sync() but this returned false because
> it looks as though the compressor is not flushable (although I could
> not find anything about this in the documentation).

Right, the compressors are not flushable. The purpose of strict_sync() is to
allow you to switch filters in the middle of a sequence of i/o operations. With
compression, switching filters before all the data is compressed will generally
result in garbage, so there's no point trying to implement flush().

> Paul Giaccone

--
Jonathan Turkanis
www.kangaroologic.com

Jonathan Turkanis

unread,
Oct 6, 2005, 8:40:59 PM10/6/05
to boost...@lists.boost.org
Sorry I didn't reply sooner -- I've been away for the last few days.

Paul Giaccone wrote:
> How do you close a filtering_ostream object once you have finished
> writing to it?

You can use either pop() or reset().

> In my program below, I would expect the file "hello.bz2" to have been
> written once the close() function has been called, but it is not the
> case. The contents are not actually written until I exit the scope in
> which the filtering_ostream object is defined (at which point the
> destructor presumably does the job).

reset() or pop() should work.

This also reflects a problem with filtering_ostream which I noticed only after
the feature freeze before the 1.33 release: copy calls close() on both its
arguments, but close() is a no-op for filtering_streams. Instead, close() should
probably call pop().

> (The file "some_text.txt"
> contains just the text "hello world!" so I would expect it not to be
> written until the file is closed.)

No, the implementation is free to flush the stream at any time. Also, copy
closes the stream.

> I would like to be able to do this explicitly and not have to rely on
> the destruction of the object - could you explain how can this be
> done?
>
> Another question: what should the second parameter to close() be?
> I've used BOOST_IOS::trunc here, but is there some other more
> appropriate value?

close() is meant to be called by the iostreams library; you shouldn't have to
call it yourself.

Thanks for using the iostreams library!

> Thanks,
>
> Paul Giaccone

--
Jonathan Turkanis
www.kangaroologic.com




Paul Giaccone

unread,
Oct 7, 2005, 4:39:30 AM10/7/05
to boost...@lists.boost.org
Jonathan Turkanis wrote:

>Paul Giaccone wrote:
>
>
>>Paul Giaccone wrote:
>>
>>
>>
>>>How do you close a filtering_ostream object once you have finished
>>>writing to it?
>>>
>>>
>>>
>>>
>>I tried calling out.reset() to the filtering_ostream object. This has
>>the desired effect, as the data is written to file before "out" falls
>>out of scope, but then when the end of the scope is reached, my
>>program crashes in the destructor.
>>
>>
>
>Could you post the program (or a simplified version)? When I add reset() to the
>program in your previous message, it works fine.
>
>
>
>>If this is not the right way to flush the stream, what should I be
>>doing instead? I tried strict_sync() but this returned false because
>>it looks as though the compressor is not flushable (although I could
>>not find anything about this in the documentation).
>>
>>
>
>Right, the compressors are not flushable. The purpose of strict_sync() is to
>allow you to switch filters in the middle of a sequence of i/o operations. With
>compression, switching filters before all the data is compressed will generally
>result in garbage, so there's no point trying to implement flush().
>
>
Thanks for the confirmation, Jonathan. The program I sent in my
original posting is the exact program I am testing.

It's strange though that reset() should crash for me but not for you.

Paul Giaccone

Paul Giaccone

unread,
Oct 7, 2005, 4:40:52 AM10/7/05
to boost...@lists.boost.org
I didn't see this message before my earlier reply. Thank you for your
detailed explanation of what is happening - it's very useful.

Paul Giaccone

Jonathan Turkanis

unread,
Oct 7, 2005, 12:49:27 PM10/7/05
to boost...@lists.boost.org
Paul Giaccone wrote:
> Jonathan Turkanis wrote:

>> close() is meant to be called by the iostreams library; you
>> shouldn't have to call it yourself.
>>
>>
> I didn't see this message before my earlier reply.

That's because I forgot to send it ;-)

> Thank you for your
> detailed explanation of what is happening - it's very useful.

Glad to help.

> Paul Giaccone

--
Jonathan Turkanis
www.kangaroologic.com



Jonathan Turkanis

unread,
Oct 7, 2005, 12:46:13 PM10/7/05
to boost...@lists.boost.org
Paul Giaccone wrote:
> Jonathan Turkanis wrote:
>
>> Paul Giaccone wrote:

>>> If this is not the right way to flush the stream, what should I be
>>> doing instead? I tried strict_sync() but this returned false
>>> because it looks as though the compressor is not flushable
>>> (although I could not find anything about this in the
>>> documentation).

>> Right, the compressors are not flushable. The purpose of
>> strict_sync() is to allow you to switch filters in the middle of a
>> sequence of i/o operations. With compression, switching filters
>> before all the data is compressed will generally result in garbage,
>> so there's no point trying to implement flush().

> Thanks for the confirmation, Jonathan. The program I sent in my
> original posting is the exact program I am testing.

The stack trace you posted looks like it contains some code from
Boost.Serialization.

> It's strange though that reset() should crash for me but not for you.

Definitely. What compiler options are you using?

> Paul Giaccone

--
Jonathan Turkanis
www.kangaroologic.com



Paul Giaccone

unread,
Oct 10, 2005, 4:37:35 AM10/10/05
to boost...@lists.boost.org
Jonathan Turkanis wrote:

>Paul Giaccone wrote:
>
>
>>Thanks for the confirmation, Jonathan. The program I sent in my
>>original posting is the exact program I am testing.
>>
>>
>
>The stack trace you posted looks like it contains some code from
>Boost.Serialization.
>
>
>>It's strange though that reset() should crash for me but not for you.
>>
>>
>
>Definitely. What compiler options are you using?
>
>

Compile flags:

/Od /I "D:\boost\include\boost-1_33" /D "WIN32" /D "_DEBUG" /D
"_CONSOLE" /D "_MBCS" /Gm /EHsc /RTC1 /MLd /Fo"Debug/"
/Fd"Debug/vc70.pdb" /W3 /nologo /c /Wp64 /ZI /TP

Link flags:

/OUT:"Debug/CompressionTest.exe" /INCREMENTAL /NOLOGO
/LIBPATH:"D:\boost\lib" /DEBUG /PDB:"Debug/CompressionTest.pdb"
/SUBSYSTEM:CONSOLE /MACHINE:X86 kernel32.lib user32.lib gdi32.lib
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib
oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

Browse information (probably not relevant):

/nologo

No build events; no custom build step.

This is a debug version of the program.

Paul
Reply all
Reply to author
Forward
0 new messages