1

I am trying to fix the code below to only read the first few N bytes. I would also like to do the same thing, but for the last number of N bytes (I assume that would involve just adding a '-' in front of the number of bytes N). I am not sure if using fget is the correct method for doing so.

I tried changing the 1000 in

while(fgets(buffer, 1000, fp)

however I do not think changing that value will pick up a certain number of bytes, as I have read that it is only a maximum value.

char buffer[1001];

int main(int argc, char** argv) {
  bzero(buffer, sizeof(buffer));
  for(int x=1; x<argc; x++) {
    FILE *fp = fopen(argv[x], "r+");
    if (fp) {
      while(fgets(buffer, 1000, fp)) {
        printf("%s", buffer);
      }
    } else {
      printf("could not open file %s\n", argv[x]);
    }
  }
} 
advan
  • 11
  • 1
  • 3
    *I assume that would involve just adding a '-' in front of the number of bytes N* That is **adorable** (but incorrect). [How do you determine the size of a file in C?](http://stackoverflow.com/questions/8236/how-do-you-determine-the-size-of-a-file-in-c) – Elliott Frisch Feb 01 '17 at 23:51
  • 2
    You probably need a suitable combination of [`fread()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fread.html), [`fwrite()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fwrite.html), and [`fseek()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html) – Jonathan Leffler Feb 01 '17 at 23:52
  • I tried using fread and fwrite but it will not compile. I do not understand exactly what i am doing wrong, but i think there is a problem with using buffer and file as arguments in fread and fwrite.while (fread(buffer, 1, number, file)) { fwrite(buffer, 1, number, file); printf("%s", buffer); } – advan Feb 02 '17 at 03:48

1 Answers1

0

Assuming that you want the first 1000 bytes and the last 1000 bytes of a file, and largely ignoring problems with files smaller than 2000 bytes (it works, but you might want a different result), you could use:

#include <stdio.h>

enum { NUM_BYTES = 1000 };

int main(int argc, char **argv)
{
    for (int x = 1; x < argc; x++)
    {
        FILE *fp = fopen(argv[x], "r");
        if (fp)
        {
            char buffer[NUM_BYTES];
            int nbytes = fread(buffer, 1, NUM_BYTES, fp);
            fwrite(buffer, 1, nbytes, stdout);
            if (fseek(fp, -NUM_BYTES, SEEK_END) == 0)
            {
                nbytes = fread(buffer, 1, NUM_BYTES, fp);
                fwrite(buffer, 1, nbytes, stdout);
            }
            fclose(fp);
        }
        else
        {
            fprintf(stderr, "%s: could not open file %s\n", argv[0], argv[x]);
        }
    }
}

This uses fread(), fwrite() and fseek() as suggested in the comments.

It also takes care to close successfully opened files. It does not demand write permissions on the files since it only reads and does not write those files (using "r" instead of "r+" in the call to fopen()).

If the file is smaller than 1000 bytes, the fseek() will fail because it tries to seek to a negative offset. If that happens, don't bother to read or write another 1000 bytes.

I debated whether to use sizeof(buffer) or NUM_BYTES in the function calls. I decided that NUM_BYTES was better, but the choice is not definitive — there are cogent arguments for using sizeof(buffer) instead.

Note that buffer becomes a local variable. There's no need to zero it; only the entries that are written on by fread() will be written by fwrite(), so there is no problem resolved by bzero(). (There doubly wasn't any point in that when the variable was global; variables with static duration are default initialized to all bytes zero anyway.)

The error message is written to standard error.

The code doesn't check for zero bytes read; arguably, it should.

If the NUM_BYTES becomes a parameter (e.g. you call your program fl19 and use fl19 -n 200 file1 to print the first and last 200 bytes of file1), then you need to do some tidying up as well as command-line argument handling.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278