在下面的代码中,我有一个腐败的“hello.bz2”,它有超出EOF的杂散字符。
有没有办法让boost :: iostreams :: copy()调用抛出?
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
int main()
{
using namespace std;
using namespace boost::iostreams;
ifstream file("hello.bz2", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(bzip2_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);
}
编辑: 请忽略迄今为止引起最多关注的路线; EOF。请假设使用损坏的bzip2文件。 我使用“EOF”表示我在文件上运行bzcat时出现的错误
bzcat hello.bz2
hello world
bzcat: hello.bz2: trailing garbage after EOF ignored
答案 0 :(得分:2)
std :: ios_base :: failure 是“通过Iostreams库中的函数作为异常引发的所有对象类型的基类,用于报告在流缓冲区操作期间检测到的错误。”
升级文档class bzip2_error : public std::ios_base::failure {
public:
bzip2_error(int error);
int error() const;
};
bzip2_error 是使用bzip2过滤器时引发的特定异常,该过滤器继承自 std :: ios_base :: failure 。如您所见,它是通过传入一个表示错误代码的整数来构造的。它还有一个方法 error(),它返回它构造的错误代码。
文档列出了bzip2错误代码如下:
修改强> 我还想澄清一下boost :: iostreams :: copy()不会是抛出异常的那个,而是bzip2过滤器。只有iostream或过滤器会抛出异常,只复制使用 iostream / filter,这可能会导致iostream / filter抛出异常。
**编辑2 ** 看来问题出在你所期望的bzip2_decompressor_impl上。当bz2文件为空时,我已经复制了无限旋转循环。我花了一些时间来弄清楚如何构建boost并与bzip2,zlib和iostreams库链接,看看我是否可以复制你的结果。
g++ test.cpp -lz -lbz2 boostinstall/boost/bin.v2/libs/iostreams/build/darwin-4.2.1/release/link-static/threading-multi/libboost_iostreams.a -Lboostinstall/boost/bin.v2/libs/ -Iboost/include/boost-1_42 -g
TEST.CPP:
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
int main()
{
using namespace std;
using namespace boost::iostreams;
try {
ifstream file("hello.bz2", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(bzip2_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);
}
catch(const bzip2_error& exception) {
int error = exception.error();
if(error == boost::iostreams::bzip2::data_error) {
// compressed data stream is corrupted
cout << "compressed data stream is corrupted";
}
else if(error == boost::iostreams::bzip2::data_error_magic)
{
// compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'
cout << "compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'";
}
else if(boost::iostreams::bzip2::config_error) {
// libbzip2 has been improperly configured for the current platform
cout << "libbzip2 has been improperly configured for the current platform";
}
}
}
调试:
gdb a.out
(gdb) b bzip2.hpp:344
有一个循环在symmetric.hpp中驱动bzip2的解压缩:109:
while (true)
{
// Invoke filter if there are unconsumed characters in buffer or if
// filter must be flushed.
bool flush = status == f_eof;
if (buf.ptr() != buf.eptr() || flush) {
const char_type* next = buf.ptr();
bool done =
!filter().filter(next, buf.eptr(), next_s, end_s, flush);
buf.ptr() = buf.data() + (next - buf.data());
if (done)
return detail::check_eof(
static_cast<std::streamsize>(next_s - s)
);
}
// If no more characters are available without blocking, or
// if read request has been satisfied, return.
if ( (status == f_would_block && buf.ptr() == buf.eptr()) ||
next_s == end_s )
{
return static_cast<std::streamsize>(next_s - s);
}
// Fill buffer.
if (status == f_good)
status = fill(src);
}
bzip2_decompressor_impl的filter方法bzip2.hpp:344在symmetric.hpp上调用:117:
template<typename Alloc>
bool bzip2_decompressor_impl<Alloc>::filter
( const char*& src_begin, const char* src_end,
char*& dest_begin, char* dest_end, bool /* flush */ )
{
if (!ready())
init();
if (eof_)
return false;
before(src_begin, src_end, dest_begin, dest_end);
int result = decompress();
after(src_begin, dest_begin);
bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
return !(eof_ = result == bzip2::stream_end);
}
我认为问题很简单,bzip2_decompressor_impl的eof_标志永远不会被设置。除非它假设以某种神奇的方式发生,我不明白,它由bzip2_decompressor_impl类拥有,并且它只被设置为false。所以当我们这样做时:
cat /dev/null > hello.bz2
我们得到一个永不停止的旋转循环,当EOF被击中时我们不会中断。这肯定是一个错误,因为其他程序(如vim)在打开以类似方式创建的文本文件时没有问题。但是,当bz2文件被“损坏”时,我能够让过滤器抛出:
echo "other corrupt" > hello.bz2
./a.out
compressed data stream does not begin with the 'magic' sequence 'B' 'Z' 'h'
有时候你必须采取一些盐的开源代码。你的bz2更有可能被破坏并正确抛出。但是,/ dev / null案例是一个严重的错误。我们应该将它提交给boost dev,以便他们能够修复它。
答案 1 :(得分:-1)
你如何在文件末尾之外有杂散字符?
如果您的意思是该文件中包含垃圾数据,那么解压缩算法如何能够判断数据是否无效以便能够对throw
做出决定?