I've always used fgets
to read a file. However, I want to read a file that may have embedded \0
. I thought of using ftell
to query the size, but it doesn't seem to work on all files.
I've got a test file,
31 32 33 00 34 35 36 0A E2 82 AC 0D 0A 61
Here is my fgets
.
#include <stdlib.h> /* EXIT */
#include <stdio.h> /* printf perror fputc fread */
#include <string.h> /* strlen */
#include <errno.h> /* errno */
#include <assert.h> /* assert */
int main(void) {
char file[1000], *f = file, *a;
const int granularity = 80;
int is_done = 0;
for( ; ; ) {
/* Fail when contents bigger than the size;
would be a good spot to use realloc. */
if(granularity > sizeof file - (f - file))
{ errno = ERANGE; break; }
if(!fgets(f, granularity, stdin))
{ if(ferror(stdin)) break; is_done = 1; break; }
f += strlen(f);
}
for(a = file; a < f; a++) printf("%02hhX ", *a);
fputc('\n', stdout);
return is_done ? EXIT_SUCCESS : (perror("stdin"), EXIT_FAILURE);
}
Running this, (I'm on a UNIX-like machine,)
$ bin/fgets < test
31 32 33 E2 82 AC 0D 0A 61
Here is my fread
.
#include <stdlib.h> /* EXIT */
#include <stdio.h> /* printf perror fputc fread */
#include <errno.h> /* errno */
#include <assert.h> /* assert */
int main(void) {
char file[1000], *f = file, *a;
const int granularity = 80;
size_t read;
int is_done = 0;
for( ; ; ) {
if(granularity > sizeof file - (f - file))
{ errno = ERANGE; break; }
read = fread(f, 1, granularity, stdin);
if(ferror(stdin)) break;
assert(read >= 0 && read <= granularity);
f += read;
if(read != granularity) { is_done = 1; break; }
}
for(a = file; a < f; a++) printf("%02hhX ", *a);
fputc('\n', stdout);
return is_done ? EXIT_SUCCESS : (perror("stdin"), EXIT_FAILURE);
}
Running this,
$ bin/fread < test
31 32 33 00 34 35 36 0A E2 82 AC 0D 0A 61
I would like to know if this is pedantically correct and how I improve.
granularity
vs. just usingfread(fine, 1, sizeof file, stdin)
? \$\endgroup\$