How to Read a File in Reverse With Fgets

Member Avatar

Read information technology forward, store information technology in a reversible container, and and so walk through the container backward. Or if you know the verbal length of each line, you could open up the file as binary and use fseek with read to get the lines in reverse. Or you could physically contrary the file before reading it. Or y'all could utilise recursion, but that'south an exceptionally poor solution. ;)

Member Avatar

>what container would you suggest?
A linked list since you might non know how many lines are in the file.

>is information technology possible to use some kind of strtok merely backwards?
No, the play tricks hither is that you have to get the lines from the file into memory before you can practice anything with them. So your problem boils downward to either reading the entire file into retentivity, or using tricky seeking to actually read the file from end to beginning.

Member Avatar

>reading it line by line frontward costs likewise much...
And reading information technology line by line astern doesn't? :icon_rolleyes: Regardless of your solution, you've got the penalization of reading the file. Unless it'southward a random access file (unlikely), that involves sequential front-to-back access. Oh, and accept you tried whatsoever of the suggestions and proven that they all cost too much? I'grand willing to bet that you haven't.

Member Avatar

Consider calling stat() to become the filesize start. Open the file, so motion the file arrow forward to some arbitrary place.

If you assume no last line is always longer than say, 200 characters,
then fseek() to within 200 character size units of the stop of the file.
fread in the last scrap of the file into a buffer.

Now yous tin can use what Narue indicated - you have a container that yous can "backwards read" from to go the concluding line of the file. If you lot demand the terminal 10 lines, so adjust the file pointer positioning scheme.

If you want to run across a generalized algorithm for this, consult the coreutils source for the "tail" utility at
www.gnu.org

Member Avatar

one. Open up the file for read, call fseek() to seek to the finish of the file, and so phone call ftell() to get the length of the file. Alternatively yous tin get the file length by calling stat() or fstat().

ii. Allocate a buffer pointer to the file size obtained in #1, in a higher place.

3. Read the entire file into that buffer -- y'all can probably use fread() to read the file all in one shot (assuming the file is minor enough).

4. Use another char pointer to transverse the file from end to beginning of the buffer. Something like this example

              char *ptr = 0; char *iobuf = malloc( fileSize ); fread(iobuf,fileSize,fp); for(ptr = iobuf; ptr >= iobuf; ptr--) {     // do something with the graphic symbol at *ptr } free(iobuf);            

Note the above code snipped does not comprise any mistake checking, which y'all should add together in your programme.

Member Avatar

line 44 should accept read < filesize because it is reading filesize bytes.

>>But tin y'all tell me if in the for loop I should exist reading each char in ptr into a new target array that should so be passed to an fwrite function for streaming to the target file

No you don't have to create another array. In the for loop I posted just use fputc() to write out each character one at a fourth dimension. The operating system will buffer them up and optimize the write to deejay.

Member Avatar

You lot are using the fread function incorrectly by swapping the position of the second and third parameter. The 2d parameter is not the size of the unabridged file, but the size of each chunk.

Try changing to fread(iobuf, nblocks, filesize, in) and it should piece of work out to be fine.

Member Avatar

Y'all are using the fread function incorrectly past swapping the position of the 2nd and third parameter. The second parameter is not the size of the entire file, just the size of each clamper.

Try changing to fread(iobuf, nblocks, filesize, in) and information technology should work out to be fine.

I don't remember information technology makes any deviation -- I ordinarily do information technology the way the OP posted and have never had a problem. Merely, equally Narue will probably say, in general it may not be safe to do that.

echobase: post your electric current program and attach a copy of the file y'all are working with.

Member Avatar

              #include <stdio.h> #include <stdlib.h>  int main(int argc, char *argv[]) {     size_t filesize;     size_t nblocks = 1;     FILE *in, *out;      /* check no. of arguments */     if (argc != three) {         fprintf(stderr, "%s: incorrect arguments\n",             argv[0]);         return 1;     }      /* open up the input file */     if ((in = fopen(argv[one], "rb")) == Nada) {         fprintf(stderr, "%due south: can't open up %due south\north",                 argv[0], argv[1]);         get out(1);     }      /* open up the target file */     if ((out = fopen(argv[2], "wb")) == Nix) {         fprintf(stderr, "%south: can't open up %s\n",                 argv[0], argv[2]);         exit(1);     }      /* move arrow to finish of input file */     if(fseek(in, 0L, SEEK_END) != 0) {         perror("fseek(in, 0L, SEEK_END");         exit(1);     }      /* become current file position in input file*/     nblocks = ftell(in);     rewind(in);      char *ptr = 0;     char *iobuf = (char*)malloc(sizeof(char) * nblocks);      /* read input file into buffer */      if(fread(iobuf, 1, nblocks, in) != nblocks){         fprintf(stderr, "fread failed\n");         exit(1);     }       fclose(in);     fwrite(iobuf, i, nblocks, out);     /*     for(ptr = iobuf; ptr <= iobuf; ptr++)     {         fputc(*ptr, out);     }     */     free(iobuf);     fclose(out);      go out(0); }            

Member Avatar

Hey you lot guys-

The programme as information technology stands now is basically the version ~southward.o.south~ simply posted. The fread office now works beautifully,but there is no mechanism to reverse the text. (The statement in the for loop at line 55 was my unsuccesful endeavor to do but that.) The program in its present land merely copies the input file to the target file from outset to finish. The fwrite function doesn't appear to exist sophisticated plenty to write the buffer in opposite, then don't you recollect I'll have to reverse the buffer somehow myself in between fread and fwrite? This goes back to my original idea of creating a new target char array for that purpose. So actually the question is, how exercise I opposite iobuf? Correct? I have fastened a re-create of the input text file I've been using.

echobase

Member Avatar

No need of another buffer, a unproblematic swap should exercise the play tricks.

              int i, j;     char ch;     for(i = 0, j = nblocks - 1; i <= j; ++i, --j)     {         ch = iobuf[i];         iobuf[i] = iobuf[j];         iobuf[j] = ch;     }     fwrite(iobuf, 1, nblocks, out);            

Member Avatar

It works! ! Thank you very much to ~south.o.s~ and Ancient Dragon.

sanchezsuired.blogspot.com

Source: https://www.daniweb.com/programming/software-development/threads/78403/how-to-read-a-text-file-backwards

0 Response to "How to Read a File in Reverse With Fgets"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel