我可以用c++中的istream读取二进制数据吗

Can I read in binary data with istream in c++?

本文关键字:二进制 数据 读取 istream c++ 中的 我可以      更新时间:2023-10-16

现在我正在使用istream读取数据。我有两个文本,我想以字符串和数字的形式读取,还有散列,它们被读取到字符数组中。由于散列实际上是随机的,所以当我试图读回它并点击EOF(这是散列的一部分)时,我遇到了障碍。有没有一种方法可以在不使用fread的情况下实现这一点。此外,是否有同时使用istream和fread的方法?我不必手动解析整数和字符串。最后,使用fgets获取未知长度字符串的最佳方法是什么。

谢谢,Eric

编辑:这是代码:

string dummy;
ifstream in(fileName);
for(int i=0; i<numVals; i++)
{
    int hashLen;
    in>>hashLen;
    char cc;
    in.get(cc);//Get the space in between
    cout<<"Got first byte: "<<(int)cc<<endl;
    char * hashChars = new char[hashLen];
    in.read(hashChars, hashLen);
    for(int j =0; j <hashLen; j++)
    {
        char c = hashChars[j];
       unsigned char cc = reinterpret_cast<unsigned char&>(c);
        cout<<"Got byte: "<<(int)c<<(int)cc<<endl;
        if(in.fail())
        {
            cout<<"Failed! "<<in.eof()<<" "<<in.bad()<<endl;
        }
    }
delete hashChars;
    getline(in,dummy);//get a dummy line
    cout<<"Dummy: "<<dummy<<" numvals: "<<numVals<<" i: "<<i<<" hashLength: "<<hashLen<<endl;
}

我的输出看起来像:

1> 得到第一个字节:32

1> 得到字节:4 4

1> 获取字节:-14 242

1> 获取字节:108 108

1> 得到字节:87 87

1> 得到字节:113 113

1> 获取字节:-116 140

1> 获取字节:-106 150

1> 获取字节:-35 221

1> 获取字节:0 0

1> 获取字节:-91 165

1> 获取字节:39 39

1> 获取字节:111 111

1> 得到字节:7 7

1> 获取字节:126 126

1> 获取字节:16 16

1> 获取字节:-42 214

1> 伪:numvals:35 i:12 hashLength:16

1> 得到第一个字节:32

1> 得到字节:14 14

1> 失败!10

1> 获取字节:-65 191

1> 失败!10

1> 获取字节:-107 149

1> 失败!10

1> 获取字节:-44 212

1> 失败!10

1> 获取字节:-60 196

1> 失败!10

1> 获取字节:-51 205

1> 失败!10

1> 获取字节:-51 205

1> 失败!1 0

读取二进制数据时,通常需要使用标志std::ios_base::binary打开std::ifstream。由此产生的差异相当小,但它们通常很重要。

在你的代码中有一些奇怪的地方你可能想修复:

  • 您总是需要在读取后检查操作是否成功,例如使用if (in.read(hashChars, hashLen)) { ... }
  • 不需要使用reinterpret_cast<...>(),它总是具有实现定义的语义。您应该使用static_cast<unsigned char>(c)
  • 您分配了一个字符数组,但使用delete p释放它。您需要使用delete[] p。使用delete p会导致未定义的行为。实际上根本不需要使用newdelete,因为std::vector<char> hashChars(hashLen)可以自动管理内存

上面的请求中嵌入了一些[残缺的]问题(因此问题/答案是对所问内容的猜测):

  • 你能在同一个流上混合std::istream::read()fread()吗(我想这就是问题所在):除非流恰好是std::cin,它与stdin从同一个源读取,否则不能立即混合。如果要在同一文件中同时使用std::istream::read()fread(),则需要用合适的std::streambuf包装FILE*,并用相应的对象初始化std::istream
  • 如何使用fgets()读取任意大小的行?你不能。fgets()的缓冲区在尝试填充之前被分配,并且总是可以在到达换行符之前被填充。但是,您可以使用std::getline()读取任意长的行。如果您只是想跳过这一行,则可以在使用std::istream时使用in.ignore(std::numeric_limits<std::streamsize>::max(), 'n')。我不知道FILE*是否也有类似的操作