Гарантирует ли метод BufferedReader.ready (), что метод readLine () не возвращает NULL? - PullRequest
11 голосов
/ 09 марта 2011

У меня есть такой код для чтения текстового файла, используя BufferedReader:

BufferedReader reader=null;
    try {
        reader = new BufferedReader(new FileReader("file1.txt"));

        while (reader.ready()) {
            final String line = reader.readLine();
            System.out.println("<"+line+">");
        } catch (..)
    {
        ...
    }

Работает правильно, но Findbugs выдает предупреждение:

NP_DEREFERENCE_OF_READLINE_VALUE: результат вызова readLine () равен разыменованный без проверки, чтобы увидеть если результат ноль. Если нет больше строк текста для чтения, readLine () вернет ноль и разыменование это сгенерирует нулевой указатель исключение.

Когда я меняю FileReader на StringReader, т.е.

BufferedReader reader=null;
    try {
        reader = new BufferedReader(new StringReader("ABCD"));

        while (reader.ready()) {
            final String line = reader.readLine();
            System.out.println("<"+line+">");
        } catch (..)
    {
        ...
    }

метод readLine возвращает null, а метод ready всегда возвращает true - действительно, это бесконечный цикл.

Кажется, что readLine может вернуть null, даже если ready вернет true. Но почему поведение отличается для разных Reader с?

UPDATE:

Я знаю нормальный способ чтения текстового файла (как иллюстрировали Питер и Али). но я прочитал этот кусок кода от моего коллеги и понял, что не знаю метод ready. Затем я читаю JavaDoc, но не понимаю block. Затем я сделал тест и разместил этот вопрос. Итак, лучший способ задать этот вопрос:

Когда будет блокироваться вход? Как использовать метод ready (или почему бы не использовать его)? Почему эти 2 Reader s (FileReader и StringReader) ведут себя по-разному в отношении метода ready?

Ответы [ 4 ]

15 голосов
/ 10 марта 2011

Метод ready сообщает нам, готов ли поток для чтения.

Представьте, что ваш поток читает данные из сетевого сокета. В этом случае поток может не закончиться, поскольку сокет не был закрыт, но он может быть не готов к следующему фрагменту данных, поскольку другой конец сокета не выдвинул больше данных.

В приведенном выше сценарии мы не можем больше читать данные, пока удаленный конец не вытолкнет их, поэтому нам нужно дождаться, когда данные станут доступны или сокет будет закрыт. Метод ready () сообщает нам, когда данные доступны.

12 голосов
/ 09 марта 2011

Reader.ready () и InputStream.available () редко работают так, как вам хотелось бы, и я не советую вам их использовать.Чтобы прочитать файл, вы должны использовать

String line;
while ((line = reader.readLine()) != null)
    System.out.println("<"+line+">");
6 голосов
/ 09 марта 2011

Вот что говорят Javadoc:

Сообщает, готов ли этот поток для чтения. Буферизованный символьный поток готов, если буфер не пуст или если основной символьный поток готов.

Таким образом, BufferedReader считается готовым, просто если базовый поток также готов. Поскольку BufferedReader является оболочкой, этот базовый поток может быть любой реализацией Reader; следовательно, семантика ready() объявлена ​​на интерфейсе:

Возвращает true, если гарантируется, что следующее чтение () не заблокирует ввод, иначе false. Обратите внимание, что возвращение false не гарантирует блокировку следующего чтения.

Таким образом, вы действительно получаете только сроки гарантии, то есть read() не будет блокироваться. Результат вызова ready() абсолютно ничего не говорит вам о контенте , который вы получите после вызова read(), и поэтому его нельзя использовать для исключения нулевой проверки.

1 голос
/ 09 марта 2011

Посмотрите на API для готовности .

То, что вы делаете, неправильно.ready() только говорит вам, если поток доступен для чтения и действителен.Прочтите также комментарий под этой ссылкой.

Что вы хотите сделать:

String thisLine;

//Loop across the arguments
for (int i=0; i < args.length; i++) {

  //Open the file for reading
  try {
    BufferedReader br = new BufferedReader(new FileReader(args[i]));
    while ((thisLine = br.readLine()) != null) { // while loop begins here
      System.out.println(thisLine);
    } // end while 
  } // end try
  catch (IOException e) {
    System.err.println("Error: " + e);
  }
} // end for
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...