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
Forum Updated to NodeBB v4.3 + New Features

Read some bytes from binary file with qfile

Scheduled Pinned Locked Moved Solved C++ Gurus
13 Posts 3 Posters 2.9k Views 1 Watching
  • 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 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 Online
    JonBJ Online
    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 Online
            JonBJ Online
            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 Online
                  JonBJ Online
                  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 Online
                      JonBJ Online
                      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 Online
                          JonBJ Online
                          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