Using fseek with a file pointer that points to stdin
Depending on command-line arguments, I'm setting a file pointer to point either towards a specified file or stdin (for the purpose of piping). I then pass this pointer around to a number of different functions to read from the file. Here is the function for getting the file pointer:
FILE *getFile(int argc, char *argv[]) {
FILE *myFile = NULL;
if (argc == 2) {
myFile = fopen(argv[1], "r");
if (myFile == NULL)
fprintf开发者_StackOverflow社区(stderr, "File \"%s\" not found\n", argv[1]);
}
else
myFile = stdin;
return myFile;
}
When it's pointing to stdin, fseek
does not seem to work. By that, I mean I use it and then use fgetc
and I get unexpected results. Is this expected behavior, and if so, how do I move to different locations in the stream?
For example:
int main(int argc, char *argv[]) {
FILE *myFile = getFile(argc, argv); // assume pointer is set to stdin
int x = fgetc(myFile); // expected result
int y = fgetc(myFile); // expected result
int z = fgetc(myFile); // expected result
int foo = bar(myFile); // unexpected result
return 0;
}
int bar(FILE *myFile) {
fseek(myFile, 4, 0);
return fgetc(myFile);
}
Yes, it's perfectly normal that fseek
won't work on stdin
-- it'll normally only work on a disk file, or something reasonably similar.
Though it's really a POSIX thing, you can typically use if (isatty(fileno(myFile)))
to get at least a pretty good idea of whether seeking will work in a particular file. In some cases, isatty
and/or fileno
will have a leading underscore (e.g., IIRC the versions provided with Microsoft's compilers do).
Fseek() is based on lseek(), and the lseek man page discusses possible errors, including:
[ESPIPE] Fildes is associated with a pipe, socket, or FIFO.
If stdin is connected to a pseudo tty, I believe it will have socket behavior.
Here is the relevant entry in the ANSI standard concerning the fseek
function:
For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_SET
So, possible but with some limitations
精彩评论