What is the difference between this lseek, fseek, read, fread?

I call these functions:

unsigned blah[5]; lseek(0, 100, SEEK_CUR); read(0, blah, sizeof(blah)); 

and

 FILE *fr; fr = fopen(arg[1], "r"); unsigned blah[5]; fseek(fr, 100, SEEK_CUR); fread(blah, 1, sizeof(blah), fr); 

And I run the first code that runs this command:

 cat TEXTFILE | ./a.out 

I run the second code that runs this command:

 ./a.out TEXTFILE 

However, I get different results. While the first one searched correctly, therefore, he reads the correct text, the second one does not. I want to use the second format, so what did I do wrong?

+4
source share
3 answers

With the addition of a call open(filename,O_RDONLY); for the first example, both worked great for me. I suspect your problem is caused by calling lseek(0, 100, SEEK_CUR); which requests a search on standard input. You cannot always look for a standard value - if you have:

  cat file | ./my_program 

Then standard input is fifo, and you cannot search. If I do this on my system, try to crash by returning -1 with the "Illegal Search" error. This may be the problem you are facing, and you may not notice, because you are not checking the return value of the search query in your example.

Please note that if you have:

  ./my_program < file 

Then standard input is a file, and you can search for it. On my system, the search returns 100 , and the output is correct.


Here is a program that you can use to illustrate the return values:

 int main(void){ int fd = 0; char blah[5]; printf("Seek moved to this position: %d\n",lseek(fd, 100, SEEK_CUR)); perror("Seek said"); printf("Then read read %d bytes\n",read(fd, blah, sizeof(blah))); printf("The bytes read were '%c%c%c%c%c'\n",blah[0],blah[1],blah[2],blah[3],blah[4]); } 

And here are two performances:

  $ ./a.out < text Seek moved to this position: 100 Seek said: Success Then read read 5 bytes The bytes read were '+++.-' 

(These are valid bytes from position 100 in this file)

 $ cat text | ./a.out Seek moved to this position: -1 Seek said: Illegal seek Then read read 5 bytes The bytes read were '# def' 

(These bytes are the first 5 bytes of the file)


I also noticed that the standard input version was the one you said worked correctly. If you are having problems with the FILE * version, I suspect that the fopen() call does not work, so make sure you specify the return value from fopen() . Of course, you can always do this:

 FILE *fr = stdin; 

So you are reading the standard version. However, since you cannot always search for the standard version, I would recommend always opening the file if you plan to search.

Please note that you cannot search on all devices on which you can open files (although you will not have problems on most systems), so you should always check that the result is seek() to make sure that it succeeded.

+5
source

I'm not 100% sure about the difference, but it seems to be related to pipe vs stdio / file. To illustrate this, I made these two different test programs:

exam.c

 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { char blah[5] = {0,}; /* we're using stdin instead of pipeline :( */ lseek(0, 100, SEEK_CUR); read(0, blah, sizeof(blah)); printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]); return 0; } 

test.c

 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> void testA(const char *s) { int f = -1; char blah[5] = {0,}; f = open(s, O_RDONLY); if (-1 < f) { lseek(f, 100, SEEK_CUR); read(f, blah, sizeof(blah)); } printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]); } void testB(const char *s) { FILE *fp = NULL; char blah[5] = {0,}; fp = fopen(s, "r"); if (fp) { fseek(fp, 100, SEEK_CUR); fread(blah, 1, sizeof(blah), fp); } printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]); } int main(int argc, char **argv) { testA(argv[1]); testB(argv[1]); return 0; } 

Then I created some test data.

data.txt

 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 

When I executed cat ./data.txt | ./exam cat ./data.txt | ./exam output

 01234 

When I executed ./test ./data.txt , I got

 bcdef bcdef 

Just FYI, the results remain unchanged even if we replace SEEK_CUR with SEEK_SET .

However ./exam <./data.txt leads to

 bcdef 

which is legal.

I know this is not an acceptable answer, not knowing why "0" causes the contents of the data file, but I hope this helps in some way.

+2
source

SEEK_CUR starts at the current position. This is why your first search works when you are at the beginning of the file. To always search from the start, you need to use SEEK_SET instead of SEEK_CUR.

 0 SEEK_SET The beginning of the file 1 SEEK_CUR The current position 2 SEEK_END The end of the file 
+2
source

Source: https://habr.com/ru/post/1391357/


All Articles