Как читать со стандартного ввода без блокировки?
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().