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. readRawData(char *s, int len) build-in function doesn't read char *buff of the len size and doesn't return number of data read
QtWS25 Last Chance

readRawData(char *s, int len) build-in function doesn't read char *buff of the len size and doesn't return number of data read

Scheduled Pinned Locked Moved Solved General and Desktop
bytearray
10 Posts 2 Posters 4.4k 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.
  • A Offline
    A Offline
    ainu
    wrote on 2 Nov 2017, 13:12 last edited by
    #1

    Hi, my question concern the use of readRawData( ... ) function, I tried to read 3 files of different size ( 11 Kb, 5 Mb and 2 Gb ) with readRawData( char *buffer, int size ).
    size was set to 460 byte, memory for buffer was allocated with calloc. ( i understand that it is better to avoid using C in C++ code it will be changed a bit later ). Files of size 5 Mb and 2Gb were filled with random values, 11 Kb was normal text file.
    While reading 11 Kb file buffer was filled with amount of data equal to the size value. In case of reading 5 Mb and 2 Gb files buffer was filled with random amount of data scarcely equal to size value. Moreover in all cases readRawData retrun 0 ( not number of data read ) although after calling to readRawData buffer was filled with appropriate data ( i could check only the case of 11 Kb file ). The code i am using to read file

    size_t chunk_size = confFile->getDatagramSize() - DATAGRAM_HEADER;
    char *temp;  // chunk without header and pos in chunk sequence
    int size = chunk_size;
    QDataStream in( &file );
    while( !file.atEnd() ) {
                if ( msgN <= file.size() / chunk_size ) {
                    temp = ( char * )calloc( chunk_size + 1, sizeof( char ) );
    
                    size = chunk_size;
                } else {
                    temp = ( char * )calloc( ( file.size() % chunk_size ) + 1, sizeof( char ) );
    
                    size = file.size() % chunk_size;
                }
    
                int dataRead = 0;
                if ( dataRead = in.readRawData( temp, size ) < 0 )    
                    qDebug() << "No datum were read";
    
                temp[ size + 1 ] = '\0';
                filMsgToSnd( fileName, msgN );
                setMsg( QString( temp ) );
    
                processData->setSndMsgsSq( getMsg() );
                ++msgN;    // represent chunk pos in seq
                free( temp );
                temp = NULL;
    
                msg.clear();
            }
    

    Why this could happen?
    Would appreciate any help or advice.
    Thank you in advance.

    J 1 Reply Last reply 2 Nov 2017, 21:00
    0
    • A ainu
      2 Nov 2017, 13:12

      Hi, my question concern the use of readRawData( ... ) function, I tried to read 3 files of different size ( 11 Kb, 5 Mb and 2 Gb ) with readRawData( char *buffer, int size ).
      size was set to 460 byte, memory for buffer was allocated with calloc. ( i understand that it is better to avoid using C in C++ code it will be changed a bit later ). Files of size 5 Mb and 2Gb were filled with random values, 11 Kb was normal text file.
      While reading 11 Kb file buffer was filled with amount of data equal to the size value. In case of reading 5 Mb and 2 Gb files buffer was filled with random amount of data scarcely equal to size value. Moreover in all cases readRawData retrun 0 ( not number of data read ) although after calling to readRawData buffer was filled with appropriate data ( i could check only the case of 11 Kb file ). The code i am using to read file

      size_t chunk_size = confFile->getDatagramSize() - DATAGRAM_HEADER;
      char *temp;  // chunk without header and pos in chunk sequence
      int size = chunk_size;
      QDataStream in( &file );
      while( !file.atEnd() ) {
                  if ( msgN <= file.size() / chunk_size ) {
                      temp = ( char * )calloc( chunk_size + 1, sizeof( char ) );
      
                      size = chunk_size;
                  } else {
                      temp = ( char * )calloc( ( file.size() % chunk_size ) + 1, sizeof( char ) );
      
                      size = file.size() % chunk_size;
                  }
      
                  int dataRead = 0;
                  if ( dataRead = in.readRawData( temp, size ) < 0 )    
                      qDebug() << "No datum were read";
      
                  temp[ size + 1 ] = '\0';
                  filMsgToSnd( fileName, msgN );
                  setMsg( QString( temp ) );
      
                  processData->setSndMsgsSq( getMsg() );
                  ++msgN;    // represent chunk pos in seq
                  free( temp );
                  temp = NULL;
      
                  msg.clear();
              }
      

      Why this could happen?
      Would appreciate any help or advice.
      Thank you in advance.

      J Offline
      J Offline
      JonB
      wrote on 2 Nov 2017, 21:00 last edited by JonB 11 Feb 2017, 21:14
      #2

      @ainu
      if ( dataRead = in.readRawData( temp, size ) < 0 )

      Oh dear, oh dear! Don't you mean:

      if ( ( dataRead = in.readRawData( temp, size ) ) < 0 )

      Not to mention that you'll want to actually reference dataRead after you've got it.... (e.g. temp[ dataRead + 1 ] = '\0'; )? Plus I think conceptually you are assuming dataRead == size after the read, which I imagine will not be guaranteed at all.

      Files of size 5 Mb and 2Gb were filled with random values

      As in random bytes, or text only?

      A 2 Replies Last reply 3 Nov 2017, 05:57
      4
      • J JonB
        2 Nov 2017, 21:00

        @ainu
        if ( dataRead = in.readRawData( temp, size ) < 0 )

        Oh dear, oh dear! Don't you mean:

        if ( ( dataRead = in.readRawData( temp, size ) ) < 0 )

        Not to mention that you'll want to actually reference dataRead after you've got it.... (e.g. temp[ dataRead + 1 ] = '\0'; )? Plus I think conceptually you are assuming dataRead == size after the read, which I imagine will not be guaranteed at all.

        Files of size 5 Mb and 2Gb were filled with random values

        As in random bytes, or text only?

        A Offline
        A Offline
        ainu
        wrote on 3 Nov 2017, 05:57 last edited by ainu 11 Mar 2017, 06:52
        #3

        @JNBarchan You answer lead to me to depressed mood as i realised i forgot C++ Operator Precedence. Thank you for detailed answer.
        As fore referencing readData, no i didn't want to do this as i add this variable just for debugging to see that data read by readRawData() function equal to the actual number of data i was intended to read with this function ( i.e. the "size" variable ). The thing is that when i am using readRawData function it fills temp with variable amount of data which rarely depend on the size parameter. That was the actual reason to write here and the main question ( dataRead was added as i wrote above only for debugging, regretfuly ).

        1 Reply Last reply
        0
        • J JonB
          2 Nov 2017, 21:00

          @ainu
          if ( dataRead = in.readRawData( temp, size ) < 0 )

          Oh dear, oh dear! Don't you mean:

          if ( ( dataRead = in.readRawData( temp, size ) ) < 0 )

          Not to mention that you'll want to actually reference dataRead after you've got it.... (e.g. temp[ dataRead + 1 ] = '\0'; )? Plus I think conceptually you are assuming dataRead == size after the read, which I imagine will not be guaranteed at all.

          Files of size 5 Mb and 2Gb were filled with random values

          As in random bytes, or text only?

          A Offline
          A Offline
          ainu
          wrote on 3 Nov 2017, 06:06 last edited by
          #4

          @JNBarchan

          Files of size 5 Mb and 2Gb were filled with random values

          As in random bytes, or text only?

          Yeah, random bytes. Do you think this is the reason, I also thought that it could be the point but as function readRawData( ... ) is designed for reading raw binary data i tried to think about other reasons but what do you think?

          J 1 Reply Last reply 3 Nov 2017, 08:36
          0
          • A ainu
            3 Nov 2017, 06:06

            @JNBarchan

            Files of size 5 Mb and 2Gb were filled with random values

            As in random bytes, or text only?

            Yeah, random bytes. Do you think this is the reason, I also thought that it could be the point but as function readRawData( ... ) is designed for reading raw binary data i tried to think about other reasons but what do you think?

            J Offline
            J Offline
            JonB
            wrote on 3 Nov 2017, 08:36 last edited by JonB 11 Mar 2017, 08:37
            #5

            @ainu

            Please don't be "depressed" :) Just be careful if you use the C-style assign-and-test pattern (( var = func() ) < value) that the assignment segment must be parenthesized, you are not the first person to omit them and result in a tale of woe!

            For the number of byes, you must be careful to respect the documentation for readRawData(). As for most read-type functions, it says:

            int QDataStream::readRawData(char *s, int len)
            Reads at most len bytes from the stream into s and returns the number of bytes read. If an error occurs, this function returns -1.

            Note what I have bolded. You must not assume it will read all of the len bytes you have asked for, only that it will read up to that number, and will return the number it actually it read. So you must use the return result (your dataRead, not your size) to determine how many bytes are actually valid in your buffer.

            There is no problem with readRawData() reading arbitrary bytes rather than text. However, when you then proceed to go:

            temp[ dataRead + 1 ] = '\0';
            setMsg( QString( temp ) );
            

            For "random bytes" your data read into buffer may contain \0 bytes, in which case your idea of plonking a \0 on the end and treating it as a string is flawed, as it may be "cut short" by an embedded \0. Just be aware of that.

            Other than that, if you adjust your code to use dataRead correctly as I have indicated, it looks to me as though it will actually work, so you can press on....

            A 1 Reply Last reply 4 Nov 2017, 16:37
            4
            • J JonB
              3 Nov 2017, 08:36

              @ainu

              Please don't be "depressed" :) Just be careful if you use the C-style assign-and-test pattern (( var = func() ) < value) that the assignment segment must be parenthesized, you are not the first person to omit them and result in a tale of woe!

              For the number of byes, you must be careful to respect the documentation for readRawData(). As for most read-type functions, it says:

              int QDataStream::readRawData(char *s, int len)
              Reads at most len bytes from the stream into s and returns the number of bytes read. If an error occurs, this function returns -1.

              Note what I have bolded. You must not assume it will read all of the len bytes you have asked for, only that it will read up to that number, and will return the number it actually it read. So you must use the return result (your dataRead, not your size) to determine how many bytes are actually valid in your buffer.

              There is no problem with readRawData() reading arbitrary bytes rather than text. However, when you then proceed to go:

              temp[ dataRead + 1 ] = '\0';
              setMsg( QString( temp ) );
              

              For "random bytes" your data read into buffer may contain \0 bytes, in which case your idea of plonking a \0 on the end and treating it as a string is flawed, as it may be "cut short" by an embedded \0. Just be aware of that.

              Other than that, if you adjust your code to use dataRead correctly as I have indicated, it looks to me as though it will actually work, so you can press on....

              A Offline
              A Offline
              ainu
              wrote on 4 Nov 2017, 16:37 last edited by
              #6

              @JNBarchan thank you for your detailed answer. It really helps me a lot and i followed ( of course ) your advice on using return result of function readRawData() instead of size of buf which i used before.
              But i still wonder what is the reason that this function behave differently with different files, i.e. when i pass small size file ( like a few kB ) it fills buf with data equal to the size of the buffer but in the case of heavy files it behaves differently and fills buf with random amount of data. The difference between files not just in their size but in the data they keep also. In case of small size file it contains normal text, in case of heavy files it is random data ( this line was used: head -c 2G </dev/urandom >file ). Do you think it can also be because of random data contain "\0"? It would be interesting to learn this but maybe of course it is better to check it in source code

              J 1 Reply Last reply 6 Nov 2017, 09:52
              0
              • A ainu
                4 Nov 2017, 16:37

                @JNBarchan thank you for your detailed answer. It really helps me a lot and i followed ( of course ) your advice on using return result of function readRawData() instead of size of buf which i used before.
                But i still wonder what is the reason that this function behave differently with different files, i.e. when i pass small size file ( like a few kB ) it fills buf with data equal to the size of the buffer but in the case of heavy files it behaves differently and fills buf with random amount of data. The difference between files not just in their size but in the data they keep also. In case of small size file it contains normal text, in case of heavy files it is random data ( this line was used: head -c 2G </dev/urandom >file ). Do you think it can also be because of random data contain "\0"? It would be interesting to learn this but maybe of course it is better to check it in source code

                J Offline
                J Offline
                JonB
                wrote on 6 Nov 2017, 09:52 last edited by
                #7

                @ainu
                You keep using the word "file". However, is your stream really an actual physical, already-created file on a hard disk, or something else? Because your code:

                size_t chunk_size = confFile->getDatagramSize() - DATAGRAM_HEADER;
                

                makes it look like it's something to do with a Datagram?

                A 1 Reply Last reply 7 Nov 2017, 05:07
                0
                • J JonB
                  6 Nov 2017, 09:52

                  @ainu
                  You keep using the word "file". However, is your stream really an actual physical, already-created file on a hard disk, or something else? Because your code:

                  size_t chunk_size = confFile->getDatagramSize() - DATAGRAM_HEADER;
                  

                  makes it look like it's something to do with a Datagram?

                  A Offline
                  A Offline
                  ainu
                  wrote on 7 Nov 2017, 05:07 last edited by
                  #8

                  @JNBarchan yeah, i use files ( for testing ) from computer to feed to the program. The actual idea of the program is that it will read files from a particular dir ( stream might be added later ) and split them in chunks of a predefined size, after headers will be added. I am trying to implement kind of my own udp protocol, I mean udp datagrams but with my own headers.

                  J 1 Reply Last reply 7 Nov 2017, 09:26
                  0
                  • A ainu
                    7 Nov 2017, 05:07

                    @JNBarchan yeah, i use files ( for testing ) from computer to feed to the program. The actual idea of the program is that it will read files from a particular dir ( stream might be added later ) and split them in chunks of a predefined size, after headers will be added. I am trying to implement kind of my own udp protocol, I mean udp datagrams but with my own headers.

                    J Offline
                    J Offline
                    JonB
                    wrote on 7 Nov 2017, 09:26 last edited by JonB 11 Jul 2017, 09:36
                    #9

                    @ainu
                    Then in answer to your question:

                    But i still wonder what is the reason that this function behave differently with different files, i.e. when i pass small size file ( like a few kB ) it fills buf with data equal to the size of the buffer but in the case of heavy files it behaves differently and fills buf with random amount of data.

                    The underlying file access routines will have some kind of buffer size somewhere (though I don't see it accessible from Qt). (It's often a (small) multiple of 4K, e.g. 4K or 8K, possibly.) If the whole of the file fits into the buffer you'll (probably) get the whole of it back on first call, otherwise you'll get it in chunks. I would not expect larger files to fill with a "random amount of data", but rather the buffer size, but in any case you must accept whatever it says it has read.

                    Another possibility is that it is affected by the way you have opened the file. You do not show that code, and yours might be incorrect. Do you have something like:

                    file.open(QIODevice::ReadOnly | QIODevice::Text)
                    

                    If you do and are using QIODevice::Text, that would be wrong for your "random bytes binary file", and might affect the chunks returned by looking for \r\n sequences (though the code might not do that under Linux, I don't know). I have already explained that if the file contains \0 bytes these will read correctly but your QString() debugging code will be "wrong".

                    It's also possible that the size you pass to readRawData() could affect how chunks are returned. Optimal will be some multiple (like 1x) of the underlying buffer size. Yours is confFile->getDatagramSize() - DATAGRAM_HEADER, which will not be such a multiple, and changing that might give a "smoother" number of chunks/sizes.

                    If you really need to end up "split them in chunks of a predefined size" to pass on, you really should implement that logic in your own code rather than relying on readRawData() to definitely return a particular, full chunk size that you can use directly, even though it's annoying to have to implement extra code and the readRawData() might end up returning the desired chunk size anyway.

                    A 1 Reply Last reply 7 Nov 2017, 12:19
                    1
                    • J JonB
                      7 Nov 2017, 09:26

                      @ainu
                      Then in answer to your question:

                      But i still wonder what is the reason that this function behave differently with different files, i.e. when i pass small size file ( like a few kB ) it fills buf with data equal to the size of the buffer but in the case of heavy files it behaves differently and fills buf with random amount of data.

                      The underlying file access routines will have some kind of buffer size somewhere (though I don't see it accessible from Qt). (It's often a (small) multiple of 4K, e.g. 4K or 8K, possibly.) If the whole of the file fits into the buffer you'll (probably) get the whole of it back on first call, otherwise you'll get it in chunks. I would not expect larger files to fill with a "random amount of data", but rather the buffer size, but in any case you must accept whatever it says it has read.

                      Another possibility is that it is affected by the way you have opened the file. You do not show that code, and yours might be incorrect. Do you have something like:

                      file.open(QIODevice::ReadOnly | QIODevice::Text)
                      

                      If you do and are using QIODevice::Text, that would be wrong for your "random bytes binary file", and might affect the chunks returned by looking for \r\n sequences (though the code might not do that under Linux, I don't know). I have already explained that if the file contains \0 bytes these will read correctly but your QString() debugging code will be "wrong".

                      It's also possible that the size you pass to readRawData() could affect how chunks are returned. Optimal will be some multiple (like 1x) of the underlying buffer size. Yours is confFile->getDatagramSize() - DATAGRAM_HEADER, which will not be such a multiple, and changing that might give a "smoother" number of chunks/sizes.

                      If you really need to end up "split them in chunks of a predefined size" to pass on, you really should implement that logic in your own code rather than relying on readRawData() to definitely return a particular, full chunk size that you can use directly, even though it's annoying to have to implement extra code and the readRawData() might end up returning the desired chunk size anyway.

                      A Offline
                      A Offline
                      ainu
                      wrote on 7 Nov 2017, 12:19 last edited by
                      #10

                      @JNBarchan thank you for the detailed answer.

                      1 Reply Last reply
                      0

                      10/10

                      7 Nov 2017, 12:19

                      • Login

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