1

I'm attempting to write a code which will read a file byte by byte, of any type/format. For starters I want to be able to read and write the same file, but I'm having trouble doing that for any file other than text files.

After searching here, I figured that fread/fwrite should work

unsigned char buff;
fopen_s(&input, "input_file_of_any_kind", "r");
fopen_s(&output, "new", "w");
while (!feof(input))
{
    fread(&buff, 1, 1, input);
    fwrite(&buff, 1, 1, output);
}
fclose(input);
fclose(output);

But when I'm trying to "copy" a jpg or pdf file, it reads only a few bytes (out of KB), so I guess my understanding here is flawed. Could you point me to the right direction? The point of that is to reach the representation of those bytes in bits and manipulate them (and it should work for a file of any size).

Null
  • 1,950
  • 9
  • 30
  • 33
Odor
  • 11
  • 1
  • 6
    `"r"` -> `"rb"`. On some systems reading a file in text-mode could do some translations that either remove or add bytes, or could mean a premature end-of-file. – Some programmer dude Mar 05 '21 at 09:20
  • 2
    Try `"rb"` and `"wb"` mode. – user253751 Mar 05 '21 at 09:20
  • 5
    Beyond that, you're going to get a lot closer to epsilon performance if you're really doing this byte at a time with [`getc`](https://en.cppreference.com/w/c/io/fgetc) and [`putc`](https://en.cppreference.com/w/c/io/fputc). And FYI, [`while (!feof(input))` is wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). You're going to end up with a duplicate final byte in your output file. It would/could be circumvented with the right control loop and/or actually validating your IO (which you should be doing anyway) rather than ignoring the function call results. – WhozCraig Mar 05 '21 at 09:47
  • Use fgetc and fputc. – stark Mar 05 '21 at 12:24
  • "it reads only a few bytes" --> Curious, how was that determined? – chux - Reinstate Monica Mar 05 '21 at 13:48
  • Slightly OT: reading and writing one byte at a time is probably might not be the most efficient way. – Jabberwocky Mar 05 '21 at 14:06
  • Note that `fopen_s()` is effectively Microsoft-only and therefore non-portable. And it doesn't actually make your code more secure. See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm Note that when MSVC says `fopen()` is "deprecated", it's pretty much lying to you - [`fopen()` is standard C](https://port70.net/~nsz/c/c11/n1570.html#7.21.5.3) and hasn't been and won't be deprecated. – Andrew Henle Mar 06 '21 at 13:11

1 Answers1

1

To read a file of any size (byte by byte) a simple approach uses fgetc().

Open the files in binary and check results.

// fopen_s(&input, "input_file_of_any_kind", "r");
if (fopen_s(&input, "input_file_of_any_kind", "rb")) {
  ; // Handle error
}

Do not use while (!feof(input)).

int ch;
while ((ch = fgetc(input)) != EOF) {
    fputc(ch, output);
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256