@FileRead from a device issues...

#1
Here's the situation: I want to read one character at a time from a device (such as "CON:", and this is important, "COM1:"; and while "InKey" will (implicitly) work for CON:, it will only work for CON: as far as I can tell). And I would have thought that the following code would work:
Code:
@Echo Off
SetLocal
Set Handle=%@FileOpen[CON:,r,b]
Set Char=%@FileRead[%Handle,1]
Do While "%Char" != "**EOF**"
   @EchoS %Char
   Set Char=%@FileRead[%Handle,1]
EndDo
EndLocal
Quit 0
But I would have been wrong. The above "@FileRead" function "buffers" the input until a carriage return/line feed (which I found rather surprising because this true despite the fact that the console is being opened in "binary" mode where I thought that cr/lf sequences would be totally irrelevant) or end-of-file (Ctrl-Z on the console).

Here's a sample of what I mean (the above batch file has been modified slightly by adding a character counter and outputting every character on a single line preceded by the value of the counter):
Code:
  Sun  Feb 26, 2012  10:19:31p
TCC  13.03.46  Windows 7 [Version 6.1.7601]
Copyright 2012 JP Software Inc.  All Rights Reserved
Registered to Daniel Mathews
[Z:\]CD Demo
[Z:\Demo]Demo
abcdef
1: a
2: b
3: c
4: d
5: e
6: f
7:
8:
^Z
[Z:\Demo]
Now I have no way to test this on a com: port on this machine (i.e., I have nothing that can be plugged into the com: port that "outputs" data) to see if it works for "COM:" (but not "CON:"), but unless I can find a way to truly read a character at a time from a device I can't proceed further in what I was attempting to accomplish.

- Dan
 

rconn

Administrator
Staff member
May 14, 2008
10,532
94
#2
WAD. @FILEREAD calls the Windows ReadFile API, and if you're reading from CON:, Windows won't send anything to ReadFile until a line has been entered in the console keyboard buffer.

If you want to read / write individuals bytes from / to COMn:, you're going to need an external app (or a custom file system driver).
 
#3
Thanks, Rex, that is kind of what I expected (rhetorical question: Why a carriage return/line feed? After all, there's no guarantee that arbitrary binary data ("b" mode) will have those), so much so that I've been actually looking for a custom file system driver on the web (and I've found two so far, neither for Windows 7 which causes me to distrust them given how many low-level changes there appear to be in Windows 7 vs. Windows XP; and I really wasn't thinking in terms of external "apps", maybe that's something to look into (if I can figure exactly what to search for in Google, of course!)

- Dan
 
#4
WAD. @FILEREAD calls the Windows ReadFile API, and if you're reading from CON:, Windows won't send anything to ReadFile until a line has been entered in the console keyboard buffer.

If you want to read / write individuals bytes from / to COMn:, you're going to need an external app (or a custom file system driver).
How about @FILEREADB[handle,1] ? I created the small batch file here:

Code:
@echo off
setlocal
*on break goto END
*on error goto END
set hc=%@fileopen[CON:,read,binary]
do forever
  set cc=%@filereadb[%hc,1]
  echo %@fz4[%cc] %@char[%cc]``
enddo

:END
set dummy=%@fileclose[%hc]
where fz4=%@format[04,%1] (display numeric value in 4 columns, zero-padded on left].

I started the program in a stand-alone TCC 12.11.76 window (to match Dave's version). The results were surprising!


- each character I entered from the keyboard was instantly echoed at the end of the current line
- when I pressed "enter", the loop was executed, and each character, including the line terminating CR and LF, was displayed on a separate line.
I tried it again, with command-line ECHO turned OFF, with identical results.

I suspect that the original echo came from the keyboard driver (WinXP SP3) and @FILEREADB did not actually receive the individual characters until "enter" was pressed, and the behavior would be identical to @FILEREAD. The significance of opening the file as binary instead of text is only how individual bytes are delivered, not the buffering.

REX:
Some minor HELP issues.
- @FILEREADB and @FILEHANDLE are missing from the "See also" section of most of the filehandle-based commands
- @FILEHANDLE should have a warning that if the handle is not valid it reports an error (though most reports of this nature report the condition by a specific value)
 

rconn

Administrator
Staff member
May 14, 2008
10,532
94
#5
(rhetorical question: Why a carriage return/line feed? After all, there's no guarantee that arbitrary binary data ("b" mode) will have those)
Ask Microsoft -- they'll probably tell you that anything coming from CON: will always have a CR/LF (eventually).

The other character devices (like COMn:) are leftovers from DOS and are deprecated in Windows. So I wouldn't expect much help from Microsoft in that area.
 
#7
It also uses the Windows ReadFile() API, so you're going to have the same issue.
For console input, the INKEY command provides unbuffered access; using the /p and /x options suppresses instant echoing. Using the /Wn option allows terminating the loop on simple timeout - no more data. I am not sure how INKEY would work with redirected COM: input - no device available to test it.