Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4329985

BufferedReader.ready() returns true when readLine() will block

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.3.1
    • 1.3.0
    • core-libs
    • ladybird
    • x86
    • linux, windows_nt
    • Verified



        Name: skT45625 Date: 04/12/2000


        java version "1.3.0rc2"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc2-Y)
        Java HotSpot(TM) Client VM (build 1.3.0rc2-Y, mixed mode)

        I was trying to find a non-threaded solution to timeout reading input from the
        System.in. After a good bit of experimentation, I determined that the code
        appearing below SHOULD work. Unfortunately, it does not work on win32 systems
        because the BufferedReader implementation -- at least in jdk1.3rc2 -- does not
        correctly (or at least to my liking) implement the semantics of readLine().

        The API docs for readLine state: "Read a line of text. A line is considered to
        be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a
        carriage return followed immediately by a linefeed." This gives one (one being
        me in this case) the impression that the entire line-termination sequence will
        consumed. On win32 systems, line-termination is "\r\n", two characters.
        Unfortunately, the implementation does not consume both characters immediately.
        It finds the carriage return but leaves the newline in the buffer. As a result,
        ready() returns true but the subsequent read blocks when the only content in
        the buffer is the second half of the win32 line termination sequence.

        Here is the correct but, on win32 systems, non-working code. Note that this
        code DOES work as expected on jdk1.2.2.

        ---------- TimedReader.java ----------
        import java.io.InputStreamReader;
        import java.io.BufferedReader;
        import java.io.Reader;
        import java.io.IOException;

        public class TimedReader {
            public static void main(String[] args) {
                InputStreamReader isr = new InputStreamReader(System.in);
                BufferedReader in = new BufferedReader(isr);
                while (true) {
                    try {
                        System.out.print("Enter a String: ");
                        if (ready(in, 5000)) {
                            String s = in.readLine();
                        } else {
                            System.out.println("timeout");
                        }
                    } catch (IOException e) {
                        // ignore until we know what to do
                    }
                }
            }

            public static boolean ready(Reader in, long timeout) throws IOException {
                while (true) {
                    long now = System.currentTimeMillis();
                    try {
                        while (in.ready() == false && timeout > 0) {
                            Thread.sleep(100);
                            timeout -= 100;
                        }
                        return in.ready();
                    } catch (IOException e) {
                        throw e;
                    } catch (Exception e) {
                        // ignore
                    } finally {
                        // adjust timer by length of last nap
                        timeout -= System.currentTimeMillis() - now;
                    }
                }
            }
        }
        ---------- end ----------
        (Review ID: 103613)
        ======================================================================

              mmcclosksunw Michael Mccloskey (Inactive)
              skondamasunw Suresh Kondamareddy (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: