2013-04-09 80 views
4

我正在读取由传感器生成的二进制文件。我在读取浮点时遇到了不同的精度问题(32或64)。我可以在MATLAB(64位版本)中阅读它们,但Qt(Windows上的32位版本)会给出错误的值。我可以阅读到dtmth(请参阅下面的结构)。之后,我得到baseline的价值Inf。事实上这个值是0。正如你所看到的,我改变了MSB(LittleEndian)。如果我保留BigEndian,则基线为0,但其他值则是错误的。我的桌面是64位。qDatastream中的Qt二进制读取错误

我检查了字节数,它们是正确的。我认为问题是机器精度。

QDataStream in(&file); 

      in.setByteOrder(QDataStream::LittleEndian); 
      params p; 

      in >> p.filetype;    
      in >> p.projectid; 
      in >> p.datamin;    
      in >> p.dtyear; 
      in >> p.dtmth;    
      in >> p.baseline; 
      in >> p.startfrequ; 

其中P是一个结构定义为:

struct params 
    { 
     quint8 filetype; 
     quint16 projectid; 
     double datamin; 
     quint16 dtyear; 
     quint8 dtmth;  
     float baseline; 
     double startfrequ; 

    }; 

我可以在MATLAB阅读。我的matlab是64位版本,我读取的数据类型如下:

MATLAB: 
     uint8 filetype; 
     uint16 projectid; 
     float64 datamin; 
     uint16 dtyear; 
     uint8 dtmth;  
     float32 baseline; 
     float64 startfrequ; 

让我知道如果我错过了任何细节。

编辑:

读文件:

QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(), 
       tr("Raw Files (*.msr);;All files (*.*)")); 

      if (!fileName.isEmpty()) { 
       qDebug("Attempting to open file.."); 
       QFile file(fileName); 
       if (!file.open(QIODevice::ReadOnly)) { 
        QMessageBox::critical(this, tr("Error"), tr("Could not open file")); 
        return; 
       } 

       QDataStream in(&file); 

非常感谢提前。

+0

也正确读取'datamin'? – UmNyobe 2013-04-09 08:43:38

+0

再次@UmNyobe。那是我困惑的地方。我正在阅读正确的字节数,并且这两个值都是0.所以我不确定它们是否正确。但后来我正确读数。此外,基线的价值也是0,我得到的是Inf。 – Naresh 2013-04-09 08:48:25

+0

是否在二进制模式下打开'file'?在Windows上,您必须区分二进制和文本模式;文本模式在输入时将“0x13 0x10”对改为“0x10”,因此可能会破坏数据。 – Angew 2013-04-09 08:53:06

回答

3

您使用的是哪个版本的Qt?如果版本优于Qt 4.6,则默认精度为64位,即which means Qt will try to read your float 32 as a float 64。您需要手动设置精度in.setFloatingPointPrecision (QDataStream::SinglePrecision);

 in >> p.filetype;    
     in >> p.projectid; 
     in >> p.datamin;    
     in >> p.dtyear; 
     in >> p.dtmth;  
     in.setFloatingPointPrecision(QDataStream::SinglePrecision); 
     in >> p.baseline; 
     in.setFloatingPointPrecision(QDataStream::DoublePrecision); 
     in >> p.startfrequ; 

从您的评论看来,这是问题。事实上,如果设置为单精度,并且您尝试读取p.dataminp.startfrequ(64位),则数据流将以32位浮点数的形式读取它们。不仅p.datamin将不正确,但它后面的所有值。

一开始,检查我的建议的工作使用的最后一个行之后

 if(in.status() == QDataStream::ReadCorruptData){ 
      qDebug() << "still doesnt work"; 
     } 
+1

我的Qt是5.0.1(32位)。 我发布这个问题之前已经尝试过。但是,投射后所有的价值都是错误的。虽然数字是0. – Naresh 2013-04-09 08:59:58

+0

Naresh,它证实这是你的问题。我从来没有尝试过,但在编辑中使用示例代码并告诉我它是否正确。我相信这是从QT家伙疯了。 – UmNyobe 2013-04-09 09:02:37

+0

hi @UmNyobe。我其实想到了它。但我认为Qt不会那么愚蠢。但实际上是。它解决了这个问题。实际上,我的头文件信息比我放在这里的要多得多,所以我不得不改变3次,然后阅读正确的值。有没有修复?写自己的函数,改变浮点数和双精度的精度? – Naresh 2013-04-09 09:22:09