readline () возвращает ноль в Java - PullRequest
2 голосов
/ 09 марта 2012

Я пытаюсь прочитать стандарт в моей программе Java. Я ожидаю серию чисел с последующими символами новой строки, например:

6  
9  
1  

При вводе данных через встроенную консоль eclipse все идет хорошо. Но при использовании командной строки Windows программа печатает:

Received '6'.  
Received 'null'.  
Invalid input. Terminating. (This line is written by another function that does an Integer.parseint()).  

Мой код:

static String readLineFromStdIn(){  
try{  
        java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));  
        String input = new String();  
        input = stdin.readLine();  
        System.out.println("Received '" + input + "'");  
        return(input);  
    }catch (java.io.IOException e) {  
        System.out.println(e);   
    }  
    return "This should not have happened";  
}  

Есть какие-нибудь подсказки?

Ответы [ 2 ]

8 голосов
/ 09 марта 2012

То, что вы получаете null, указывает, что соответствующие Reader объекты достигли EOF (конец файла), или другими словами, что они не могут получить более стандартный ввод. Теперь очевидные проблемы с вашим кодом:

  1. Каждый вызов метода readLineFromStdIn() создаст new BufferedReader.
  2. Каждый такой BufferedReader будет «конкурировать» друг с другом за один и тот же общий вход от System.in
  3. И ни один из этих BufferedReader объектов никогда не закрывается должным образом, поэтому ваша программа теряет ресурсы ввода-вывода при каждом вызове readLineFromStdIn().

Решением является использование одного общего BufferedReader объекта для каждого вызова readLineFromStdIn().

2 голосов
/ 12 февраля 2014

Не совсем новый ответ на этот вопрос, но я хотел прояснить путаницу в комментариях о том, почему исходный код вел себя так, как он (я не могу комментировать, потому что я новичок в ST и не набрал репутацию точек).

Нулевой результат не имеет ничего общего с сборкой мусора. Следующая программа постигла та же участь, хотя оба читателя все еще живут, доступные объекты:

BufferedReader r1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r1.readLine());
BufferedReader r2 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r2.readLine());

Все сводится к тому, что означает «Буферизованный» в BufferedReader. Это Reader, который включает внутреннюю буферизацию. Внутренняя буферизация обычно значительно повышает эффективность операций в основном потоке, например пытаясь каждый раз прочитать значение полного буфера, вместо того, чтобы «потрубить поток» до смерти, получая несколько байтов здесь и несколько там.

Так что же происходит, когда вы создаете первый BufferedReader на stdin и читаете из него строку? BufferedReader читает полный буфер из потока, обнаруживает конец строки, возвращает первую строку и вешает остаток буфера, чтобы заполнить свой следующий запрос. Это оставляет основной поток, расположенный за концом этой первой строки. И если ваш ввод небольшой, его можно легко расположить на EOF.

Итак, теперь вы идете и создаете второй BufferedReader поверх того же потока - который находится в EOF - и пытаетесь получить строку. Второй BufferedReader пытается прочитать из базового потока и обнаруживает EOF, поэтому readLine возвращает null.

...