java InputStreamReader / BufferedReader "read" behavior - java

A related question is this one: Where is the specification that defines this behavior for InputStreamReader?, but I'm not sure if it answers mine...
Please note, I'm just experimenting with the language.
I have this code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Capitalize {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(
System.in))) {
char c;
do {
c = Character.toUpperCase((char) br.read());
System.out.print(c);
} while (c != (char) -1);
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
Using ubuntu linux, I was expecting the output to be like this:
fFoOoO bBaArR
but instead, it's like this:
foo bar (line feed)
FOO BAR (waits for more characters or Ctrl + D)
Right now I'm not sure about what is the behavior in windows, probably it's different, but still, this confuses me a bit. Reading the documentation for the read method, I see it will only return -1 if the end of stream is reached. I kind of understand how that would work for reading a file, but how about, in this case, the console? Why does it have to wait until the Ctrl + D is typed? Is there any way to get to the end of the stream without having to type Ctrl + D? Is there a way to achieve what I was expecting?
Thanks in advance

As EJP comments, this is nothing to do with InputStream / BufferedReader. What you are seeing is the behaviour of the Linux "tty" input drivers and a typical console command.
What you are seeing is normal "line editing" or "line buffering". The input is only made available for Java to read (via the stdin file descriptor) when you press the <Enter> key. The output you are seeing prior to that is the character echoing from the "tty" drivers. (And notice that if you enter <Backspace> or whatever ... the characters get erased. When you type <Enter>, Java doesn't see the backspaces, etc. They have been edited out.)
Input via the java.io.Console class behaves the same way.
This is the same on Windows: the behaviour is portable. (This is a good thing ...)
If you want your Java application to see the characters as they are typed, when they are typed, you will need to use 3rd-party libraries (or native code) to implement this. (In Linux, it entails switching the tty driver into "raw" mode ... and this functionality is non-portable, and not supported by standard Java SE.)

Related

How to read input while the user is still typing in java? [duplicate]

Is there an easy way to read a single char from the console as the user is typing it in Java? Is it possible? I've tried with these methods but they all wait for the user to press enter key:
char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read(); // Java 6
I'm starting to think that System.in is not aware of the user input until enter is pressed.
What you want to do is put the console into "raw" mode (line editing bypassed and no enter key required) as opposed to "cooked" mode (line editing with enter key required.) On UNIX systems, the 'stty' command can change modes.
Now, with respect to Java... see Non blocking console input in Python and Java. Excerpt:
If your program must be console based,
you have to switch your terminal out
of line mode into character mode, and
remember to restore it before your
program quits. There is no portable
way to do this across operating
systems.
One of the suggestions is to use JNI. Again, that's not very portable. Another suggestion at the end of the thread, and in common with the post above, is to look at using jCurses.
You need to knock your console into raw mode. There is no built-in platform-independent way of getting there. jCurses might be interesting, though.
On a Unix system, this might work:
String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();
For example, if you want to take into account the time between keystrokes, here's sample code to get there.
I have written a Java class RawConsoleInput that uses JNA to call operating system functions of Windows and Unix/Linux.
On Windows it uses _kbhit() and _getwch() from msvcrt.dll.
On Unix it uses tcsetattr() to switch the console to non-canonical mode, System.in.available() to check whether data is available and System.in.read() to read bytes from the console. A CharsetDecoder is used to convert bytes to characters.
It supports non-blocking input and mixing raw mode and normal line mode input.
There is no portable way to read raw characters from a Java console.
Some platform-dependent workarounds have been presented above. But to be really portable, you'd have to abandon console mode and use a windowing mode, e.g. AWT or Swing.
Use jline3:
Example:
Terminal terminal = TerminalBuilder.builder()
.jna(true)
.system(true)
.build();
// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();
I' ve done it using jcurses...
import jcurses.system.InputChar;
import jcurses.system.Toolkit;
//(works best on the local machine when run through screen)
public class readchar3 {
public static void main (String[] args)
{
String st;
char ch;
int i;
st = "";
ch = ' ';
i = 0;
while (true)
{
InputChar c = Toolkit.readCharacter();
ch = c.getCharacter();
i = (int) ch;
System.out.print ("you typed " + ch + "(" + i + ")\n\r");
// break on '#'
if (ch == '#') break;
}
System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
}
}
See This
It calls _getch() function from c to read a single char without hitting Enter

How to implement keypress in java? [duplicate]

Is there an easy way to read a single char from the console as the user is typing it in Java? Is it possible? I've tried with these methods but they all wait for the user to press enter key:
char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read(); // Java 6
I'm starting to think that System.in is not aware of the user input until enter is pressed.
What you want to do is put the console into "raw" mode (line editing bypassed and no enter key required) as opposed to "cooked" mode (line editing with enter key required.) On UNIX systems, the 'stty' command can change modes.
Now, with respect to Java... see Non blocking console input in Python and Java. Excerpt:
If your program must be console based,
you have to switch your terminal out
of line mode into character mode, and
remember to restore it before your
program quits. There is no portable
way to do this across operating
systems.
One of the suggestions is to use JNI. Again, that's not very portable. Another suggestion at the end of the thread, and in common with the post above, is to look at using jCurses.
You need to knock your console into raw mode. There is no built-in platform-independent way of getting there. jCurses might be interesting, though.
On a Unix system, this might work:
String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();
For example, if you want to take into account the time between keystrokes, here's sample code to get there.
I have written a Java class RawConsoleInput that uses JNA to call operating system functions of Windows and Unix/Linux.
On Windows it uses _kbhit() and _getwch() from msvcrt.dll.
On Unix it uses tcsetattr() to switch the console to non-canonical mode, System.in.available() to check whether data is available and System.in.read() to read bytes from the console. A CharsetDecoder is used to convert bytes to characters.
It supports non-blocking input and mixing raw mode and normal line mode input.
There is no portable way to read raw characters from a Java console.
Some platform-dependent workarounds have been presented above. But to be really portable, you'd have to abandon console mode and use a windowing mode, e.g. AWT or Swing.
Use jline3:
Example:
Terminal terminal = TerminalBuilder.builder()
.jna(true)
.system(true)
.build();
// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();
I' ve done it using jcurses...
import jcurses.system.InputChar;
import jcurses.system.Toolkit;
//(works best on the local machine when run through screen)
public class readchar3 {
public static void main (String[] args)
{
String st;
char ch;
int i;
st = "";
ch = ' ';
i = 0;
while (true)
{
InputChar c = Toolkit.readCharacter();
ch = c.getCharacter();
i = (int) ch;
System.out.print ("you typed " + ch + "(" + i + ")\n\r");
// break on '#'
if (ch == '#') break;
}
System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
}
}
See This
It calls _getch() function from c to read a single char without hitting Enter

Taking input without using "ENTER" key [duplicate]

Is there an easy way to read a single char from the console as the user is typing it in Java? Is it possible? I've tried with these methods but they all wait for the user to press enter key:
char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read(); // Java 6
I'm starting to think that System.in is not aware of the user input until enter is pressed.
What you want to do is put the console into "raw" mode (line editing bypassed and no enter key required) as opposed to "cooked" mode (line editing with enter key required.) On UNIX systems, the 'stty' command can change modes.
Now, with respect to Java... see Non blocking console input in Python and Java. Excerpt:
If your program must be console based,
you have to switch your terminal out
of line mode into character mode, and
remember to restore it before your
program quits. There is no portable
way to do this across operating
systems.
One of the suggestions is to use JNI. Again, that's not very portable. Another suggestion at the end of the thread, and in common with the post above, is to look at using jCurses.
You need to knock your console into raw mode. There is no built-in platform-independent way of getting there. jCurses might be interesting, though.
On a Unix system, this might work:
String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();
For example, if you want to take into account the time between keystrokes, here's sample code to get there.
I have written a Java class RawConsoleInput that uses JNA to call operating system functions of Windows and Unix/Linux.
On Windows it uses _kbhit() and _getwch() from msvcrt.dll.
On Unix it uses tcsetattr() to switch the console to non-canonical mode, System.in.available() to check whether data is available and System.in.read() to read bytes from the console. A CharsetDecoder is used to convert bytes to characters.
It supports non-blocking input and mixing raw mode and normal line mode input.
There is no portable way to read raw characters from a Java console.
Some platform-dependent workarounds have been presented above. But to be really portable, you'd have to abandon console mode and use a windowing mode, e.g. AWT or Swing.
Use jline3:
Example:
Terminal terminal = TerminalBuilder.builder()
.jna(true)
.system(true)
.build();
// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();
I' ve done it using jcurses...
import jcurses.system.InputChar;
import jcurses.system.Toolkit;
//(works best on the local machine when run through screen)
public class readchar3 {
public static void main (String[] args)
{
String st;
char ch;
int i;
st = "";
ch = ' ';
i = 0;
while (true)
{
InputChar c = Toolkit.readCharacter();
ch = c.getCharacter();
i = (int) ch;
System.out.print ("you typed " + ch + "(" + i + ")\n\r");
// break on '#'
if (ch == '#') break;
}
System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
}
}
See This
It calls _getch() function from c to read a single char without hitting Enter

Indicate new line into console input, without pressing enter key? [duplicate]

Is there an easy way to read a single char from the console as the user is typing it in Java? Is it possible? I've tried with these methods but they all wait for the user to press enter key:
char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read(); // Java 6
I'm starting to think that System.in is not aware of the user input until enter is pressed.
What you want to do is put the console into "raw" mode (line editing bypassed and no enter key required) as opposed to "cooked" mode (line editing with enter key required.) On UNIX systems, the 'stty' command can change modes.
Now, with respect to Java... see Non blocking console input in Python and Java. Excerpt:
If your program must be console based,
you have to switch your terminal out
of line mode into character mode, and
remember to restore it before your
program quits. There is no portable
way to do this across operating
systems.
One of the suggestions is to use JNI. Again, that's not very portable. Another suggestion at the end of the thread, and in common with the post above, is to look at using jCurses.
You need to knock your console into raw mode. There is no built-in platform-independent way of getting there. jCurses might be interesting, though.
On a Unix system, this might work:
String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();
For example, if you want to take into account the time between keystrokes, here's sample code to get there.
I have written a Java class RawConsoleInput that uses JNA to call operating system functions of Windows and Unix/Linux.
On Windows it uses _kbhit() and _getwch() from msvcrt.dll.
On Unix it uses tcsetattr() to switch the console to non-canonical mode, System.in.available() to check whether data is available and System.in.read() to read bytes from the console. A CharsetDecoder is used to convert bytes to characters.
It supports non-blocking input and mixing raw mode and normal line mode input.
There is no portable way to read raw characters from a Java console.
Some platform-dependent workarounds have been presented above. But to be really portable, you'd have to abandon console mode and use a windowing mode, e.g. AWT or Swing.
Use jline3:
Example:
Terminal terminal = TerminalBuilder.builder()
.jna(true)
.system(true)
.build();
// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();
I' ve done it using jcurses...
import jcurses.system.InputChar;
import jcurses.system.Toolkit;
//(works best on the local machine when run through screen)
public class readchar3 {
public static void main (String[] args)
{
String st;
char ch;
int i;
st = "";
ch = ' ';
i = 0;
while (true)
{
InputChar c = Toolkit.readCharacter();
ch = c.getCharacter();
i = (int) ch;
System.out.print ("you typed " + ch + "(" + i + ")\n\r");
// break on '#'
if (ch == '#') break;
}
System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
}
}
See This
It calls _getch() function from c to read a single char without hitting Enter

How to resolve? java console application:System.in.readLine issue:User can not see what he is typing

I am writing a simple java console application where program will prompt the user to type something in and then the program control will wait for the user input and do something with that input.
Issue is : while typing on the console , the user can not see what he is typing. What should I do differently so the user can see what he is typing?(user can see what he has typed after he hits 'enter').
I created a java standalone project and built and ran the project using netbean's ant command from command line:
ant run
Below is the whole code that I have.OS is Windows 7. jdk version: 1.6
Below is the code I am using to get user-input from console.
import java.io.*;
public class StatLibraryTest {
public static void main(String[] args) {
String CurLine = ""; // Line read from standard in
try{
while (!(CurLine.equals("quit"))){
System.out.println("Enter: " );
CurLine = readLine();
if (!(CurLine.equals("quit"))){
System.out.println("You typed: " + CurLine);
}
}
}catch(Exception e){
System.out.println(e.getMessage());
}
}
public static String readLine()
{
String s = "";
try {
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
s = in.readLine();
} catch (Exception e) {
System.out.println("Error! Exception: "+e);
}
return s;
}
}
Character echoing is normal taken care of by the operating system's terminal driver or (in modern systems) the terminal emulator. It happens independently of Java ... or whatever else the application is written in ... unless the application has turned character echoing off or something.
So ...
We need you to explain how you've run the application that is causing the console connected to System.in to get into "no echo" mode.
I don't know if this is the cause of your problem, but your readLine method is incorrect. Each time you call readLine it creates a new InputStreamReader and BufferedReader for System.in. This is inefficient. But worse than that, it is liable to lose input. You see, when in.readLine() is called, the input stack will make a read call on System.in to read all input that is currently available. If more than one line is available (because the user has typed ahead ... or because the application has been called with standard input redirected from a file), you can end up with multiple lines in the BufferedReader's buffer. The readLine() call returns the first line ... but the rest get thrown away.
There is also a bug in the way that you handle EOF. The in.readLine call will return a null when it sees EOF, but you are not dealing with it.
I suspect that the reason you are not getting echoing is something to do with the way you are running the program ... using Ant. Try running your program directly from the command line instead; i.e. run java StatLibraryTest.
Finally, there are some style problems with your code:
You've got an identifier (CurrLine) which violates the Java identifier name rules.
The indentation is inconsistent
Your use of embedded whitespace is inconsistent
Catching Exception is generally a bad idea. Catch the specific exceptions that you are expecting (e.g. IOException).
It is better to let an exception propagate if your code cannot do something sensible with it. Specifically, if readLine catches an exception, the caller will get an empty String. It can't distinguish that from valid input; e.g. the user entering an empty line. You should declare readLine as throws IOException.

Categories

Resources