0

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

Community
  • 1
  • 1
  • 3
    It is `System.in` that is line-buffered here. It has nothing to do with `BufferedReader` or `InputStreamReader.` If you want a character at a time use `java.io.Console.` Your question about 'get[ting] to the end of the stream without having to type Ctrl+D' is meaningless. Ctrl+D *is* the end of the stream. – user207421 Aug 20 '14 at 01:09
  • The `java.io.Console` class is line buffered as well, read the Java docs. – markspace Aug 20 '14 at 01:21
  • Ok so that explains why do I get that output, the buffering independently of if `BufferedReader` is used. Thank you guys –  Aug 20 '14 at 01:26
  • @markspace Err oops my bad, tks. – user207421 Aug 20 '14 at 01:36

1 Answers1

2
  1. 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.

  2. 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.)

  3. Input via the java.io.Console class behaves the same way.

  4. This is the same on Windows: the behaviour is portable. (This is a good thing ...)

  5. 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.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216