Как читать со стандартного ввода без блокировки?

    long end=System.currentTimeMillis()+60*10;
    InputStreamReader fileInputStream=new InputStreamReader(System.in);
    BufferedReader bufferedReader=new BufferedReader(fileInputStream);
    try
    {
        while((System.currentTimeMillis()<end) && (bufferedReader.readLine()!=null))
        {

        }
        bufferedReader.close();
    }
    catch(java.io.IOException e)
    {
        e.printStackTrace();
    }

Я действительно пробовал сделать выше для чтения в 600 миллисекунд, после чего он не должен позволять читать, но readline буферизованного считывателя блокирует. Пожалуйста, помогите

Ответ 1

Вы можете проверить с помощью BufferedReader.available() > 0, если есть символы для чтения.

String s;

while((System.currentTimeMillis()<end))
{
    if (bufferedReader.available() > 0)
        s += bufferedReader.readLine();
}

bufferedReader.close();

Ответ 2

Использование BufferedReader.available(), как предложено Sibbo, не является надежным. Документация available() гласит:

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

Другими словами, вы не можете полагаться на это значение, например, оно может возвращать 0, даже если некоторые символы действительно доступны.

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


Обновление: здесь приведена упрощенная версия кода из приведенной выше ссылки:

public class NonblockingBufferedReader {
    private final BlockingQueue<String> lines = new LinkedBlockingQueue<String>();
    private volatile boolean closed = false;
    private Thread backgroundReaderThread = null;

    public NonblockingBufferedReader(final BufferedReader bufferedReader) {
        backgroundReaderThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        String line = bufferedReader.readLine();
                        if (line == null) {
                            break;
                        }
                        lines.add(line);
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    closed = true;
                }
            }
        });
        backgroundReaderThread.setDaemon(true);
        backgroundReaderThread.start();
    }

    public String readLine() throws IOException {
        try {
            return closed && lines.isEmpty() ? null : lines.poll(500L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new IOException("The BackgroundReaderThread was interrupted!", e);
        }
    }

    public void close() {
        if (backgroundReaderThread != null) {
            backgroundReaderThread.interrupt();
            backgroundReaderThread = null;
        }
    }
}

Ответ 3

long end=System.currentTimeMillis()+60*10;
InputStreamReader fileInputStream = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(fileInputStream);
try {
    while ((System.currentTimeMillis() < end)) {
        if (bufferedReader.ready()) {
            System.out.println(bufferedReader.readLine());
        }
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (bufferedReader != null) {
            bufferedReader.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Ответ 4

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

Если рабочий поток ожидает дольше, чем разрешено, главный поток завершает его и генерирует исключение.

Ответ 5

BufferReader.readLine() может блокироваться очень долго, если строка очень длинна, как 1M символов.

В вашем файле содержатся такие длинные строки?

Если да, возможно, вам придется разбить строки или использовать per-w980 > методы чтения, такие как BufferReader.read().