Получение нулевого значения из буфера чтения

Я не могу понять, почему я получаю null от буферизованного считывателя в следующем коде (2-я строка вывода), хотя в некоторых местах он работал нормально (1-я строка вывода).

Я использовал несколько system.out.println только для целей отладки.

Хотя BufferedReader.readLine() возвращает значение null только при достижении конца потока, входные данные предоставляются (как показано на входных данных ниже программы). Пожалуйста, помогите мне понять причину получения нуля и предложите решение.

 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.util.*;
 import java.lang.Integer;
 import java.io.*;

class TestClass {
public static void main(String args[] ) throws Exception {

     //* Read input from stdin and provide input before running
    List a2=new ArrayList();
    String[] a1=new String[2];
    int count=0;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String line = br.readLine();
    /*for (String retval: line.split(" "))
        a2.add(retval);*/
    a1=line.split(" ");
    //System.out.println("here 0"+a1[0]+" "+a1[1]);
    /*int N = Integer.parseInt((a2.get(0)).toString());
    int Q= Integer.parseInt((a2.get(1)).toString());*/
    int N = Integer.parseInt(a1[0].toString());
    int Q= Integer.parseInt(a1[1].toString());

        System.out.println("here xxxxxxxx" + N +" " +Q);
    String[] names=new String[N];
    for(int i=0;i<N;i++){
        //names[i]  =   (new BufferedReader(new InputStreamReader(System.in))).readLine();

        BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
    names[i] = br1.readLine();

    /*Scanner sc=new Scanner(System.in);  
    names[i]=sc.nextLine();*/
    }
   System.out.println("here 111" + names[0]);
   for(int i=0;i<Q;i++) {
    br = new BufferedReader(new InputStreamReader(System.in));
    String line1 = br.readLine();
    try{
         System.out.println("here 1" + line1);

        int M = Integer.parseInt(line1);
        System.out.println("here 2");
        if(M<=20){
            System.out.println("here 3");
            count++;
        }
    }
    catch(Exception e){
        System.out.println("here 4");
        if(!((Arrays.asList(names)).contains(line))){
            System.out.println("here 5");
            count++;
        }

    }
   }

    System.out.println(count);
}
}

Вход

Первая строка входных данных будет содержать два целых числа, разделенных пробелом, обозначающих N и Q.

Следующие N строк будут содержать строки

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

enter code here

Входы и выходы следующие:

 Input:
 2 4
 pranjul
 sachin
 21
 19
 pranjul
 vipul

 Output:
 here xxxxxxxx2 4
 here 111null
 here 1null
 here 4
 here 5
 here 1null
 here 4
 here 5
 here 1null
 here 4
 here 5
 here 1null
 here 4
 here 5
 4

person Gaurav Jain    schedule 20.03.2016    source источник
comment
Как вы сказали, «причина нуля» - это конец потока. Вы не тестируете его и не обрабатываете его. Сделай так. NB Не создавайте новый буферизованный считыватель каждый раз в цикле. Таким образом вы можете потерять данные. Используйте тот же.   -  person user207421    schedule 20.03.2016


Ответы (2)


Вы пытаетесь открыть более одного считывателя в одном входном потоке.

Когда вы читаете содержимое своего первого br.readLine(), вот что происходит:

  • У BufferedReader есть внутренний буфер, который необходимо заполнить. Он вызывает метод read из базового InputStreamReader, чтобы заполнить его.
  • InputStreamReader, чтобы преобразовать байты входного потока в символы, использует StreamDecoder. Поэтому он вызывает метод read этого StreamDecoder. Внутри у него также есть буфер, и он считывает столько байтов, сколько может из базового потока в этот буфер.

Это означает, что как только вы читаете одну строку, вы также читаете несколько символов после этой строки. По умолчанию размер буфера StreamDecoder байт составляет 8 КБ, поэтому он считывает 8 КБ байт из System.in, если они доступны.

Если вы используете System.in в интерактивном режиме, каждое чтение только заполняет буфер таким количеством байтов, которое доступно прямо сейчас. Таким образом, он заполняет только одну строку до точки, где пользователь нажал Enter, и поэтому, когда вы открываете другие экземпляры BufferedReader, они получат следующий ввод, который вводит пользователь.

Но если System.in перенаправить из файла или другого потока, где он не блокируется в конце строки, он прочитает весь файл (при условии, что размер файла меньше 8 КБ) при первом вызове readLine. Эти данные ожидают в этом буфере BufferedReader или базовом буфере StreamDecoder.

Поэтому, когда вы открываете новый BufferedReader на System.in, в этом потоке больше нет данных — он уже был прочитан первым BufferedReader. Вот почему не рекомендуется открывать более одного ридера на одном потоке.

person RealSkeptic    schedule 20.03.2016

во-первых, вам не нужны первые две строки, если вы используете io.*; во-вторых зачем вы использовали столько потоков, если 1 достаточно

import java.util.*;
 import java.lang.Integer;
 import java.io.*;

class TestClass {
public static void main(String args[] ) throws Exception {

List a2=new ArrayList();
int count=0;
Scanner br = new Scanner(System.in);
String line = br.nextLine();

String[] a1=line.split(" ");
int N = Integer.parseInt(a1[0]);
int Q= Integer.parseInt(a1[1]);

    System.out.println("here xxxxxxxx" + N +" " +Q);
String[] names=new String[N];
for(int i=0;i<N;i++){
 names[i]=br.nextLine();
}
System.out.println("here 111" + names[0]);
for(int i=0;i<Q;i++) {
String line1 = br.nextLine();
try{
     System.out.println("here 1" + line1);

    int M = Integer.parseInt(line1);
    System.out.println("here 2");
    if(M<=20){
        System.out.println("here 3");
        count++;
    }
}
catch(Exception e){
    System.out.println("here 4");
    if(!((Arrays.asList(names)).contains(line))){
        System.out.println("here 5");
        count++;         }    }   }
System.out.println(count);
br.close();}}

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

person KennyMD    schedule 20.03.2016
comment
Строки кода не являются «строками», и ваш ответ должен быть написан с заглавной буквы, пунктуирован и грамматически исправлен. - person user207421; 20.03.2016
comment
Спасибо. Я проверил ваш код. Он работает нормально. Не могли бы вы рассказать мне, почему использование bufferestream дает значение null. - person Gaurav Jain; 20.03.2016