views:

499

answers:

6

(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 file descriptors, not streams.

+1  A: 

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

jdmichal
fclean is certainly not standard from the language point of view
anon
Correct. It is part of GNU libc. I'm pretty sure that that's available in just about every OS. I updated the links to the GNU manual, instead of the mirror.
jdmichal
The prevailing answer seems to be "lseek". I'll accept your answer since you were the first to suggest it. I was hoping for something which would work on pipes, FIFOs, etc, which is why I waited, but I guess no such thing exists.
Teddy
`lseek` is the best solution for actual files, but certain file descriptors are non-seekable (e.g. pipes and fifos), so doing an `lseek` will fail. If you want the most general solution that works with all types of file descriptors, you really do need to read it into a temp buffer and discard it. For optimal performance, use a reasonably large buffer, but not so large that you blow your L1 or L2 cache.
Adam Rosenfield
Ah, I see. I agree with Adam's comment, that if `lseek` does not work, then really the only recourse is to read and discard the data.
jdmichal
+1  A: 

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.

anon
A: 

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.

Chinmay Kanchi
This governs (a) synchronizing read and write positions when interleaving buffered IO on a single file, and (b) undoing the effects of a read buffer that has proceeded ahead of what has been requested. Not what OP requests.
ephemient
That's for streams, not file descriptors.
Teddy
+1  A: 

For POSIX, use lseek(2) or lseek64(3) to seek ahead. For Windows, use SetFilePointer() or SetFilePointerEx().

Adam Rosenfield
A: 

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.

Alok
+1  A: 

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

squelart