Re: Slightly OT: non-buffered stdin in Java

From: Greg Lewis <glewis_at_eyesbeyond.com>
Date: Sat, 10 Jun 2023 05:38:52 UTC
On 6/8/23 8:35 PM, Aryeh Friedman wrote:

> On Thu, Jun 8, 2023 at 11:23 PM Paul Procacci <pprocacci@gmail.com> wrote:
>>
>>
>> On Thu, Jun 8, 2023 at 10:55 PM Aryeh Friedman <aryeh.friedman@gmail.com> wrote:
>>> On Thu, Jun 8, 2023 at 10:32 PM Paul Procacci <pprocacci@gmail.com> wrote:
>>>>
>>>>
>>>> On Thu, Jun 8, 2023 at 9:22 PM Aryeh Friedman <aryeh.friedman@gmail.com> wrote:
>>>>> On Thu, Jun 8, 2023 at 6:37 PM Dr. Nikolaus Klepp <dr.klepp@gmx.at> wrote:
>>>>>> Anno domini 2023 Thu, 8 Jun 17:22:38 -0400
>>>>>>   Aryeh Friedman scripsit:
>>>>>>> On Thu, Jun 8, 2023 at 2:39 PM Dr. Nikolaus Klepp <dr.klepp@gmx.at> wrote:
>>>>>>>> Anno domini 2023 Thu, 8 Jun 14:01:19 -0400
>>>>>>>>   Aryeh Friedman scripsit:
>>>>>>>>> Under Java stdin (System.in) is a buffered stream not sent to the
>>>>>>>>> application until return is pressed.  But, Java can read from
>>>>>>>>> files/sockets and other generic InputStreams unbuffered.   So I was
>>>>>>>>> wondering if there is a command that will make stdin go to a file so
>>>>>>>>> that Java can open that file and read it unbuffered?
>>>>>>>>>
>>>>>>>>> I know I can do something like cat ->file but that makes it hard to
>>>>>>>>> sync stdout and stderr (both are unbuffered in Java) with the file
>>>>>>>>> version of stdin
>>>>>>>>>
>>>>>>>> "stdbuf" might be what you look for:
>>>>>>>>
>>>>>>>> https://man.freebsd.org/cgi/man.cgi?query=stdbuf
>>>>>>> Will likely need to play with it more but stdbuf -i 0 -o 0 cat -|cat
>>>>>>> didn't produce the expected immediate echo I still had to hit return
>>>>>>>
>>>>>> Your console is linebuffered, so "cat" receives lines. IIRC "cat" disables linebuffer on input by itself, so you should use someting else for testing.
>>>>>>
>>>>>> Nik
>>>>>>
>>>>> I am pretty convinced by the following test it is not working as advertised:
>>>>>
>>>>> aryehl@neomarx:~/Desktop % cat foo.c
>>>>> #include <stdio.h>
>>>>> #include <fcntl.h>
>>>>> #include <unistd.h>
>>>>>
>>>>> int main()
>>>>> {
>>>>>      int in=fcntl(STDIN_FILENO, F_DUPFD, 0);
>>>>>      int out=fcntl(STDOUT_FILENO, F_DUPFD, 0);
>>>>>      char c=0;
>>>>>
>>>>>      do {
>>>>>          read(in,&c,1);
>>>>>          write(out,&c,1);
>>>>>      } while(c!=EOF);
>>>>> }
>>>>> aryehl@neomarx:~/Desktop % !cc
>>>>> cc foo.c
>>>>> aryehl@neomarx:~/Desktop % stdbuf -i 0 -o 0 ./a.out
>>>>> this is not echoing!
>>>>> this is not echoing!
>>>>> neither is this
>>>>> neither is this
>>>>> ^C
>>>>> aryehl@neomarx:~/Desktop %
>>>>>
>>>>> --
>>>>> Aryeh M. Friedman, Lead Developer, http://www.PetiteCloud.org
>>>>>
>>>> stdbuf only works for stdio buffering of which read(2) and write(2) aren't.
>>> I also tried it with System.in.read() in Java and it was also buffered
>>> but according to the openjdk source it appears that this is on
>>> purpose.
>>>
>>>
>>>
>>> --
>>> Aryeh M. Friedman, Lead Developer, http://www.PetiteCloud.org
>>
>>
>> When you just `./a.out` you're being bitten by the tty.
>> You can manipulate that terminal to do what you want.  Start reading termios(4).
>>
>> Without a tty you will only get a character at a time with the following:
>>
>> #include <unistd.h>
>>
>> int main(int argc, char **argv)
>> {
>>    char ch;
>>    for(;;){
>>      ssize_t r = read(0,&ch,1);
>>      if(!r) break;
>>      write(1, &ch, 1);
>>    }
>>    _exit(0);
>> }
> Please see the whole context the goal is to make it so I can type at
> the command line into a java program and have instantaneous
> presentation of any characters I enter to Java
>
If you want to type at the command line while running a Java program and 
have it be able to see each character at a time then maybe what you want 
is java.io.Console

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Console.html

You can then get a Reader from the console and call read() on that to 
read a single character.

-- Greg