Empty or "flush" a file descriptor without read()?
(Note: This is not a question of how to flush a write()
. This is the other end of it, so to speak.)
Is it possible to empty a file descriptor that has data to be read in it without having to read()
it? You might not be interested in the data, and reading it all would therefore waste space and cycles you might have better uses for.
If it is not possible in POSIX, do any operating systems have any non-portable ways to do this?
UPDATE: Please note that I'm talking about fil开发者_开发问答e descriptors, not streams.
If you're dealing with a tty, have a look at tcflush()
:
#include <termios.h>
int tcflush(int fildes, int queue_selector);
Upon successful completion, tcflush() discards data written to the object referred to by fildes (an open file descriptor associated with a terminal) but not transmitted, or data received but not read, depending on the value of queue_selector [...]
http://opengroup.org/onlinepubs/007908775/xsh/tcflush.html
For POSIX, use lseek(2)
or lseek64(3)
to seek ahead. For Windows, use SetFilePointer()
or SetFilePointerEx()
.
If you know the number of bytes to skip, you can do lseek(fd, n, SEEK_CUR);
for POSIX systems. There is fseek()
as well, for FILE *
objects. In POSIX, I think you can safely seek past the end of file, the idea is that if more data is written later, so as to make data go past the position set with lseek()
, you will be able to read more data now.
Linux 2.6.17 or later with the GNU C library version 2.5 or later contain the splice()
system call, which can be used to send data from one file descriptor to another without copying it to user space. This can be used to discard data by simply opening /dev/null
and splice
ing data from the source file descriptor into the /dev/null
file descriptor.
Streams have fclean available, which flushes the write buffer, and returns the read buffer back to the IO system.
http://www.gnu.org/software/hello/manual/libc/Cleaning-Streams.html
If what you really want to do is skip bytes, repositioning the file pointer is the correct action. Just skip ahead as many bytes as you don't want to read.
http://www.gnu.org/software/hello/manual/libc/File-Position-Primitive.html#File-Position-Primitive
Neither read() nor flush() are part of Standard C or C++, but certainly none of the standard functions support flushing of input streams. I would guess this reflects something not available in the underlying operating systems. The normal way to avoid reading something altogether is to skip over it with a seek() function of some sort.
According to this, a POSIX system will do this on fflush(stream);
.
For a stream open for reading, if the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be adjusted so that the next operation on the open file description deals with the byte after the last one read from or written to the stream being flushed.
BSD introduced fpurge()
, Solaris and glibc introduced __fpurge()
.
From the man page:
#include <stdio.h>
#include <stdio_ext.h>
void __fpurge(FILE *stream);
The function __fpurge() clears the buffers of the given stream. For output streams this discards any unwritten output. For input streams this discards any input read from the underlying object but not yet obtained via getc(3); this includes any text pushed back via ungetc(3).
The function __fpurge() does precisely the same, but without returning a value.
Note, however:
These functions are nonstandard and not portable. The function fpurge() was introduced in 4.4BSD and is not available under Linux. The function __fpurge() was introduced in Solaris, and is present in glibc 2.1.95 and later.
If you're working with a file descriptor, you might be able to get a FILE*
from the descriptor first.
int fd;
/* ... */
FILE* fp = fdopen(fd, "r");
/* ... */
__fpurge(fp);
精彩评论