从二进制文件中读取并转换为double?

时间:2017-02-03 18:26:24

标签: c file file-io binary-data

我正在尝试编写一个读取二进制文件并将其转换为数据类型的C程序。我正在使用头命令head -c 40000 /dev/urandom > data40.bin生成二进制文件。该程序适用于数据类型int和char但不适用于double。这是该程序的代码。

void double_funct(int readFrom, int writeTo){
    double buffer[150];
    int a = read(readFrom,buffer,sizeof(double));
    while(a!=0){
        int size = 1;
        int c=0;

         for(c=0;c<size;c++){
            char temp[100];
            int x = snprintf(temp,100,"%f ", buffer[c]);
            write(writeTo, temp, x);
        }
        a = read(readFrom,buffer,sizeof(double));
    }
}

这是有效的char函数

void char_funct(int readFrom, int writeTo){
    char buffer[150];
    int a = read(readFrom,buffer,sizeof(char));
    while(a!=0){
        int size = 1;
        int c=0;

        for(c=0;c<size;c++){
            char temp[100]=" ";
            snprintf(temp,100,"%d ", buffer[c]);
            write(writeTo, temp, strlen(temp));
        }
        a = read(readFrom,buffer,sizeof(char));
    }
}

问题是,对于char,我需要用wc -w file获得40000个单词并获得它们。现在有了双倍,我得到随机数量的单词,但理论上我应该从40000字节的数据得到5000但是我得到4000到15000之间的随机量,对于char我得到40000就像它应该1个字节的一个字符。

我不知道同样的代码对于int有什么问题,我从40000字节的数据中得到10000个单词。

1 个答案:

答案 0 :(得分:5)

主要问题似乎是您的temp数组对于printf格式和数据来说不够大。 IEEE-754 double的小数指数范围为-308到+308。您正在使用格式"%f"打印双打,这会产生纯十进制表示。由于未指定精度,因此默认精度为6。这可能需要多达1(符号)+ 309(数字)+ 1(小数点)+ 6(尾随小数位)+ 1(终结符)字符(总共318),但您只有100的空间。 / p>

使用snprintf()打印到缓冲区,因此不会超出那里的数组边界,但snprintf()会返回所需的字节数,更少终结者所需的那个。这是你write()的字节数,在很多情况下, 溢出你的缓冲区。您可以在输出中看到结果。

其次,您还会在输出中看到大量0.00000,这是因为将小数字舍入到6位小数位数精度。

如果更改打印数字的格式,您可能会获得更好的成功。例如,"%.16e "将以指数格式输出,总共有17位有效数字(小数点前一位)。这不需要内存或磁盘上的过多空间,并且无论规模如何,它都会准确地传达所有数字,再次假设您的double代表每个IEEE 754.如果您愿意,您可以进一步消除(非常安全)通过在评论中使用@chux建议的变体来假设IEEE 754格式。那将是最安全的方法。

还有一件事:IEEE浮点支持无穷大和多个非数值。相对于普通的FP数字,它们的数量非常少,但是你偶尔会遇到其中一个。它们可能会很好地转换为输出,但您可能需要考虑是否需要专门处理它们。