C ++ 11 boost :: iostreams :: filtering_stream delete

У меня есть некоторые данные, которые я хочу отформатировать и вывести, либо в необработанном текстовом файле, либо в сжатом текстовом файле .gz.

Таким образом, я хотел сделать что-то вроде этого:

shared_ptr<ofstream> file = make_shared<ofstream>(filename.c_str());
shared_ptr<ostream> stream;
if (compressed) {
stream = getCompressedStream(*file);
} else {
stream = std::move(file);
}

for (auto c = data.begin(); c != data.end(); ++c) {
*stream << **c << "\t" << (*c)->getThing() << endl;
}

С getCompressedStream функция, которая расшифровывает поток и возвращает новый незашифрованный поток:

std::unique_ptr<std::ostream> getCompressedStream(std::ofstream& file)
{
typedef io::filtering_ostream filter;
std::unique_ptr<filter> out = std::unique_ptr<filter> (new filter());
out->push(io::gzip_compressor());
out->push(file);
return std::move(out);
}

Поэтому я хотел, чтобы getCompressedStream абстрагировал вызовы для увеличения lib, чтобы в моей основной программе я использовал только std-потоки.

Это не работает: файл .gz поврежден / не читается.

Согласно этому нить, вывод filtering_stream выполняется при уничтожении объекта. Таким образом, я не знаю, можно ли это сделать чисто с shared_ptr. Я не знаю, был ли файл или поток уничтожен первым, и я предполагаю, что это приводит к проблемам.

Как вы думаете, реализация getCompressedStream таким образом возможна? Что бы вы изменили?

Спасибо

редактировать : Это работает, если я переключаюсь на обычные указатели вместо общих указателей и явно удаляю поток перед файлом.

0

Решение

Я не уверен. Настоящая проблема заключается в том, что вы никогда явно не
закрой ofstreamтак что вы понятия не имеете, что происходит
на. (За исключением случаев, когда вы собираетесь
удалить новый файл в любом случае, вы должны проверить состояние
ofstream объект после близко, чтобы знать, все ли
удалось или нет.) В целом, ваше решение кажется чрезмерным
сложный для меня; вы пытаетесь сделать слишком много в одном
функция. Как я обычно это делаю (с моей собственной фильтрацией
streambuf, который предшествует буст-версиям на несколько лет)
сделать что-то вроде:

std::ofstream file( filename.c_str() );
if ( compressed ) {
CompressedStreambuf c( file );
outputData( file );
} else {
outputDate( file );
}
file.close();
if ( !file ) {
remove( filename.c_str() );   //  Since it isn't complete
//  Ensure that program return code is failure.
}

Конечно, моя собственная фильтрация streambuf работает немного по-другому
чем те из Boost: конструктор принимает ostream вставки
фильтр перед ostreamи деструктор сбрасывает
и удаляет фильтр (вариант RAII). Но это не должно быть
слишком сложно сделать оболочку классов Boost для поддержки
этот.

Преимущество этого решения в том, что все гарантировано
быть построенным и разрушенным в правильном, вложенном порядке,
потому что нет динамического распределения, которое позволило бы
произвольный порядок.

0

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector