Синтаксис Param для замены boost filtering_stream для std :: ofstream

Некоторые основные вопросы о boost filtering_streams. У меня есть десятки функций, которые принимают параметр std :: ofstream&

void foo(std::ofstream& outStream)
{
// lots of operations, like this:
outStream << "various bits of text";
}

void StreamSomeTextToFile(char* fileName)
{
ofstream myFileStream(fileName, ios::out | ios::app | ios::binary);
foo(myFileStream);
myFileStream.close();
}

Теперь я хотел бы использовать boost filtering_stream для вывода в сжатый ZIP-файл. Обычно цитируемый тестовый код boost filtering_streams для упаковки и распаковки компилируется, связывается и отлично работает для меня. Я хотел бы заменить filtering_stream:

void StreamSomeCompressedTextToFile(char* fileName)
{
ofstream myFileStream(destPath, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> myCompressedFileStream;
myCompressedFileStream.push(boost::iostreams::zlib_compressor());
myCompressedFileStream.push(myFileStream);

foo(myCompressedFileStream);    // I can't just pass myCompressedFileStream to foo(std::ofstream&), right?
myFileStream.close();
}

ТРИ ВОПРОСА:

1) Делать все мои функции, которые ранее принимали std :: ofstream& outStream теперь нужно принять параметр типа boost :: iostreams :: filtering_streambuf& ? Или существует правильный тип параметра, чтобы эти многочисленные («foo») функции могли работать с типом потока типа EITHER?

2) В моих простых тестовых случаях я не смог использовать синтаксис оператора потока с filtering_streambuf:

myCompressedFileStream << "some text";

это породило ошибку: нет совпадения для оператора ‘<<». Я также имел ошибки компиляции с write ():

error: 'class boost::iostreams::filtering_streambuf<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>' has no member named 'write

3) В коде примера общего тестового примера (ниже) я был озадачен тем, что не могу найти файл «hello.z» после того, как он был создан. Код распаковки (также ниже) четко ссылается на него — так где его можно найти? ПРИМЕЧАНИЕ: местоположение было наконец обнаружено: оно было в / Library / Preferences /

void pack()
{
std::ofstream file("hello.z", std::ios_base::out | std::ios_base::binary);

boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::zlib_compressor());
out.push(file);
char data[5] = {'a', 'b', 'c', 'd', 'e'};
boost::iostreams::copy(boost::iostreams::basic_array_source<char>(data, sizeof(data)), out);
file.close();
}

void unpack()
{
std::fstream file("hello.z", std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
boost::iostreams::copy(in, std::cout);
}

Кстати: XCode 3.2.6, GNU 4.0, OS X 10.6.8

4

Решение

Принимая вопросы по порядку:

1: поток буфер объекты (такие как boost :: iostream :: filtering_streambuf или std :: streambuf) не являются взаимозаменяемыми с объектами потока (такими как std :: ostream или реализация boost). При этом вы можете передать объект streambuf, такой как «myCompressedFileStream», в конструктор объекта ostream (это повышение iostream учебник дает достойное объяснение с примерами). А поскольку потоковые буферы boost совместимы с таковыми в стандартной библиотеке, вам не нужно изменять какие-либо функции, принимающие ссылки std :: ostream / ofstream. Вы просто не можете передавать streambufs как потоки.

2: То же, что и выше, оператор вставки определен для потоков, а не для streambuf.

3: Обычно файлы без предшествующего имени каталога создаются в каталоге исполняемого файла. При этом я обнаружил, что иногда Finder несколько медленно отображает файлы, которые обновляются / создаются не-Finder-процессами. Я не испытывал этих проблем в Терминале, используя ls. Не знаю, связано ли это с вашей проблемой.

3

Другие решения

УСПЕХ!

Сочетание подсказок от Пола Шеллина (выше) и нескольких на Boost-пользователей привело к ответу:

1) Повышающий пользователь Фредерик отметил, что «ничего не происходит [s] до тех пор, пока выходной_файл [filtering_ostream] не будет уничтожен. Поэтому заключите в {}». Это было основной недостающий кусок, потому что я пытался сделать file.close () в моем оффстриме ДО того, как мой filtering_streambuf был уничтожен. Это объясняет, почему файл был пустым!

Перечитывание документации выявило:

  "By default, if the Device at the end of the chain is popped
or if the filtering_stream is complete when it is destroyed,
all the filters and devices in the chain are closed using the
function close. This behavior can be modified using the member
function set_auto_close"

Это говорит о том, что нет необходимости «извлекать» компрессор () или ofstream (файл) из стека filtering_stream, а также вызывать close (). Просто уничтожьте объект filtering_stream, и все будет записано и очищено. Непонятная деталь, противоречащая ожиданиям.

3) Повышающий пользователь Хольгер Герт спросил, почему я использовал filtering_streambuf, когда я мог использовать filtering_stream. Правда, я не был уверен, однако, в своих экспериментах я не мог ни построить ostream (который я должен был передать другим функциям) из filtering_stream, ни я не мог передать filtering_stream вместо ostream, который мне требовался.

Даже после прочтения нескольких статей о filtering_streambuf и filtering_stream я все еще не понимаю, как и почему (ДЛЯ МОЕЙ ЦЕЛИ) я бы использовал filtering_stream вместо создания ostream из filtering_streambuf.

ТАК, ЗАПИСАТЬ:

1) Создайте отдельный ostream от filtering_streambuf и передайте TH для foo () или оператора Stream Insertion (т.е. <<).

2) Не вызывайте myFileStream.close ();

2