Reputation: 125
Why CTRL + M gives an ASCII value of 10 (decimal value). It should actually give 13. I am connecting to Amazon EC2 linux instance through putty. I execute the below program
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
public class NumbersConsole {
private static String ttyConfig;
public static void main(String[] args) {
try {
setTerminalToCBreak();
int i=0;
while (true) {
//System.out.println( ""+ i++ );
if ( System.in.available() != 0 ) {
int c = System.in.read();
System.out.println(c);
if ( c == 13 ) {
break;
}
}
} // end while
}
catch (IOException e) {
System.err.println("IOException");
}
catch (InterruptedException e) {
System.err.println("InterruptedException");
}
finally {
try {
stty( ttyConfig.trim() );
}
catch (Exception e) {
System.err.println("Exception restoring tty config");
}
}
}
private static void setTerminalToCBreak() throws IOException, InterruptedException {
ttyConfig = stty("-g");
// set the console to be character-buffered instead of line-buffered
stty("-icanon min 1");
// disable character echoing
stty("-echo");
}
/**
* Execute the stty command with the specified arguments
* against the current active terminal.
*/
private static String stty(final String args)
throws IOException, InterruptedException {
String cmd = "stty " + args + " < /dev/tty";
return exec(new String[] {
"sh",
"-c",
cmd
});
}
/**
* Execute the specified command and return the output
* (both stdout and stderr).
*/
private static String exec(final String[] cmd)
throws IOException, InterruptedException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Process p = Runtime.getRuntime().exec(cmd);
int c;
InputStream in = p.getInputStream();
while ((c = in.read()) != -1) {
bout.write(c);
}
in = p.getErrorStream();
while ((c = in.read()) != -1) {
bout.write(c);
}
p.waitFor();
String result = new String(bout.toByteArray());
return result;
}
}
and when I give the input as (CTRL + M), I am getting displayed a value of 10. But I am expecting a value of 13. Please let me know if I am missing anything??
Upvotes: 0
Views: 503
Reputation: 263307
The translation of CR to LF is handled by the tty driver. You're calling setTerminalToCBreak()
, which manipulates the tty settings (I think it disables the erase, kill, werase, and rprnt special characters).
The icrnl
setting, which is enabled by default, causes carriage return (CR) to be translated to newline (LF). Disabling that should let you see CR characters directly. Setting raw
mode changes a number of flags, including turning off icrnl
. (Figuring out how to do that in Java is left as an exercise.)
But beware of doing this. The Enter or Return key typically sends a CR character. Translating it to LF is what allows it to mark the end of a line. If you turn off that translation, you might break that behavior unless you handle CR yourself.
For more information on tty settings, man tty
or follow this link.
Upvotes: 3
Reputation: 13914
My other answer started on totally the wrong page.
stty ("-cooked")
works for me.
Something in the depths of teletype land wants you to have happy little ^J
s instead of ^M
s, but cooking the terminal stops it.
$ stty -cooked ; java -cp /tmp NumbersConsole
13
$
Back in the Good Ol' Days, some computers (Commodore, Apple) used ^M (13) for their Return key; some (IBM) used a combination ^M^J; others (Unix) used ^J (10).
Now, in the modern world, it's almost always ^J (although I think Windows code still has some legacy ^M^J stuff under the hood sometimes?)
Upvotes: 0