Search code examples
ccs50

Difference between fread() & fwrite() while using fseek()?


I'm currently working on a problem in CS50x, I have to reverse a existing WAV file and make it into a new one. I've been able to tackle all other TODOs (I think) but using fopen, fwrite and fseek is causing me a headache. Here's the code I wrote:

for (int i = 0; i < iterateCount; i++)
    {
        fseek(input, -blockSize * (i + 1), SEEK_END);
        fseek(output, headerSize + blockSize * i, SEEK_SET);

        // copy & paste
        fread(&buffer, blockSize, 1, input);
        fwrite(&buffer, blockSize, 1, output);
    }

So, what the code's trying to do is iterating over the original file(aka "input") and copy & pasting over the new file(aka "output").

This code works JUST FINE actually, but when I searched for more information about the problem so I can found something to improve in efficiency, people seemed to not use fseek() with output. I thought I had to iterate over not only input but also output too because if I didn't, fwrite would write the new information to the same location over and over again. Or is it??

My question is, does fwrite() have the feature same to fseek() by itself?

I removed the fseek() for output and it indeed worked fine.


Solution

  • people seemed to not use fseek() with output. I thought I had to iterate over not only input but also output too because if I didn't, fwrite would write the new information to the same location over and over again. Or is it??

    No, that is not the case.

    You seem to understand that the system maintains a sense of a current position in each stream (file). fseek() is one way to modify that. But successfully reading from or writing to a stream also modifies its file position. They advance it by the number of bytes transferred, which is almost always what you want. If the file is not manually repositioned then the next read just picks up where the last one left off. For writes without repositioning, the next write starts immediately after the last byte written, or (always) at the end of the file if it is open in append mode. It's more complicated if you're both reading and writing the same file, but that's not your case.

    My question is, does fwrite() have the feature same to fseek() by itself?

    That's an odd way to put it. fseek() is by far the exception, not the rule. Many programs do I/O without ever calling fseek(). The fwrite() function does update the file position, as already discussed, but few people would characterize that as fwrite() performing an fseek(). Some files are not even seekable -- the only way to change their file positions is by reading from them or writing to them. stdin, stdout, and stderr often have this characteristic, for example.

    I removed the fseek() for output and it indeed worked fine.

    As I would expect. Overall, the section of code presented writes a contiguous section of the output file, starting at the beginning of that section and continuing in order to the end. That doesn't require any seeking, and it would be better to omit the fseek()s on this file for clarity and to reduce the cross section for bugs.

    The situation for the reads is different -- you are reading, blockwise, from end to beginning, so after each block you are not automatically at the start position for the next read. You do need to reposition (via fseek()) in that case.