Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Read some bytes from binary file with qfile

Read some bytes from binary file with qfile

Scheduled Pinned Locked Moved Solved C++ Gurus
13 Posts 3 Posters 2.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Please_Help_me_DP Offline
    Please_Help_me_DP Offline
    Please_Help_me_D
    wrote on last edited by
    #1

    Hi,
    I'm trying to get familiar with QFile. I need to read some bytes from binary file. Here is my code:

    QString myFile[]{"C:/Qt_Projects/raw_le.bin"};
    quint16_le dataFormatCode_le;
    qFile = new QFile(myFile);
     if (!qFile->open(QIODevice::ReadOnly)) {
        std::cout << "QFile: Error opening file!" << std::endl;
        return;
    }
    qFile->seek(3224);
    qFile->read(dataFormatCode_le, 2); // error
    

    I know that 3225-3226 bytes is of qint16 format so I want to read these bytes in dataFormatCode_le variable but I don't understand how.
    I use Windows 10 x64, MSVC 64, Qt 5.14.0

    JonBJ 1 Reply Last reply
    0
    • Please_Help_me_DP Please_Help_me_D

      @JonB sorry, here is the error:
      *readsegy.cpp:37:16: error: no matching member function for call to 'read'
      qiodevice.h:122:12: note: candidate function not viable: no known conversion from 'quint16_le' (aka 'QSpecialInteger<QLittleEndianStorageType<unsigned short> >') to 'char ' for 1st argument
      qiodevice.h:123:16: note: candidate function not viable: requires single argument 'maxlen', but 2 arguments were provided

      Yes I can't compile it and this is my problem.
      I think that according to the documentation I shoud use QByteArray for this purpose but I have not used it before.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #6

      @Please_Help_me_D
      Yes, I thought so! That's why it's good for both you & us to copy the error message here and examine it together!

      That read() overload requires a first parameter of type char *. You are passing your quint16_le dataFormatCode_le, which is not a pointer in the first place and is an integer not a char type in the second place.

      You have to pass the address of the area you want to read() into, so that read() has the place to store the data. This would be a start:

      qFile->read(&dataFormatCode_le, 2);
      

      That & is the magic. It passes the address of dataFormatCode_le, so that is where read() will put its bytes/chars, which is a good start!

      Now however the compiler will complain that it wants a char * but you have given it a quint16_le *, so it still won't be happy!

      This is where my knowledge of C++ gets a touch wobbly. I believe you'll want:

      qFile->read(reinterpret_cast<char *>(&dataFormatCode_le), 2);
      

      but experts may correct me on this. Give it a try!

      EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

      Please_Help_me_DP K 2 Replies Last reply
      3
      • Please_Help_me_DP Please_Help_me_D

        Hi,
        I'm trying to get familiar with QFile. I need to read some bytes from binary file. Here is my code:

        QString myFile[]{"C:/Qt_Projects/raw_le.bin"};
        quint16_le dataFormatCode_le;
        qFile = new QFile(myFile);
         if (!qFile->open(QIODevice::ReadOnly)) {
            std::cout << "QFile: Error opening file!" << std::endl;
            return;
        }
        qFile->seek(3224);
        qFile->read(dataFormatCode_le, 2); // error
        

        I know that 3225-3226 bytes is of qint16 format so I want to read these bytes in dataFormatCode_le variable but I don't understand how.
        I use Windows 10 x64, MSVC 64, Qt 5.14.0

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #2

        @Please_Help_me_D
        When asking a question, please say what // error means, don't you think that helps or do you prefer we guess?

        If you are trying to use qint64 QIODevice::read(char *data, qint64 maxSize) for your qFile->read(dataFormatCode_le, 2), yours won't compile, is that your issue?

        Please_Help_me_DP 1 Reply Last reply
        2
        • JonBJ JonB

          @Please_Help_me_D
          When asking a question, please say what // error means, don't you think that helps or do you prefer we guess?

          If you are trying to use qint64 QIODevice::read(char *data, qint64 maxSize) for your qFile->read(dataFormatCode_le, 2), yours won't compile, is that your issue?

          Please_Help_me_DP Offline
          Please_Help_me_DP Offline
          Please_Help_me_D
          wrote on last edited by
          #3

          @JonB sorry, here is the error:
          *readsegy.cpp:37:16: error: no matching member function for call to 'read'
          qiodevice.h:122:12: note: candidate function not viable: no known conversion from 'quint16_le' (aka 'QSpecialInteger<QLittleEndianStorageType<unsigned short> >') to 'char ' for 1st argument
          qiodevice.h:123:16: note: candidate function not viable: requires single argument 'maxlen', but 2 arguments were provided

          Yes I can't compile it and this is my problem.
          I think that according to the documentation I shoud use QByteArray for this purpose but I have not used it before.

          JonBJ 1 Reply Last reply
          0
          • K Offline
            K Offline
            Konstantin Tokarev
            wrote on last edited by
            #4

            With QIODevice::read you can read only raw bytes (as char* or QByteArray), and then it's your responsibility to convert bytes to qint16 with correct endianness

            Please_Help_me_DP 1 Reply Last reply
            4
            • K Konstantin Tokarev

              With QIODevice::read you can read only raw bytes (as char* or QByteArray), and then it's your responsibility to convert bytes to qint16 with correct endianness

              Please_Help_me_DP Offline
              Please_Help_me_DP Offline
              Please_Help_me_D
              wrote on last edited by Please_Help_me_D
              #5

              @Konstantin-Tokarev thank you for the answer.
              Could you please give me an example how use QByteArray in my case?
              Also how do yo think, recently I used fread/fseek for these purposes and I coud use it to read data in struct such as:

              struct binHdr_struct {
                  qint32 var1, var2;
                  quint16 var3, var4;
              };
              
              void main(){
                  binHdr_struct binHdr;
              
                  pFile = fopen(myFile, "rb");
                  if (pFile == nullptr){
                    std::cout << "fopen: Error opening file!" << std::endl;
                    return;
                  }
                  fseek (pFile , 3200 , SEEK_SET);
                  fread(&binHdr, sizeof(binHdr_struct), 1, pFile);}
              

              So it was very simple to read data in struct. Is it possible to do something simple with QFile?
              Here my struct contain only 4 variables (var1,2,3,4) but actually it has over 30 of them

              1 Reply Last reply
              0
              • Please_Help_me_DP Please_Help_me_D

                @JonB sorry, here is the error:
                *readsegy.cpp:37:16: error: no matching member function for call to 'read'
                qiodevice.h:122:12: note: candidate function not viable: no known conversion from 'quint16_le' (aka 'QSpecialInteger<QLittleEndianStorageType<unsigned short> >') to 'char ' for 1st argument
                qiodevice.h:123:16: note: candidate function not viable: requires single argument 'maxlen', but 2 arguments were provided

                Yes I can't compile it and this is my problem.
                I think that according to the documentation I shoud use QByteArray for this purpose but I have not used it before.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #6

                @Please_Help_me_D
                Yes, I thought so! That's why it's good for both you & us to copy the error message here and examine it together!

                That read() overload requires a first parameter of type char *. You are passing your quint16_le dataFormatCode_le, which is not a pointer in the first place and is an integer not a char type in the second place.

                You have to pass the address of the area you want to read() into, so that read() has the place to store the data. This would be a start:

                qFile->read(&dataFormatCode_le, 2);
                

                That & is the magic. It passes the address of dataFormatCode_le, so that is where read() will put its bytes/chars, which is a good start!

                Now however the compiler will complain that it wants a char * but you have given it a quint16_le *, so it still won't be happy!

                This is where my knowledge of C++ gets a touch wobbly. I believe you'll want:

                qFile->read(reinterpret_cast<char *>(&dataFormatCode_le), 2);
                

                but experts may correct me on this. Give it a try!

                EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                Please_Help_me_DP K 2 Replies Last reply
                3
                • JonBJ JonB

                  @Please_Help_me_D
                  Yes, I thought so! That's why it's good for both you & us to copy the error message here and examine it together!

                  That read() overload requires a first parameter of type char *. You are passing your quint16_le dataFormatCode_le, which is not a pointer in the first place and is an integer not a char type in the second place.

                  You have to pass the address of the area you want to read() into, so that read() has the place to store the data. This would be a start:

                  qFile->read(&dataFormatCode_le, 2);
                  

                  That & is the magic. It passes the address of dataFormatCode_le, so that is where read() will put its bytes/chars, which is a good start!

                  Now however the compiler will complain that it wants a char * but you have given it a quint16_le *, so it still won't be happy!

                  This is where my knowledge of C++ gets a touch wobbly. I believe you'll want:

                  qFile->read(reinterpret_cast<char *>(&dataFormatCode_le), 2);
                  

                  but experts may correct me on this. Give it a try!

                  EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                  Please_Help_me_DP Offline
                  Please_Help_me_DP Offline
                  Please_Help_me_D
                  wrote on last edited by
                  #7

                  @JonB thank you!
                  That was exactly what I was looking for
                  By the way you approach also works with struct as I asked one message above

                  1 Reply Last reply
                  0
                  • JonBJ JonB

                    @Please_Help_me_D
                    Yes, I thought so! That's why it's good for both you & us to copy the error message here and examine it together!

                    That read() overload requires a first parameter of type char *. You are passing your quint16_le dataFormatCode_le, which is not a pointer in the first place and is an integer not a char type in the second place.

                    You have to pass the address of the area you want to read() into, so that read() has the place to store the data. This would be a start:

                    qFile->read(&dataFormatCode_le, 2);
                    

                    That & is the magic. It passes the address of dataFormatCode_le, so that is where read() will put its bytes/chars, which is a good start!

                    Now however the compiler will complain that it wants a char * but you have given it a quint16_le *, so it still won't be happy!

                    This is where my knowledge of C++ gets a touch wobbly. I believe you'll want:

                    qFile->read(reinterpret_cast<char *>(&dataFormatCode_le), 2);
                    

                    but experts may correct me on this. Give it a try!

                    EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                    K Offline
                    K Offline
                    Konstantin Tokarev
                    wrote on last edited by
                    #8

                    @JonB said in Read some bytes from binary file with qfile:

                    EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                    "Sparing" someone from endianness when dealing with multibyte data types coming from files or network is effectively an advice to write broken code.

                    JonBJ Please_Help_me_DP 2 Replies Last reply
                    2
                    • K Konstantin Tokarev

                      @JonB said in Read some bytes from binary file with qfile:

                      EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                      "Sparing" someone from endianness when dealing with multibyte data types coming from files or network is effectively an advice to write broken code.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #9

                      @Konstantin-Tokarev
                      IMO, when the user still needs to understand how to take address to get a pointer and match method parameter types, that is what they need to grasp first. I do not advise people to write broken code, here I gave advice on how to action a compilation error.

                      I never said endianness would not be covered. Had the user tried to get the code compiling correctly first, I would then have gone on to discuss the endianness issue and hence that he needed to change approach.

                      I totally respect your point. Evidently you & I differ on how best to help a beginner.

                      @Please_Help_me_D , or anyone else reading this in future
                      Let's be absolutely clear. The code as shown will work in a limited set or circumstances on one architecture. @Konstantin-Tokarev is absolutely correct that to get this robust the approach should be changed to deal with integers/endiainness.

                      1 Reply Last reply
                      0
                      • K Konstantin Tokarev

                        @JonB said in Read some bytes from binary file with qfile:

                        EDIT I see while I was typing @Konstantin-Tokarev has chimed in and talked about "endianness". What he says is correct, but I was trying to spare you that, assuming you only have one endianness at issue. What I have shown you is the equivalent using QFile & C++ of the code you have now shown using fopen() & fread().

                        "Sparing" someone from endianness when dealing with multibyte data types coming from files or network is effectively an advice to write broken code.

                        Please_Help_me_DP Offline
                        Please_Help_me_DP Offline
                        Please_Help_me_D
                        wrote on last edited by Please_Help_me_D
                        #10

                        @Konstantin-Tokarev @JonB If I understood the comment then I use some if statement to define endianess. The idea is that I know what number should be in 3225-3226 bytes and I read in both quint16_le dataFormatCode_le and quint16_be dataFormatCode_be. Then compare these numbers and define the endianess.
                        I just tried my updated with @JonB help code with both big- and little-endian files and it works
                        By the way instead of reinterpret_cast<char >(&dataFormatCode_le) I use util::bit_cast<char>(&dataFormatCode_le)
                        So I hope it should run on different architectures

                        How to highlight text with red in this forum? Like @JonB did

                        JonBJ 1 Reply Last reply
                        0
                        • Please_Help_me_DP Please_Help_me_D

                          @Konstantin-Tokarev @JonB If I understood the comment then I use some if statement to define endianess. The idea is that I know what number should be in 3225-3226 bytes and I read in both quint16_le dataFormatCode_le and quint16_be dataFormatCode_be. Then compare these numbers and define the endianess.
                          I just tried my updated with @JonB help code with both big- and little-endian files and it works
                          By the way instead of reinterpret_cast<char >(&dataFormatCode_le) I use util::bit_cast<char>(&dataFormatCode_le)
                          So I hope it should run on different architectures

                          How to highlight text with red in this forum? Like @JonB did

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #11

                          @Please_Help_me_D
                          I won't say much more, you had better get @Konstantin-Tokarev or another to suggest the correct way to do this here, including any necessary correct C++ casting. But

                          read in both quint16_le dataFormatCode_le and quint16_be dataFormatCode_be. Then compare these numbers and define the endianess.

                          does not sound right. If you mean you (somehow) read the data into those two types of variables, that does not sound right, and how can you "compare" and know which one is correct?

                          You have to start by saying/discovering how that integer was stored into the file by the writer in the first place? Only then can you know how to read it back.

                          Please_Help_me_DP 1 Reply Last reply
                          1
                          • JonBJ JonB

                            @Please_Help_me_D
                            I won't say much more, you had better get @Konstantin-Tokarev or another to suggest the correct way to do this here, including any necessary correct C++ casting. But

                            read in both quint16_le dataFormatCode_le and quint16_be dataFormatCode_be. Then compare these numbers and define the endianess.

                            does not sound right. If you mean you (somehow) read the data into those two types of variables, that does not sound right, and how can you "compare" and know which one is correct?

                            You have to start by saying/discovering how that integer was stored into the file by the writer in the first place? Only then can you know how to read it back.

                            Please_Help_me_DP Offline
                            Please_Help_me_DP Offline
                            Please_Help_me_D
                            wrote on last edited by
                            #12

                            @JonB ok, thank you for advice.
                            There is official description of the file format that tells us that number in 3225-3226 bytes should be in range from 1 to 5. I believe that there is no way that quint16_le dataFormatCode_le and quint16_be dataFormatCode_be be in this range at the same time. Only one of them should be in range.
                            I have not used QByteArray before so I will postpone it for some time.

                            JonBJ 1 Reply Last reply
                            0
                            • Please_Help_me_DP Please_Help_me_D

                              @JonB ok, thank you for advice.
                              There is official description of the file format that tells us that number in 3225-3226 bytes should be in range from 1 to 5. I believe that there is no way that quint16_le dataFormatCode_le and quint16_be dataFormatCode_be be in this range at the same time. Only one of them should be in range.
                              I have not used QByteArray before so I will postpone it for some time.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #13

                              @Please_Help_me_D
                              OK, but in case someone observes that this is not the way to do it (which they are entitled to do!), be aware of that.

                              Given:

                              There is official description of the file format that tells us that number in 3225-3226 bytes should be in range from 1 to 5.

                              somewhere in such an official description there should also be a statement as to how they store 2-byte/16-bit numbers!

                              1 Reply Last reply
                              2

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved