I'm trying to make a basic program which copies the header of a .wav file, this was my attempt:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
FILE* input = fopen("input.wav", "r");
FILE* output = fopen("output.wav", "w");
uint8_t header [44];
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
fclose(input);
fclose(output);
}
However, after failing to make it work, I looked up how to do it and apparently
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
should be
fread(header, 44, 1, input);
fwrite(header, 44, 1, output);
This is very confusing to me, as I thought that the second argument was supposed to be the size of the type of data unit you want to fread. Can anyone help me understand what I'm missing? Many thanks.
The first size parameter specifies the size of a single record. The second size parameter defines how many records you want to load. fread returns the number of records it loaded.
So if you have a structure which is 20 bytes, and you have a file where you have stored 5 of the records then you can pass it like this.
if(fread(ptr, 20, 5, strm) != 5)
printf("Unable to load 5 records\n");
Alternativaly you could load the same file like this:
if(fread(ptr, 1, 5*20, strm) != 5*20)
printf("Unable to load 5 records\n");
The effect is the same, but the first version is more readable, because usually you may read records not just "bytes". It's easier to understand in the context of your application logic. And of course you don't have to deal with calculating the number of bytes yourself, thus reducing a chance for errors.
The same applies to fwrite.
So in your above example I would rather write it like this:
// Your header is 44 bytes long (which is sizeof) but you want to read ONE header
if(fread(header, sizeof(header), 1, input) != 1)
... error reading 1 header ....
sizeof(uint8_t) is guaranteed to be 1 . Some people think it good style to use the sizeof expression instead of the number.
You can either write 44 "blocks" of size 1, or 1 block of size 44. In either case , you tried to write 44 bytes -- the writing part is the same either way.
The difference is in the return value, which reports how many blocks were successfully written. So if you use the 1, 44 order then it will tell you exactly how many bytes were written. If you use the 44, 1 order then you will either get 0 or 1 as the return value (and no way to know if it partially succeeded).
The same consideration applies to fread.
The FILE* input = fopen("input.wav", "r"); part is incorrect: this specifies to open the file in text mode, which may perform translations on the input, such as changing the line endings.
Instead, open in binary mode with "rb" mode string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With