confusion about the behavior of the read() method of System.in in Java
Asked Answered
T

2

6

I know that the System.in of the System class is an instance of a concrete subclass of InputStream because the read() method of InputStream is abstract and System.in must override this method. According to the document about the read() method of InputStream:

public abstract int read() throws IOException

Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
A subclass must provide an implementation of this method.

Returns:
the next byte of data, or -1 if the end of the stream is reached.

Throws:
IOException - if an I/O error occurs.

The read() method should return -1 if the end of the stream is reached. My question is, when will the System.in.read() return -1?

The following is sample code:

import java.io.*;

class SystemInTest{
    public static void main(String[] args) throws IOException{
        InputStream in = System.in;
        //InputStream in = new FileInputStream("h.txt");

        int ch = 0;
        while((ch = in.read()) != -1){
            System.out.println(ch);
        }
    }
}

Run this code, and type "abc" followed by an "Enter", the result is(under Linux):

97
98
99
10

Then the application is blocked and waits for another input. But I thought the statement in while loop "ch = in.read()" should continue to run and return -1 after reading the line-termination character and printing 10 on the console. If so, the application should be terminated. But it is blocked.

As a comparison, if I uncomment the commented line, using a file whose content is "abc\n" as byte input stream, then the application terminates as expectation because -1 is returned.

Is it really true that the System.in.read() never returns -1? If so, why is the implementation of the read() method in System.in different with other subclasses of InputStream such as FileInputStream?

Tasteless answered 10/6, 2016 at 6:28 Comment(4)
Press ctrl-D (maybe twice) to close the input stream. If you don't actually close the stream, you're not at EOF.Existent
Only when the input actually ends, e.g. echo abc | java SystemInTestBeadroll
What you suggest would prevent any program to read more than one line from the command line. The stream isn't closed. It just waits for you to enter the next characters. -1 will be returned if you use java MyClass < somefile.txt, for example.Quarterdeck
Your stream will never return -1 because its size is undefined. In the case of a file, the size in bytes of the file is known and when all the bytes are read, read() then returns -1. Related : #24992303Goodrum
O
4

Pressing Enter only means that you finished a line, it doesn’t mean that you finished a whole “file”.

How you finish a file depends on the operating system. On Linux, it is Ctrl+D, which you can use in many programs to exit them (instead of typing exit or quit). On Windows, it is Ctrl+Z.

Obsequent answered 10/6, 2016 at 7:2 Comment(0)
G
1

Input stream don't have fixed size so your program is entering infinite loop and asking for input again and again. However, h.txt file is having fixed size so while is getting terminated.

Grainy answered 10/6, 2016 at 6:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.