从二进制文件中读取双类型数据

时间:2014-04-14 17:13:27

标签: c++ binary double

我想从double文件中读取binary值,并将它们存储在向量中。我的值具有以下形式:73.6634,73.3295,72.6764等。我有这个代码,可以在内存中读取和存储数据。它与char类型完美配合,因为read函数的输入为char类型(istream& read (char* s, streamsize n))。当我尝试将char类型转换为double时,我显然得到整数值74,73,73等等。是否有任何函数允许我直接读取双值或任何其他方式?

如果我将char * memblock更改为double * memblock而将memblock = new char[]更改为memblock = new double[],则在编译时会出现错误,因为read函数只能char输入变量...

谢谢,非常感谢您的帮助:)。

// reading an entire binary file
#include <iostream>
#include <fstream>
using namespace std;

int main () {
streampos size;
char * memblock;

int i=0;

ifstream file ("example.bin", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
    size = file.tellg();

    cout << "size=" << size << "\n"; 

    memblock = new char [size];
    file.seekg (0, ios::beg);
    file.read (memblock, size);
    file.close();

    cout << "the entire file content is in memory \n";

    for(i=0; i<=10; i++)
    {
    double value = memblock [i];
    cout << "value ("<<i<<")=" << value << "\n";
    }

};

    delete[] memblock;
}
else cout << "Unable to open file";
return 0;
}

2 个答案:

答案 0 :(得分:10)

(抱歉“喜欢我5岁”的语气,我不知道你有多少知道或不知道)

简介二进制数据

您可能知道,您的计算机并不像您那样考虑数字。

首先,计算机会考虑“基础2”系统中的所有数字。但它并不止于此。您的计算机还将固定大小与所有数字相关联。它创建了数字的固定“宽度”。此大小(几乎总是)以字节为单位,或4位数组。这是(非常接近)相当于,当您对数字[1,15,30002]进行数学运算时,您将所有数字视为

[
 00000001
 00000015
 00030002
]

(双打有点奇怪,但我会在一秒钟内完成这一点。)

让我们假装出于演示目的,上面每2个字符代表一个字节的数据。这意味着,在计算机中,它会考虑这样的数字:

[
 00,00,00,01
 00,00,00,15
 00,03,00,02
]

文件IO全部按照“字节”(字符)大小完成:它通常不知道它正在读取什么。您可以自己解决这个问题。将二进制数据写入文件(至少从一个数组中)时,我们只需将其全部转储。所以在上面的例子中,如果我们将它全部写入文件,如下所示:

[00,00,00,01,00,00,00,15,00,03,00,02]

但你必须重新解释它,回到4字节的类型。

幸运的是,在c ++中这很容易做到:

size = file.tellg();

cout << "size=" << size << "\n"; 

memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();

cout << "the entire file content is in memory \n";
double* double_values = (double*)memblock;//reinterpret as doubles
for(i=0; i<=10; i++)
{
double value = double_values[i];
cout << "value ("<<i<<")=" << value << "\n";
}

这基本上就是说,将那些字节(char)解释为double。

编辑:Endianness

Endianness(再次,LI5)计算机写入数字的顺序。您习惯于从左到右(25,25)写入十五个,但从右到左(52,五十二)编写数字同样有效。我们有big-endian(最低地址的最高有效字节)和little-endian(最高地址的MSB)。

这在体系结构或虚拟机之间从未标准化......但如果他们不同意,您可能会得到奇怪的结果。

一个特例:双打

不完全符合您的问题,但我必须指出双打是一种特殊情况:虽然阅读和写作看起来相同,但基础数据不仅仅是一个简单的数字。我喜欢将双打视为计算机的“科学记法”。双重标准使用底座和电源来获取您的号码。 在与长相同的空间中存储(符号)(a ^ x)。这给出了一个更大的动态范围的值表示,但是你松散了字节的“人类可读性”,并且你获得了相同数值的值,因此你可以放松精度(尽管它的相对精度,就像科学一样符号,所以你可能无法区分十亿和一十亿和二十,但是1和2是TINY与数字相比)。

用C ++编写数据

我们不妨指出一个C ++的怪癖:你必须确保在编写数据时,它不会尝试将文件重新格式化为ascii。 http://www.cplusplus.com/forum/general/21018/

答案 1 :(得分:0)

问题是这个 - 不能保证由另一个程序(你说Matlab)写的二进制数据只能通过转换被另一个程序读回,除非你知道这个辅助程序写的数据是相同的作为您的程序写的数据。

仅仅强制转换可能还不够 - 您需要知道所写数据的确切形式。您需要知道二进制格式(例如IEEE),每个值占用的字节数,字节顺序等,以便您可以正确地解释数据。

你应该做的是 - 编写一个小程序,将你声称这个文件的号码写到另一个文件中。然后查看您在十六进制编辑器中编写的文件。然后获取您尝试阅读的文件,该文件由MatLab创建,并将内容与您刚编写的文件并排比较。你看到一个模式吗?如果没有,那么要么你必须找到一个,要么忘掉它并让两个文件保持一致。