I'm trying to use fread()
to ascertain whether a file is a jpeg, my idea was to use fread()
to read the header of the file to make sure it's a jpeg, and then, if it is - copy the file. I understand that the standard jpeg header is 0xff 0xd8 0xff 0xe(0 to f)
, so I made a program to read the first four bytes of a file.
#include <stdio.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main (int argc, char *argv[])
{
FILE *in = fopen(argv[1], "rb");
FILE *out = fopen("output.jpg", "wb");
BYTE buffer [4096];
while (fread(buffer, 1, sizeof(buffer), in))
{
if ((buffer[0] == 0xff) & (buffer[1] == 0xd8) & (buffer[2] == 0xff) & ((buffer[3] & 0xf0) == 0xe0))
{
fwrite(buffer, 1, sizeof(buffer), out);
}
}
fclose(in);
fclose(out);
}
However, after running the program, when I try to open output.jpg
, I get the message: Invalid or Unsupported Image Format
.
I decided to double check that I was using fwrite()
correctly, by changing the paragraph to:
while (fread(buffer, 1, sizeof(buffer), in))
{
fwrite(buffer, 1, sizeof(buffer), out);
}
and in this case, output.jpg
does open correctly, which has led me to think that it is my attempt to use fread()
to check the file type that has caused the problem. Should I be using a different function, or am I just formatting something incorrectly?
There are two issues here.
Your program is reading up to 4KB at a time from the file in a loop, and you're checking the first 4 bytes of each 4KB block to see if it's a jpeg header before writing to the file. You only want to do this once on the initial read of the file. If it passes the check keep reading and writing in a loop, otherwise break out.
The other issue is that you're always writing sizeof(buffer)
bytes to the file. The fread
function might be reading less bytes than that, and if that's the case you'll be writing extra data you shouldn't. You need to capture the return value of fread
to know how much was read and then use that as the length to write in fwrite
.