Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Writing raw data to a file using QFile
QtWS25 Last Chance

Writing raw data to a file using QFile

Scheduled Pinned Locked Moved Unsolved General and Desktop
16 Posts 8 Posters 8.9k 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.
  • S Offline
    S Offline
    Smeeth
    wrote on 31 Oct 2018, 15:17 last edited by
    #1

    I have some data (uint8_t, uint32_t, float) that I want to write to a raw data file, without any extra information.

    What is the best way to do this? I've read the QDataStream appends every QByteArray with information like the size of the array. This is not what I want; I simply want a file that is only the bytes that I write, and will only be interpretable if someone knows the correct order and size of the data types being written.

    I have tried writing the the QFile directly, but that requires a const char * object. What is the correct way to convert all this data to a const char * without wasting any space?

    A side note that is not really related: I am encrypting this file, and I believe the write way to do this is to extend QFile and reimpliment the write() method to encrypt the data before writing it.

    J J 2 Replies Last reply 31 Oct 2018, 15:45
    0
    • V Offline
      V Offline
      VRonin
      wrote on 31 Oct 2018, 15:21 last edited by
      #2

      Do you require a specific endianness?

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      2
      • E Offline
        E Offline
        Eeli K
        wrote on 31 Oct 2018, 15:43 last edited by
        #3

        const char *QByteArray::constData() const

        1 Reply Last reply
        0
        • S Smeeth
          31 Oct 2018, 15:17

          I have some data (uint8_t, uint32_t, float) that I want to write to a raw data file, without any extra information.

          What is the best way to do this? I've read the QDataStream appends every QByteArray with information like the size of the array. This is not what I want; I simply want a file that is only the bytes that I write, and will only be interpretable if someone knows the correct order and size of the data types being written.

          I have tried writing the the QFile directly, but that requires a const char * object. What is the correct way to convert all this data to a const char * without wasting any space?

          A side note that is not really related: I am encrypting this file, and I believe the write way to do this is to extend QFile and reimpliment the write() method to encrypt the data before writing it.

          J Offline
          J Offline
          JonB
          wrote on 31 Oct 2018, 15:45 last edited by JonB
          #4

          @Smeeth

          I have tried writing the the QFile directly, but that requires a const char * object.

          But you will use the following overload: http://doc.qt.io/qt-5/qiodevice.html#write-2

          qint64 QIODevice::write(const QByteArray &byteArray)

          From your specifications, you will want to write directly to the file IMHO. You have no desire to share your data with anything else, so you will write & read it with your own code. Endian-ness might still be an issue if you want your own program to be cross-platform, e.g. write on one platform and use your own program to read it back on another platform, if you want that ability.

          S 1 Reply Last reply 31 Oct 2018, 17:25
          3
          • J JonB
            31 Oct 2018, 15:45

            @Smeeth

            I have tried writing the the QFile directly, but that requires a const char * object.

            But you will use the following overload: http://doc.qt.io/qt-5/qiodevice.html#write-2

            qint64 QIODevice::write(const QByteArray &byteArray)

            From your specifications, you will want to write directly to the file IMHO. You have no desire to share your data with anything else, so you will write & read it with your own code. Endian-ness might still be an issue if you want your own program to be cross-platform, e.g. write on one platform and use your own program to read it back on another platform, if you want that ability.

            S Offline
            S Offline
            Smeeth
            wrote on 31 Oct 2018, 17:25 last edited by
            #5

            @JonB Thank you, I didn't realize there was an overload for byte array.

            Say I have the following data:

            uint8_t status = getStatus();
            uint8_t channel = getChannel();
            float sourceVal1 = getSource1();
            float sourceVal2 = getSource2();
            uint32_t ticks = getTicks();

            What is the correct way to transform my data into a byte array? The old style cast and static_cast<char> don't seem to do that job (I get a warning "implicit conversion changes signedness", which means this would not work, correct?)

            Endianess is not an issue as the platform will not change.

            J 1 Reply Last reply 31 Oct 2018, 18:06
            0
            • S Smeeth
              31 Oct 2018, 17:25

              @JonB Thank you, I didn't realize there was an overload for byte array.

              Say I have the following data:

              uint8_t status = getStatus();
              uint8_t channel = getChannel();
              float sourceVal1 = getSource1();
              float sourceVal2 = getSource2();
              uint32_t ticks = getTicks();

              What is the correct way to transform my data into a byte array? The old style cast and static_cast<char> don't seem to do that job (I get a warning "implicit conversion changes signedness", which means this would not work, correct?)

              Endianess is not an issue as the platform will not change.

              J Offline
              J Offline
              JonB
              wrote on 31 Oct 2018, 18:06 last edited by JonB
              #6

              @Smeeth
              I'm afraid I'm just the wrong to person to ask that! I'd go memcpy(char_bur, &status, sizeof(status)), or write a union or use a (unsigned char *) cast. (I wouldn't get a "implicit conversion changes signedness", you shouldn't be accessing the int as an int, only its address. Or more like static_cast<char *>&status.) And make a QByteArray from the char buffer/pointer.

              (I'd really just go fwrite(&status, sizeof(status), 1, file_pointer), and the whole thing would be done in one line).

              None of which doubtless is at all allowed/encouraged now. So hopefully a C++ expert will offer some C++ or Qt friendly ways to get those bytes out of the variables.... :)

              1 Reply Last reply
              1
              • S Offline
                S Offline
                Smeeth
                wrote on 31 Oct 2018, 18:08 last edited by Smeeth
                #7

                Thank you for your help. I believe I saw someone else suggest using memcopy in another thread somewhere so I will pursue that route. Thanks!

                J 1 Reply Last reply 31 Oct 2018, 18:12
                0
                • S Smeeth
                  31 Oct 2018, 18:08

                  Thank you for your help. I believe I saw someone else suggest using memcopy in another thread somewhere so I will pursue that route. Thanks!

                  J Offline
                  J Offline
                  JonB
                  wrote on 31 Oct 2018, 18:12 last edited by
                  #8

                  @Smeeth
                  Please don't say I encouraged you to use memcpy. I'll get thrown out of the forum.

                  S 1 Reply Last reply 31 Oct 2018, 18:40
                  2
                  • J JonB
                    31 Oct 2018, 18:12

                    @Smeeth
                    Please don't say I encouraged you to use memcpy. I'll get thrown out of the forum.

                    S Offline
                    S Offline
                    Smeeth
                    wrote on 31 Oct 2018, 18:40 last edited by
                    #9

                    @JonB I swear I heard it elsewhere! :)

                    1 Reply Last reply
                    2
                    • E Offline
                      E Offline
                      Eeli K
                      wrote on 31 Oct 2018, 19:09 last edited by
                      #10
                      const char* charbytes{reinterpret_cast<const char*>(original_data)};
                      int size{static_cast<int>(sizeof(original_type))};
                      QByteArray bytes{charbytes, size};
                      
                      E 1 Reply Last reply 31 Oct 2018, 19:35
                      1
                      • E Eeli K
                        31 Oct 2018, 19:09
                        const char* charbytes{reinterpret_cast<const char*>(original_data)};
                        int size{static_cast<int>(sizeof(original_type))};
                        QByteArray bytes{charbytes, size};
                        
                        E Offline
                        E Offline
                        Eeli K
                        wrote on 31 Oct 2018, 19:35 last edited by
                        #11

                        Works the other way, too:

                        auto myStruct = reinterpret_cast<MyStruct*>(bytearray.data());
                        // "The pointer remains valid as long as the byte array isn't reallocated or destroyed."
                        

                        The same structure in both ends is of course handy unless you need really variable data. In the latter case you have to create a complicated protocol and it would be better to use a higher level protocol.

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          mpergand
                          wrote on 31 Oct 2018, 19:50 last edited by
                          #12

                          If you want to write raw data, use raw C functions :)

                          #include <cstdio>
                          
                          FILE * file;
                          file = fopen ("MyFile.dat", "wb");
                          fwrite (&status , 1, 1, file);
                          fwrite (&channel , 1, 1, file);
                          fwrite (&sourceVal1 , sizeof(float), 1, file);
                          fwrite (&sourceVal2 , sizeof(float), 1, file);
                          fwrite (&ticks , sizeof(ticks), 1, file);
                          fclose (file);
                          
                          J 1 Reply Last reply 31 Oct 2018, 20:07
                          0
                          • M mpergand
                            31 Oct 2018, 19:50

                            If you want to write raw data, use raw C functions :)

                            #include <cstdio>
                            
                            FILE * file;
                            file = fopen ("MyFile.dat", "wb");
                            fwrite (&status , 1, 1, file);
                            fwrite (&channel , 1, 1, file);
                            fwrite (&sourceVal1 , sizeof(float), 1, file);
                            fwrite (&sourceVal2 , sizeof(float), 1, file);
                            fwrite (&ticks , sizeof(ticks), 1, file);
                            fclose (file);
                            
                            J Offline
                            J Offline
                            JonB
                            wrote on 31 Oct 2018, 20:07 last edited by JonB
                            #13

                            @mpergand
                            OMG! But that's what I said. I assumed you'd be shot for that here!
                            To be fair, I assumed the OP would want to use the QFile class to do his writing. Isn't one of the points of Qt to use QFile etc. instead of the C/C++ stdio stuff?

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              aha_1980
                              Lifetime Qt Champion
                              wrote on 31 Oct 2018, 20:24 last edited by
                              #14

                              What about QFile::writeData()?

                              Qt has to stay free or it will die.

                              1 Reply Last reply
                              3
                              • S Smeeth
                                31 Oct 2018, 15:17

                                I have some data (uint8_t, uint32_t, float) that I want to write to a raw data file, without any extra information.

                                What is the best way to do this? I've read the QDataStream appends every QByteArray with information like the size of the array. This is not what I want; I simply want a file that is only the bytes that I write, and will only be interpretable if someone knows the correct order and size of the data types being written.

                                I have tried writing the the QFile directly, but that requires a const char * object. What is the correct way to convert all this data to a const char * without wasting any space?

                                A side note that is not really related: I am encrypting this file, and I believe the write way to do this is to extend QFile and reimpliment the write() method to encrypt the data before writing it.

                                J Offline
                                J Offline
                                J.Hilk
                                Moderators
                                wrote on 1 Nov 2018, 10:07 last edited by
                                #15

                                To get back to the original question, I think we derailed a bit with QByteArray

                                @Smeeth said in Writing raw data to a file using QFile:

                                I have some data (uint8_t, uint32_t, float) that I want to write to a raw data file, without any extra information.

                                Never the less @aha_1980 is right,´qint64 QIODevice::write(const char *data, qint64 maxSize)´ is the way to go

                                this, should do just fine, its untested however.

                                QFile f (...);
                                ....
                                
                                uint8_t var1;
                                uint32_t var2;
                                float var3;
                                
                                f.write(reinterpret_cast<const char *>(&var1), sizeof(uint8_t));
                                f.write(reinterpret_cast<const char *>(&var2), sizeof(uint32_t ));
                                f.write(reinterpret_cast<const char *>(&var3), sizeof(float ));
                                

                                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                Q: What's that?
                                A: It's blue light.
                                Q: What does it do?
                                A: It turns blue.

                                M 1 Reply Last reply 1 Nov 2018, 13:18
                                3
                                • J J.Hilk
                                  1 Nov 2018, 10:07

                                  To get back to the original question, I think we derailed a bit with QByteArray

                                  @Smeeth said in Writing raw data to a file using QFile:

                                  I have some data (uint8_t, uint32_t, float) that I want to write to a raw data file, without any extra information.

                                  Never the less @aha_1980 is right,´qint64 QIODevice::write(const char *data, qint64 maxSize)´ is the way to go

                                  this, should do just fine, its untested however.

                                  QFile f (...);
                                  ....
                                  
                                  uint8_t var1;
                                  uint32_t var2;
                                  float var3;
                                  
                                  f.write(reinterpret_cast<const char *>(&var1), sizeof(uint8_t));
                                  f.write(reinterpret_cast<const char *>(&var2), sizeof(uint32_t ));
                                  f.write(reinterpret_cast<const char *>(&var3), sizeof(float ));
                                  
                                  M Offline
                                  M Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on 1 Nov 2018, 13:18 last edited by
                                  #16

                                  @J.Hilk
                                  Works fine :)

                                  template< class aType >
                                  qint64 write( QFile& file, aType var ) {
                                    qint64 toWrite = sizeof(decltype (var));
                                    qint64  written = file.write(reinterpret_cast<const char*>(&var), toWrite);
                                    if (written != toWrite) {
                                      qDebug () << "write error";
                                    }
                                     qDebug () << "out: " << written;
                                    return written;
                                  }
                                  
                                  
                                  template< class aType >
                                  qint64 read( QFile& file, aType &var ) {
                                    qint64 toRead = sizeof(decltype (var));
                                    qint64  read = file.read(reinterpret_cast<char*>(&var), toRead);
                                    if (toRead != read) {
                                      qDebug () << "read error";
                                    }
                                    qDebug () << "in: " << read;
                                    return read;
                                  }
                                  
                                   QFile file("e:/test.txt");
                                    if (!file.open(QFile::WriteOnly)) {
                                      return;
                                    }
                                  
                                    uint8_t var1 = 10;
                                    uint32_t var2 = 20000;
                                    float var3 = 10.8;
                                  
                                    write(file, var1);
                                    write(file, var2);
                                    write(file, var3);
                                  
                                    file.close();
                                  
                                    var1 = 0; var2 = 0; var3 = 0;
                                  
                                    if (!file.open(QFile::ReadOnly)) {
                                      return;
                                    }
                                  
                                    read(file, var1);
                                    read(file, var2);
                                    read(file, var3);
                                  
                                  qDebug() << " result = " << var1 << " " << var2 << " " << var3;
                                  
                                  

                                  out: 1
                                  out: 4
                                  out: 4
                                  in: 1
                                  in: 4
                                  in: 4
                                  result = 10 20000 10.8

                                  but file is fragile to platform change etc.

                                  1 Reply Last reply
                                  2

                                  7/16

                                  31 Oct 2018, 18:08

                                  • Login

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