0

I have a program that I want to use to read a file and output its last N characters (could be 50 or whatever that I have coded). From my piece of code, I get output that is question marks in diamond boxes,(unsupported unicode?)

I'm using lseek to set the cursor, could someone please assist me?

int main(int argc,char *argv[]){
    int fd; //file descriptor to hold open info
    int count=0; //to hold value of last 200th char number
    char ch; //holds read char
    char* outputString = "The file does not exist!\n";
    if(!access("myFile.txt",F_OK)==0){
        write(2,outputString,strlen(outputString));
        exit(1);
    }
    fd = open("myFile.txt",O_RDONLY| O_NONBLOCK);
    int ret = lseek(fd,200,SEEK_END); //get position of the last 200th item
    while (ret!=0) {
          write(1, &ch,1);
          ret--;
    }
    close(fd);
    return(0);
}

I don't want to use <stdio.h> functions so I'm using the file descriptors not making a FILE* object.

  • 2
    You mean you want `lseek(fd, -200, SEEK_END);`? `ch; //holds read char` - you never read anything from `fd`. – KamilCuk Aug 28 '19 at 09:52
  • Yeah. some help there please? New to c – JackPeters667 Aug 28 '19 at 09:53
  • SEEK_END seeks the file to the end _plus_ offset. So SEEK_END + 200 would seek 200 character past the end of file (makes no sense). Also check the return value of lseek, it return `-1` on failure. `int ret = lseek(...); if( ret == -1) { printf("A! error!"); abort(); }` – KamilCuk Aug 28 '19 at 09:55
  • okay, I get that, I checked the value of lseek, its giving me a positive integer 832. How to I position the offset to the last N characters of the file? – JackPeters667 Aug 28 '19 at 10:01
  • I'm thinking get total characters in the file then subtract N.. then set that as the offset value but that seems like it would use too much processing power, isnt there a more efficient function for this? – JackPeters667 Aug 28 '19 at 10:07
  • `get total characters in the file then subtract N` - that is great alternative. You do that with `lseek(fd, lseek(fd, 0, SEEK_END) - 200, SEEK_SET)`. But you can just seek to the end and _substract_ 200. `lseek(fd, -200, SEEK_END);` – KamilCuk Aug 28 '19 at 10:08

1 Answers1

0

I slightly modified your attempt. The lseek(fd, 200, SEEK_END) seeks the file 200 characters past the end of file. If you want to read last 200 character from a file, you need to seek to 200 character to end of file, ie lseek(fd, -200, SEEK_END).

I places some comments in code to help explaining.

// please include headers when posting questions on stackoverflow
// It makes it way easier to reproduce and play with the code from others
#include <unistd.h>
#include <error.h>
// I use glibc error(3) to handle errors
#include <errno.h>
#include <stdlib.h> 
#include <fcntl.h>

int main(int argc,char *argv[]){
    // no idea if a typo, myFile.txt != logfile.txt
    if(!access("myFile.txt", F_OK) == 0) {
        error(1, errno, "The file does not exist!");
        exit(1);
    }

    int fd = open("logfile.txt", O_RDONLY | O_NONBLOCK);
    if (fd == -1) { 
        error(1, errno, "Failed opening the file");
    }

    // move cursor position to the 200th characters from the end
    int ret = lseek(fd, -200, SEEK_END); 
    if (ret == -1) {
        error(1, errno, "Failed seeking the file");
    }

    // we break below
    while (1) { 
          char ch = 0; // holds read char
          ssize_t readed = read(fd, &ch, sizeof(ch));
          if (readed == 0) { 
              // end-of-file, break
              break;
          } else if (readed == -1) {
              // error handle
              // actually we could handle `readed != 1`
              error(1, errno, "Error reading from file");
          }
          // output the readed character on stdout
          // note that `STDOUT_FILENO` as more readable alternative to plain `1`
          write(STDOUT_FILENO, &ch, sizeof(ch));
    }

    close(fd);

    return 0;
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    Thank you Kamil, let me follow through and see what I was missing. Also going to try it with the other way for reading all files to calculate the offset just for practise – JackPeters667 Aug 28 '19 at 10:10