【问题标题】:Reading Binary Data with streambuf in C++ through a Class通过类在 C++ 中使用 streambuf 读取二进制数据
【发布时间】:2012-10-27 18:28:39
【问题描述】:

我是一名 c 程序员,正试图在 c++ 中开始我生命的新阶段(我知道我仍在使用下面的 printf,但那是因为格式化是如此简单)。我希望从对象的成员函数中打印出数据文件的第一个字节。我认为我的流缓冲区在读取数据之前就被破坏了,但我不知道该怎么做。

我的班级如下所示

class MyParser {
    MyParser(string filepath);
    void readHeader();

    streambuf *pbuf;
    long size;
}

我的构造函数打开文件,取出缓冲区,输出第一个字节并返回。 (我认为pbuf 在这段代码的末尾会死掉)。此代码输出First Byte (in constructor): 0x8C

MyParser::MyParser(string filepath) {
    ifstream file(filepath.c_str(), ios::in | ios::binary)
    pbuf = file.rdbuf();
    size = pbuf->pubseekoff(0,ios::end,ios::in);
    pbuf->pubseekpos(0,ios::in);

    unsigned char byte = pbuf->sgetc();
    printf("First Byte (in constructor): 0x%02X\n", byte);

    return;
}

我的读取头正在转储第一个字节,但根据输出,所有看到的是First Byte (in readHeader): 0xFF

void MyParser::readHeader() {
    unsigned char byte = pbuf->sgetc();
    printf("First Byte (in readHeader): 0x%02X\n", byte);
}

我的 main 只是创建了一个解析器并尝试读取Header

void main() {
    MyParser parser("../data/data.bin");
    parser.readHeader();
}

我认为我的问题的解决方案是创建一个 new 流缓冲区,但 new streambuf(file.rdbuf()) 不适合我。有什么建议吗?

【问题讨论】:

标签: c++ object constructor streambuf


【解决方案1】:

您的程序具有未定义的行为:您保留的流缓冲区归您在构造函数主体中打开的std::ifstream 所有。当这个对象死亡时,流缓冲区也会被释放。避免此问题的最简单方法是让您的std::ifstream 成为您的类的成员:这将流的生命周期绑定到您的对象。使用std::istream 接口进行解析也可能比有些尴尬的std::streambuf 接口更容易。

如果你真的只想使用一个流缓冲区,你可以使用new filebufopen()直接分配一个std::filebuf文件流。要保留指向它的指针,您可能会使用std::unique_ptr<std::filebuf>(或std::auto_ptr<std::filebuf>,如果您不使用C++ 2011)。使用指针类安排对象的自动释放。当然,指针仍然是你的类的成员,以确保生命周期正确。

您复制流缓冲区的尝试无效,因为流缓冲区不可复制。您需要直接创建文件缓冲区:

MyParser::MyParser(std::string const& filename)
    : pbuf(new std::filebuf)
{
    this-pbuf->open("whatever", std::ios_base::in);
    ...
}

【讨论】:

  • 谢谢。将文件流保留为成员并在初始化列表中打开文件有效。我正在尝试编写一些最终会从二进制网络数据流中读取二进制数据的东西,所以我觉得将来将整个缓冲区读入内存需要更多更改。
【解决方案2】:

您需要一些新的 C++ 教材,因为(对不起)但这是错误的。您需要将文件流声明为成员,在此程序中的任何地方都不需要任何new,而且几乎没有人需要处理streambuf

class MyParser {
    std::ifstream file;
public:
    MyParser(string filepath) {
        file.open(filepath, std::ios::in | std::ios::binary );
        char byte;
        file.read(sizeof(byte), &byte);
        printf("First Byte (in constructor): 0x%02X\n", byte);        
    }
    void readHeader() {
        char byte;
        file.read(sizeof(byte), &byte);
        printf("First Byte (in readHeader): 0x%02X\n", byte);   
    }
};

【讨论】:

  • 参数在你读取时是倒退的,应该是指针,大小而不是大小,指针。
猜你喜欢
  • 2016-04-03
  • 2012-05-05
  • 1970-01-01
  • 2011-11-22
  • 2014-01-08
  • 1970-01-01
  • 2012-07-23
  • 2021-12-24
  • 1970-01-01
相关资源
最近更新 更多