3

This is the loop I have for reading from a file of any size, and writing to a 1016 byte char* packet 1016 bytes each time then sending it (sending not included yet).

Is the seekg() necessary? Or does reading move the pointer to the front of the next chunk already?

ifstream file (packet.message, ios::in|ios::binary|ios::ate);
if(file.is_open()) {
    size = file.tellg();
    file.seekg(0, ios::beg);
    for(int i = 0; !ios::eof; i++) {
        memset(packet.message,0,1016*sizeof(char));
        file.read(packet.message,1016*sizeof(char));
        file.seekg(i*1016*sizeof(char));
    }
}

I know this isn't an issue for writing to a file, since you just keep writing to the end until the file is the right size.

Edit: added the whole bit of code in the if statement.

Portaljacker
  • 3,102
  • 5
  • 25
  • 33
  • You know, you can always just compile the code, run it and see if it does what you want.. – Brendan Long Oct 03 '12 at 19:41
  • There's a lot of other things going on. I'd have to make a separate program. – Portaljacker Oct 03 '12 at 19:42
  • You say that as if creating a C++ program is hard. I tend to write, compile and run a small program almost every time I answer a question about C++ (mainly because I don't use C++ often and I don't want to post code samples that don't compile). – Brendan Long Oct 03 '12 at 19:44
  • 1) Using `.eof()` as a loop condition is [almost always a bad idea](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). 2) `.eof()` is a function to invoke, NOT a flag to test. – Robᵩ Oct 03 '12 at 19:44
  • @BrendanLong Sound advice in some cases, but in C and C++ it fails quite often due implementation-defined and undefined behavior. –  Oct 03 '12 at 19:44
  • @delnan In some cases it's definitely necessary to ask what the standard says, but in this case it's a basic yes/no question: If I don't call `seekg()`, will I get the same data over and over again? – Brendan Long Oct 03 '12 at 19:46
  • To complete Robᵩ's answer: 1) eof() will only tell you the PREVIOUS I/O operation reached the end of file, so using it in a loop like that is wrong; 2) if you had to seek before every read, the API would be pretty much useless to consume a whole file; 3) stream objects are meant for handling textual representations, if you have binary data the low-level streambuf objects are more convenient and efficient. – DanielKO Oct 03 '12 at 19:53
  • @DanielKO 1) the point is that I can ignore the file size, so if less than 1016 is remaining in the file, read will truncate at eof and set the bit, and only save the part of the file that was remaining. On the next iteration eof would be true. 2) That makes a lot of sense, I just wasn't really sure. I'm removing the seekg from the end of the iterations. 3) The way we're sending the packets is as a char* array. It's what we were told to do honestly. – Portaljacker Oct 03 '12 at 19:59
  • @DanielKO What should I use instead of eof()? – Portaljacker Oct 03 '12 at 20:03
  • read() returns the stream object, so you can just test it to see if the operation succeeded. As in "while (file.read(....)) { ... }", that's how it's typically used. – DanielKO Oct 03 '12 at 20:14
  • @DanielKO So then just move the line into the loop statement and do the work inside. I guess my memset has to be at the end of the loop iteration then, since I don't want to erase before I send the packet. :P – Portaljacker Oct 03 '12 at 20:16

2 Answers2

7

It's not necessary. Reading continues from where the file pointer was last seen, exactly like writing does.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • Thanks, I guess this can become a while loop now! – Portaljacker Oct 03 '12 at 19:39
  • 1
    @Portaljacker - You also probably don't need the seek the precedes the loop. – Robᵩ Oct 03 '12 at 19:45
  • @Robᵩ I only put it there because in the example it shows to. I didn't show that the line before I save the size using tellg(). I assumed tellg() moved the pointer. – Portaljacker Oct 03 '12 at 19:47
  • `tellg()` doesn't, but it sounds like you had a prior `seekg()`. In that case, you probably do need to reset back to the beginning. – Robᵩ Oct 03 '12 at 19:49
  • @Robᵩ The example I got it from is odd...it does what I did in the example, tellg then seekg to 0. It says tellg gives the current position of the pointer, which would be the size if it were at end of file right? Tutorial in question: http://www.cplusplus.com/doc/tutorial/files/ – Portaljacker Oct 03 '12 at 19:52
0

I would venture a bet that the file wasn't opened in std::ios_base::binary mode and both the memset() and the seekg() were used to gloss over the resulting effects: neither is needed although you might need to clear the trailing bytes at the end of the file if it read a partial record.

BTW: you always want to check the state of the stream after reading:

while (in.read(buffer, size)) {
    ...
}

Also: sizeof(char) == 1.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Are you saying this is newly written code? Loose all of the calls to `seekg()` (you don't even use the `size`, not to mention that it might give you a wrong result, e.g., if a non-C `std::codecvt` facet is used). Also, loose the `memset()`: the data gets overwritten by the `read()` anyway, although you might want to verify you read the expected amount of data. ... and your loop condition is clearly wrong and should be `file.read(...)`. – Dietmar Kühl Oct 03 '12 at 20:01
  • The memset is for making sure the packet is 0'd before writing to it. Size is used for something else, but its poisition is important since I have to send the size to the other machine before transfer. Like I said, I didn't put any of the network code, just moving stuff into the packet before that. – Portaljacker Oct 03 '12 at 20:04
  • The `memset()` is pointless as is: except potentially for the last packet all bytes get overwritten by the `read()`! You can set the trailing bytes which were not written using `gcount()`: `while (file.read(buffer, size)) { std::fill(buffer + file.gcount(), buffer + size, 0); send(buffer, size); }`. Whether seeking to end of the file gives you the size of a rough approximation is pretty much not defined. The result of the seek can be used to restore the position. Computations on seek positions do work but you'd need, at least, take the difference between the end and the start. – Dietmar Kühl Oct 03 '12 at 20:15