How to peek at STDIN with Delphi 7?
In a Delphi 7 console application, how can I check whether stdin holds a character, without blocking until one i开发者_开发技巧s entered?
My plan is that this console program will be executed by a GUI program, and its stdin will be written to by the GUI program.
So I want my console app to periodically check stdin, but I can't find a way of doing this without blocking.
I have looked at this answer, which gets me a stream pointing to stdin, but there's still no way to "peek" as far as I can see.
I think you have already found the right way to read stdin. It is meant to block when there's nothing more to be read.
The standard way to handle this is to use a separate thread to handle the pipe. When it receives new data from stdin it signals this to the processing thread, for example with a message passing mechanism.
Having said all that, if you really want to poll you can call PeekNamedPipe to check if there is data in the pipe.
You could as the other answer says use threads, but even then you might have problems (using the threading method) unless you also investigate overlapped IO.
I normally use overlapped IO with serial ports rather than stdin, where "read a character if one is ready" is commonly needed, and where non-blocking IO is a usual way of working. You should be able to adapt the technique shown here. However, if I was writing an application that was keyboard driven (instead of purely driven by say, a file redirected to standard input) I would let go of StdIN, and use a CRT type unit. So, if you don't mind letting go of StdIn, and simply want to have a keyboard-driven input model, you could look at console based APIs and abandon the very limiting StdIn capabilities. For an example of a "kbhit" function that uses the Win32 Console APIs see here.
There is no other way (as far as i know), as reading from a pipe inside a separate thread. Otherwise as you already have seen, the readfile operation will block. I wrote an example how to do this, an example project is also available: redirect stdoutput
Edit: Well, reading your question another time, i understand that your problem lies within the console program, not the calling application. I wonder what your console application expects, normally a console application knows when it needs input and cannot proceede until the user enters this information. Do you need to check for an exit?
For a Stream if you .Read() the function result is the number of bytes read which will be zero if there was nothing there even if you asked for more. From the Delphi help for Classes.TStream.Read:
Read is used in cases where the number of bytes to read from the stream is not necessarily fixed. It attempts to read up to Count bytes into buffer and returns the number of bytes actually read.
精彩评论