4

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.

5
  • you also read correctly datamin?? Commented Apr 9, 2013 at 8:43
  • 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. Commented Apr 9, 2013 at 8:48
  • 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. Commented Apr 9, 2013 at 8:53
  • I am using QFile which by default assumes binary. (question updated) Commented Apr 9, 2013 at 9:07
  • did you tried switching precision each time?? Commented Apr 9, 2013 at 9:11

1 Answer 1

3

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";
      }
Sign up to request clarification or add additional context in comments.

4 Comments

My Qt is 5.0.1 (32 bit). I already tried that before posting this question. But then all values are wrong after projectid. Though datamin is 0.
Naresh, it confirms that this is your issue. I never tried it, but use the sample code in my edit and tell me if it's correct. I believe this is insane from the qt guys.
hi @UmNyobe . I actually thought of it. But I assumed Qt wont be that stupid. But it actually is. It fixed the problem. I actually had a lot more of header information than I put here so I had to change 3 times and then I read right values. Is there a fix? Write own function that changes precision for floats and doubles?
The only reason which come to my mind is that QDataStream is designed to write and read a platform-independent byte stream for serialising objects. Still it sucks, because you basically need to write what you say, a custom wrapper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.