4
votes

I am reading a binary file that is a produced by a sensor. I am having problem in reading float with different precision (32 or 64). I can read them in MATLAB (64 bit version) but Qt (32 bit version on windows) is giving wrong values. I can read till dtmth (please ref structure below) . After it I am getting a value Inf for baseline. This value is 0 in fact. As you can see, I changed MSB (LittleEndian). If I keep BigEndian, I get 0 for baseline but others values are wrong then. My desktop is 64 bit.

I have checked number of bytes and they are correct. I think the problem is machine precision.

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;

Where p is a structure defined as:

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

    };

I can read them in MATLAB. My matlab is 64 bit version where I read data types as following:

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

Let me know if I missed any details.

EDIT:

Reading file:

    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);

Thanks a lot in advance.

1
you also read correctly datamin??UmNyobe
Hi again @UmNyobe . That is where I am confused. I am reading right number of bytes, and both values are 0. so I am not sure if they are correct or not. But then I am reading dtyear correctly. Further, value of baseline is also 0, which I am getting as Inf.Naresh
Is file opened in binary mode? On Windows, you have to differentiate binary and text mode; text mode changes 0x13 0x10 pairs into just 0x10 on input, so it could corrupt your data.Angew is no longer proud of SO
I am using QFile which by default assumes binary. (question updated)Naresh
did you tried switching precision each time??UmNyobe

1 Answers

3
votes

Which version of Qt are you using? If the version is superior to Qt 4.6, then the default precision is 64 bit, which means Qt will try to read your float 32 as a float 64. You need to manually set the precision with 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;

From your comment it seems this was the issue. Indeed, if you set to single precision, and you try to read p.datamin or p.startfrequ (64 bits), then the data stream will read them as 32 bits floats. and not only p.datamin will be incorrect but all values after it.

For a start, to check that my suggestion worked use after the last line

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