我是 boost 及其 iostreams 包的新手,发现文档有点薄。希望有人能纠正我。我正在尝试转换我不久前编写的一小段 C# 流代码,以便在压缩流中读取。
byte[] data = new byte[length - 1];
file.Read(data, 0, data.Length);
Stream ret = new ZlibStream(new MemoryStream(data), CompressionMode.Decompress, true);
return ret;
来自文件的一部分的数据被读入内存缓冲区,该缓冲区为 zlib 解压缩器提供数据。随着时间的推移,流的消费者会选择它,当它完成时会调用Close()
which 结合垃圾收集器将清理所有资源。 注意:一个重要的区别是我不是要解压整个文件,只是其中的一小部分。该文件已被搜索到某个内部位置,并且长度相对于文件的完整大小而言很小。
我正在尝试使用 Boost 在 C++ 代码中找到与此等效的最佳方法。到目前为止,我的道德等同于上述(未经测试):
char * data = new char[length - 1];
_file.read(data, length - 1);
io::stream_buffer<io::basic_array_source<char> > buffer(data, length - 1);
io::filtering_stream<io::input> * in = new io::filtering_stream<io::input>;
in->push(io::zlib_decompressor());
in->push(buffer);
return in;
我假设我可以返回包装在 a 中的过滤shared_ptr
流,这将使消费者不必担心删除流,但我也有新的数据缓冲区。理想情况下,我希望消费者只调用close()
流,并且某些机制(例如回调)会清理过滤器中的底层资源。要求消费者将流传递给显式释放函数也是可以接受的,但我仍然不完全确定如何首先获取底层数据缓冲区。
更清洁的替代解决方案也受到欢迎。
更新 1
我尝试松散地抓住 Cat Plus Plus 关于 std::vector 支持的驱动程序的评论。这不是我所做的,但这是我迄今为止想出的。在以下代码中,我有一个 boost::shared_array-backed 驱动程序,基于 boost 驱动程序示例。
namespace io = boost::iostreams;
class shared_array_source
{
public:
typedef char char_type;
typedef io::source_tag category;
shared_array_source (boost::shared_array<char> s, std::streamsize n)
: _data(s), _pos(0), _len(n)
{ }
std::streamsize read (char * s, std::streamsize n)
{
std::streamsize amt = _len - _pos;
std::streamsize result = (std::min)(amt, n);
if (result != 0) {
std::copy(_data.get() + _pos, _data.get() + _pos + result, s);
return result;
}
else {
return -1;
}
}
private:
boost::shared_array<char> _data;
std::streamsize _pos;
std::streamsize _len;
};
然后我有我的函数返回一个流
io::filtering_istream * GetInputStream (...)
{
// ... manipulations on _file, etc.
boost::shared_array<char> data(new char[length - 1]);
_file.read(data.get(), length - 1);
shared_array_source src(data, length - 1);
io::stream<shared_array_source> buffer(src);
io::filtering_istream * in = new io::filtering_istream;
in->push(io::zlib_decompressor());
in->push(buffer);
// Exhibit A
// uint32_t ui;
// rstr->read((char *)&ui, 4);
return in;
}
在我的测试程序的主要功能中:
int main () {
boost::iostreams::filtering_istream * istr = GetInputStream();
// Exhibit B
uint32_t ui;
rstr->read((char *)&ui, 4);
return 0;
}
忽略我返回的指针永远不会被释放的事实——我尽可能简单。当我运行它时会发生什么?如果我取消注释附件 A 中的代码,我会在ui
. 但是当我点击图表 B 时,我在 Boost 中深深地、深深地、深深地崩溃(有时)。好吧,废话,我超出了范围,事情就坏了,一定是一些当地人在解构并把一切都搞砸了。 data
在 shared_arrayin
中,在堆上,并且压缩器是根据文档构造的。
boost 构造函数或函数之一是否获取了对堆栈上对象的引用(即 io::stream 或 filtering_stream 的推送)?如果是这样的话,我有点回到堆上的非托管对象的问题上。