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

时间:2013-08-16 23:45:35

标签: c++ fread istream

现在我正在使用istream来读取数据。我有两个文本,我想读作字符串和数字,哈希读入字符数组。由于哈希是有效随机的,当我尝试将其读回并点击EOF(这是哈希的一部分)时,我遇到了障碍。有没有办法在不诉诸恐惧的情况下实现这一目标。此外,有一个使用istream和fread一些我不必手动解析整数和字符串。最后,使用fgets获取未知长度字符串的最佳方法是什么。

谢谢, 埃里克

编辑: 这是代码:

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&gt;得到第一个字节:32

1&gt;得到字节:4 4

1&gt;得到字节:-14 242

1&gt;得到字节:108 108

1&gt;得到字节:87 87

1&gt;得到字节:113 113

1&gt;得到字节:-116 140

1&gt;得到字节:-106 150

1&gt;得到字节:-35 221

1&gt;得到字节:0 0

1&gt;得到字节:-91 165

1&gt;得到字节:39 39

1&gt;得到字节:111 111

1&gt;得到字节:7 7

1&gt;得到字节:126 126

1&gt;得到字节:16 16

1&gt;得到字节:-42 214

1&gt; Dummy:numvals:35 i:12 hashLength:16

1&gt;得到第一个字节:32

1&gt;得到字节:14 14

1&GT;失败! 1 0

1&gt;得到字节:-65 191

1&GT;失败! 1 0

1&gt;得到字节:-107 149

1&GT;失败! 1 0

1&gt;得到字节:-44 212

1&GT;失败! 1 0

1&gt;得到字节:-60 196

1&GT;失败! 1 0

1&gt;得到字节:-51 205

1&GT;失败! 1 0

1&gt;得到字节:-51 205

1&GT;失败! 1 0

1 个答案:

答案 0 :(得分:1)

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

您可能想要解决的代码有一些奇怪之处:<​​/ p>

  • 始终需要在阅读后检查操作是否成功,例如使用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(),则需要使用合适的FILE*包裹std::streambuf并初始化std::istream相应的对象。
  • 如何使用fgets()读取任意大小的行?你不能。 fgets()的缓冲区在尝试填充之前得到分配,并且在到达换行符之前始终可以填充。但是,您可以使用std::getline()读取任意长行。如果您只想跳过该行,则可以在使用in.ignore(std::numeric_limits<std::streamsize>::max(), '\n')时使用std::istream。副手我不知道FILE*是否有类似的操作。