Read Binary Data into a QVector



  • Hi Guys,

    I need some help with reading a binary Data into a vector of doubles :/

    This is my Code :

    QString filename = "C:/Qt/Test/test.bin";
     QFile file1(filename);
        if (!file1.open(QIODevice::ReadOnly)) return;
        QByteArray data = file1.readAll();
        qDebug() << data.size();
        QDataStream ds(&data, QIODevice::ReadWrite);
    
           QVector<double> outVect;
           outVect.resize(data.size());
    
    
           ds.readRawData((char*)outVect.data(), data.size());
           foreach (double current, outVect)
               qDebug() << current;
    
    

    My Problem is that i only get 0 :/ and i don't know why --- has sb an idea ?
    Maybe it has sth to do with the line :
    ds.readRawData((char*)outVect.data(), data.size());



  • What is the format of the file? Binary is the most generic description I can think of

    Good place to start http://www.bogotobogo.com/Qt/Qt5_QFile_Serialization.php



  • @VRonin thanks for the link :) it's almost the same i have done in my code except the copy intoa vector of double... and thats where i don't know how to do it :/
    the format is a .bin File ... if you open the file with the editor you can see some random ASCII code.. which describes some double values



  • @BadHombre said in Read Binary Data into a QVector:

    thanks for the link :) it's almost the same i have done in my code except the copy intoa vector of double

    No, it's not I'm afraid. It most definitely is not.

    the format is a .bin File

    still meaningless. How is it saved? by who?

    let's try:

    QFile file1("C:/Qt/Test/test.bin");
    QVector<double> outVect;
    if (file1.open(QIODevice::ReadOnly)){
    QDataStream fileStream(&file1);
    for(;;){
    double tempValue;
    fileStream.startTransaction();
    fileStream >> tempValue;
    if(fileStream.commitTransaction())
    outVect << tempValue;
    else
    break;
    }
    }
    

    but it's pure speculation until we know what the file contains.

    If you really have no idea and the file is not too big you can open it in a hex editor and paste the results here so we can try and guess what's in there



  • the .bin File was created by Matlab and contains only numbers



  • @BadHombre Getting warmer, can you post the matlab code that created it?



  • Without seeing more,

    I would suggest union

    union
    {
        double f;
        unsigned char chr;
    } u;
    

    this should do the trick as long as you pass the correct byteArrey/length.

    code: untested from my side



  • @VRonin so i tested your code but i don ' t get the right values :/

    matlab code : 
    matrix_save=[A' B' C D' E' ];
    fileID = fopen('folder/filename.bin','w');
    fwrite(fileID,matrix_save','double');
    fclose(fileID);
    
    

    this is the code i wrote for c++ .. A B C D E are some Matrix..with numbers in it

      ifstream file("E:\\file.bin");
    
            char * buffer;
            long size;
            file.seekg(0, std::ios::end);
            size = file.tellg();
            file.seekg(0, std::ios::beg);
            buffer = new char[size];
            file.read(buffer, size);
            file.close();
    
            double* double_values = (double*)buffer;//reinterpret as doubles
            vector<double> buffer2(double_values, double_values + (size / sizeof(double)));
    


  • the code I posted above should work then



  • @BadHombre
    I totally missed, that you're using <fsteam>

    You could also use this code sample:

    ifstream file("E:\\file.bin");
    double read;
    
            if ( file) {
                file.read( reinterpret_cast<char*>( &read ), sizeof read );
                qDebug() << read;
            }
    

    If MatLap has the same byteorder of course :)

    Edit, I acutally found the Source, from when i was researching that.



  • @VRonin doesn't work :/

    this are the values in the Qvector

    0
    0
    3.1568e-58
    -3.03415e-298
    2.08159e+74
    2.92534e+211
    -2.01411e+84
    3.21098e+39
    0
    0
    

    and this are the numbers from matlab which it should have :/

    0	0	-5,99983766238420	-5,99651426671551	-5,22786749086602	5,99821019538431	5,99832392614572	5,22649512993718	0	0
    


  • If you can temporarily change the matlab file with from fwrite(fileID,matrix_save','double'); to fwrite(fileID,matrix_save','b'); and see if it works in that case?



  • @VRonin I get an error

    Error using fwrite
    Invalid precision.

    Error in Untitled (line 28)
    fwrite(fileID,matrix_save','b');



  • @BadHombre my bad, I deleted an argument by mistake, I meant fwrite(fileID,matrix_save','double','b');



  • @VRonin now i get the right number ... what was the Problem ? Is it possible to get the right numbers without changing the matlab code ?



  • @BadHombre

    the b paramter tells matlab to write in Big-endian ordering



  • @BadHombre said in Read Binary Data into a QVector:

    what was the Problem ?

    @J-Hilk is super correct!

    Is it possible to get the right numbers without changing the matlab code ?

    Yes and no. If your matlab code and your program are assured to run on the same system and you know the default byte order of that system yes.

    if you know your system is big-endian then my original code will just work, if you know your system is little endian (like in your case) add fileStream.setByteOrder(QDataStream::LittleEndian); before the for(;;)

    There is no way with your current matlab code to make the file readable in another system without a doubt

    EDIT

    Actually you can hack your way around the "you know the default byte order of that system" but there is no way out of the "your matlab code and your program are assured to run on the same system" part

    bool is_big_endian()
    {
        union {
            quint32 i;
            char c[4];
        } bint = {0x01020304};
        return bint.c[0] == 1; 
    }
    
    QFile file1("C:/Qt/Test/test.bin");
    QVector<double> outVect;
    if (file1.open(QIODevice::ReadOnly)){
    QDataStream fileStream(&file1);
    if(!is_big_endian())
    fileStream.setByteOrder(QDataStream::LittleEndian);
    for(;;){
    double tempValue;
    fileStream.startTransaction();
    fileStream >> tempValue;
    if(fileStream.commitTransaction())
    outVect << tempValue;
    else
    break;
    }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.