Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    More data help

    C++ Gurus
    5
    16
    5447
    Loading More Posts
    • 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.
    • J
      jnewing last edited by

      the binary data is pulled from a file
      fields are separated by 0x7c "|" char

      the data
      @46 49 4C 45 48 45 41 44 45 52 8C 00 00 00 30 00 00 00 7C 53 54 52 49
      4E 47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00 00 00 00 00 00 7C 03 00 7C 73 74 72 7C 0B 00
      7C 61 6E 6F 74 68 65 72 20 73 74 72 7C 1E 00 00 00 7C 09 00 7C 30 30
      30 2E 34 33 2E 32 39 7C
      @

      data breakdown;
      breakdown of the data is as follows;
      @uchar[0x0a] "46 49 4C 45 48 45 41 44 45 52 " (this is a constant file header)
      ulong[0x4] "8C 00 00 00" (unsigned long value)
      ulong[0x4] "30 00 00 00" (unsigned long value)
      uchar[0x1] "7C" (field separator)
      uchar[0x3f] "53 54 52 49
      4E 47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00 00 00 00 00 00" (constant char[])
      uchar[0x1] "7C" (field separator)
      ushort[0x2] "03 00" (length of the next char[] after the field separator)
      uchar[0x1] "7C" (field separator)
      uchar[0x3] "73 74 72" (char[] length defined by previous field NOT including the field separator)@

      currently what I'm doing is reading the data one char at a time looking for field separator 0x7c and put prior to that into a variable.
      I know this is not very efficient etc... this is why I'm looking for a better way would a struct be an option?
      @
      struct foo {
      unsigned char f1[0x0a];
      unsigned long f2[0x4];
      ...
      unsigned shot f3_len[0x2];
      unsigned char f3[f3_len];
      ...
      } bar;

      infile.read(bar, sizeof(bar));
      @

      any help / feedback is appreciated - thanks

      1 Reply Last reply Reply Quote 0
      • J
        jnewing last edited by

        Also another question I had, didn't feel it warranted a new thread,

        Say I had the above data in a QByteArray, know say I know that at offset 0x53, the next two bytes make up a qint16 integer, what would be the best way to go about reading that into an int?

        currently I'm using QString to turn it into a string and then toInt from there, this seems a little much, i though about using memcopy however really was hoping there is a nicer way of doing it.

        -thx

        1 Reply Last reply Reply Quote 0
        • V
          vsorokin last edited by

          1. Using of structure is better way.
          2. Try look on QByteArray().data() method, it returned const char* on data, may be you can add your offset for this and get needed bytes

          --
          Vasiliy

          1 Reply Last reply Reply Quote 0
          • G
            goetz last edited by

            QByteArray has some method that could be of use for you:

            • indexOf with a single char can help you finding the field separators
            • mid() can extract the snippets you're in need of (use in conjunction with the indexes found with the previous function)
            • toInt, toLong might be of use for the ints, but watch out for endianess!

            If you create the file you read of with Qt too, you should have a look at QDataStream. It contains nice platform independent conversion methods for various types.

            http://www.catb.org/~esr/faqs/smart-questions.html

            1 Reply Last reply Reply Quote 0
            • J
              jnewing last edited by

              volker oddly enough this does not work

              @qint16 foo = data.mid(0x64, 2).toInt();@

              so to test i added some watches and did the following
              @QByteArray foo = data.mid(0x64, 2);
              qint16 bar = foo.toInt(); // note i also tried toShort();
              @

              foo does indeed get the data that is expected "0x03, 0x00" however it does not convert this
              to a int, sort or anything else. they all return 0

              1 Reply Last reply Reply Quote 0
              • G
                goetz last edited by

                Ah, sorry, I misread the docs. You'll have to convert the data to an int yourself:

                @
                qint16 bar = ba.at(0x64) + (ba.at(0x64 +1) << 8);
                @

                QDataStream is not an option?

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply Reply Quote 0
                • J
                  jnewing last edited by

                  I was unable to get datastream to work :/ ether, have you tried it?

                  1 Reply Last reply Reply Quote 0
                  • A
                    andre last edited by

                    QDataStream works reliably for me. If you have the option of using it, I suggest you do.

                    Just make sure that if you stream integers in and out, you use one of Qts explicit types: quint16, qint64, etc., so you have well defined items in your binairy file. These types are guaranteed to be the same on all supported platforms. Also, it is wise to explicitly set a version for the datastream at both ends.

                    You can even overload the operator<<() and operator>>() for your class or struct, and stream the whole block of data in one go that way.

                    1 Reply Last reply Reply Quote 0
                    • G
                      goetz last edited by

                      [quote author="jnewing" date="1303253359"]I was unable to get datastream to work :/ ether, have you tried it?[/quote]

                      It works perfectly. But you must create the file using QDataStream for writing too!

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply Reply Quote 0
                      • J
                        jnewing last edited by

                        I found a quick simple way, here is an example:

                        @
                        QDataArray foo; // is filled with binary data
                        qint16 bar = static_cast<qint16>(data[0x5e]);
                        @

                        that works quite efficiently.

                        thanks: Volker, Andre

                        1 Reply Last reply Reply Quote 0
                        • G
                          goetz last edited by

                          This code is not platform independent (big/small endian!). You will run into some troubles eventually. Do yourself a favor and do it the right way from the very beginning!

                          http://www.catb.org/~esr/faqs/smart-questions.html

                          1 Reply Last reply Reply Quote 0
                          • J
                            jnewing last edited by

                            [quote author="Volker" date="1303300686"]This code is not platform independent (big/small endian!). You will run into some troubles eventually. Do yourself a favor and do it the right way from the very beginning![/quote]

                            Yah your right, thx again.

                            1 Reply Last reply Reply Quote 0
                            • T
                              tobias.hunger last edited by

                              "QtEndian":http://doc.qt.nokia.com/4.7/qtendian.html has some helper functions for endianess issues. A little known corner of Qt:-)

                              1 Reply Last reply Reply Quote 0
                              • J
                                jnewing last edited by

                                [quote author="Tobias Hunger" date="1303308248"]"QtEndian":http://doc.qt.nokia.com/4.7/qtendian.html has some helper functions for endianess issues. A little known corner of Qt:-)[/quote]

                                So using this tasty little tidbit and because I already had my data into a QByteArray I wrote some functions in a untility class as follows;

                                @
                                qint16 ByteUtils::extractUInt16(const QByteArray& data, int offset, bool bigendian)
                                {
                                if (bigendian)
                                return qFromBigEndian<qint16>((uchar*)data.mid(offset, 0x2).data());
                                else
                                return qFromLittleEndian<qint16>((uchar*)data.mid(offset, 0x2).data());

                                }

                                qint32 ByteUtils::extractUInt32(const QByteArray& data, int offset, bool bigendian)
                                {
                                if (bigendian)
                                return qFromBigEndian<qint32>((uchar*)data.mid(offset, 0x4).data());
                                else
                                return qFromLittleEndian<qint32>((uchar*)data.mid(offset, 0x4).data());

                                }
                                @

                                works like a charm ;) thanks all

                                1 Reply Last reply Reply Quote 0
                                • T
                                  tobias.hunger last edited by

                                  I'd just decide on one byte order to use in the file and stick with that. That avoids the bigendian bool and the if/else. Branches are always slow and avoiding them in a method that is called all the time is a good idea: Extracting ints from a data file smells like something that will happen rather often.

                                  Why do you need the data.mid()? That constructs a temporary object that is not necessary. @data.constData() + offset@ should work just as well as @data.mid(offset, 2).data()@ without creating a temporary object.

                                  I'd also try to use constData whenever possible. Using data() the way you do the compiler might think it needs to copy the temporary object you created since somebody might want to write into those bytes. Using constData is a very clear hint that this is not going to happen and the compiler can optimize the copy out. Of course it might be intelligent enough to do it for the data() case, too, but who wants to bet on the compiler being intelligent? ;-)

                                  1 Reply Last reply Reply Quote 0
                                  • J
                                    jnewing last edited by

                                    [quote author="Tobias Hunger" date="1303314614"]I'd just decide on one byte order to use in the file and stick with that. That avoids the bigendian bool and the if/else. Branches are always slow and avoiding them in a method that is called all the time is a good idea: Extracting ints from a data file smells like something that will happen rather often.

                                    Why do you need the data.mid()? That constructs a temporary object that is not necessary. @data.constData() + offset@ should work just as well as @data.mid(offset, 2).data()@ without creating a temporary object.

                                    I'd also try to use constData whenever possible. Using data() the way you do the compiler might think it needs to copy the temporary object you created since somebody might want to write into those bytes. Using constData is a very clear hint that this is not going to happen and the compiler can optimize the copy out. Of course it might be intelligent enough to do it for the data() case, too, but who wants to bet on the compiler being intelligent? ;-)
                                    [/quote]

                                    I have no control over the file and it has both bigendian and littleendian values (just to make my life hard) as it was a pc game that was ported to xbox 360 :s

                                    Also you're 100% right I'll use the data.constData() + offset as I have no real need for a temp object :) thanks again.

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post