本文介绍了在C ++中从二进制文件读取时,将char *转换为double?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在为应用程序中存储数据编写一个二进制I / O。



为了说明,我想要存储一个大小为10的double数组



现在由于不能保证double在所有平台上使用8个字节,所以文件的读者需要修改一下。
虽然我使用Qt我认为问题主要是在char *数据读取的方式翻译成双。读取的数据几乎为零。



例如,1读为2.08607954259741e-317。



为什么每个double都被读取为零,即使不是吗?

  void FileString :: SaveBinary()
{
QFile * file = new QFile(fileName);
if(!file-> open(QFile :: WriteOnly))
{
QString err = file-> errorString
QString * msgText = new QString(无法从磁盘打开文件!\\\
);
msgText-> append(err);
QString * msgTitle = new QString(ERROR:Could not open the file!);
emit errMsg(msgTitle,msgText,WARNING);
删除文件;
return;
}
QDataStream out(file);
QString line =MyApp;
out<<线;
line.setNum(size); // size = 10
out<<线;
line.setNum(sizeof(double));
out<<线;

for(int i = 0; i {
out< array [i];
}

if(out.status()!= QDataStream :: Ok)
{
qCritical(error:+ QString :: number(out。 status())。toAscii());
}
file-> close();
删除文件;
}

void FileString :: ReadBinary()
{
bool ok = false;
QString line =;
QFile * file = new QFile(fileName);
if(!file-> open(QFile :: ReadOnly))
{
QString err = file-> errorString
QString * msgText = new QString(无法从磁盘打开文件!\\\
);
msgText-> append(err);
QString * msgTitle = new QString(ERROR:Could not open the file!);
emit errMsg(msgTitle,msgText,WARNING);
删除文件;
return;
}

QDataStream in(file);
在>>线;
if(line.simplified()。contains(MyApp))
{
在>线;
size = line.simplified()。toInt();
if(size == 10)
{
int mysize = 0;
在>>线;
mysize = line.simplified()。toInt();
if(1)// this block runs perfect
{
for(int i = 0; i {
in> ; array [i];
}

if(in.status()== QDataStream :: Ok)
ok = true;
}
}
else if(1)//此块只读取零
{
char * reader = new char [mysize + 1];
int read = 0;
double * dptr = NULL;
for(int i = 0; i {
read = in.readRawData(reader,mysize);
if(read!= mysize)
{
break;
}

dptr = reinterpret_cast< double *>(reader); //垃圾数据存储在dptr中,为什么?
if(dptr)
{
array [i] = * dptr;
dptr = NULL;
}
else
{
break;
}
}


if(in.status()== QDataStream :: Ok)
ok = true;
delete [] reader;
}
}
}

if(!ok ||(in.status()!= QDataStream :: Ok))
{
qCritical(error:true+status =+ QString :: number((int)in.status())。
}
file-> close();
删除文件;
}

EDIT: b

生成的文件的内容

 & M y A p p 1。 1 8。 3。 0 1 0 8ð@ @ @ @ @ @ @ @@ $ 

包含:

  MyApp 1.18.3.010812345678910 

MyApp 1.18.3.010 12345678910


解决方案

在读平台上的 sizeof double 与写平台上的 sizeof double

不同?



假设您的写入平台上的 sizeof double 为10.然后,您在一个代表10字节double的文件中存储了10个字节的序列,如果<$你的读平台上的c $ c> sizeof double 是8,你会尝试将一个10字节的双位解析为一个8字节,这显然会结束垃圾。



这里有一个更直观的ints示例:
如果你有一个2字节的整数,说5.如果你存储在二进制文件,你会得到一个2字节的序列: 00000000 00000101 。然后,如果您尝试读取与1字节int相同的数字,您将设法只读取第一个字节,即 00000000 ,并获得零作为



考虑使用字符串保存双重可移植性


I am writing a binary I/O for storing data in my application.

For illustration consider I want to store a double array of size 10 to the file.

Now since it is not guaranteed that double uses 8 bytes on all platforms, the reader of the file needs to be be modified a bit.Although I am using Qt I think the problem is mainly in the way data read in char * is translated into double. The data read is almost zero.

For example, 1 is read as 2.08607954259741e-317.

Why is every double being read as zero even thought it is not?

void FileString::SaveBinary()
{
    QFile *file = new QFile(fileName);
    if (!file->open(QFile::WriteOnly))
    {
        QString err = file->errorString();
        QString *msgText = new QString("Could not open the file from disk!\n");
        msgText->append(err);
        QString *msgTitle = new QString("ERROR: Could not open the file!");
        emit errMsg(msgTitle, msgText, "WARNING");
        delete file;
        return;
    }
    QDataStream out(file);
    QString line = "MyApp";
    out << line;
    line.setNum(size);//size = 10
    out << line;
    line.setNum(sizeof(double));
    out << line;

    for(int i = 0; i < size; i++)
    {
        out << array[i];
    }

    if(out.status() != QDataStream::Ok)
    {
        qCritical("error: " + QString::number(out.status()).toAscii());
    }
    file->close();
    delete file;
}

void FileString::ReadBinary()
{
    bool ok = false;
    QString line = "";
    QFile *file = new QFile(fileName);
    if (!file->open(QFile::ReadOnly))
    {
        QString err = file->errorString();
        QString *msgText = new QString("Could not open the file from disk!\n");
        msgText->append(err);
        QString *msgTitle = new QString("ERROR: Could not open the file!");
        emit errMsg(msgTitle, msgText, "WARNING");
        delete file;
        return;
    }

    QDataStream in(file);
    in >> line;
    if(line.simplified().contains("MyApp"))
    {
        in >> line;
        size = line.simplified().toInt();
        if(size == 10)
        {
            int mysize = 0;
            in >> line;
            mysize = line.simplified().toInt();
            if(1)//this block runs perfect
            {
                for(int i = 0; i < size; i++)
                {
                    in >> array[i];
                }

                if(in.status() == QDataStream::Ok)
                    ok = true;
                }
            }
            else if(1)//this block reads only zeros
            {
                char *reader = new char[mysize + 1];
                int read = 0;
                double *dptr = NULL;
                for(int i = 0; i < size; i++)
                {
                    read = in.readRawData(reader, mysize);
                    if(read != mysize)
                    {
                        break;
                    }

                    dptr = reinterpret_cast<double *>(reader);//garbage data stored in dptr, why?
                    if(dptr)
                    {
                        array[i] = *dptr;
                        dptr = NULL;
                    }
                    else
                    {
                        break;
                    }
                }


                if(in.status() == QDataStream::Ok)
                    ok = true;
                delete[] reader;
            }
        }
    }

    if(!ok || (in.status() != QDataStream::Ok))
    {
        qCritical("error : true" + " status = " + QString::number((int) in.status()).toAscii());
    }
    file->close();
    delete file;
}

EDIT:

Contents of the generated file

   & M y A p p   1 . 1 8 . 3 . 0    1 0    8?ð      @       @      @      @      @      @      @       @"      @$      

That is supposed to contain:

MyApp 1.18.3.010812345678910

"MyApp 1.18.3.0" "10" "8" "12345678910"
解决方案

What do you expect to read if sizeof double on read platform differs from sizeof double on write platform?

Suppose sizeof double on your write platform was 10. Then you stored a sequence of 10 bytes in a file that represents a 10-byte double. Then, if sizeof double on your read platform is 8, you would try to parse bits of an 10-byte double into an 8-byte and that would obviously end up with garbage.

Here's a more intuitive example with ints:If you a have a 2-byte integer number, say 5. If you store it in binary file, you'll get a sequence of 2 bytes: 00000000 00000101. Then, if you try to read the same number as a 1-byte int, you'll manage to read only the first byte, which is 00000000 and get just zero as a result.

Consider using strings to save doubles for portability http://stackoverflow.com/a/6790009/817441

这篇关于在C ++中从二进制文件读取时,将char *转换为double?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 20:22