Использование inputStream.available ()
System.in.available () всегда допустимо возвращать 0.
Я обнаружил обратное - он всегда возвращает лучшее значение для количества доступных байтов. Javadoc для InputStream.available()
:
Returns an estimate of the number of bytes that can be read (or skipped over)
from this input stream without blocking by the next invocation of a method for
this input stream.
Оценка неизбежна из-за сроков / устаревания. Эта цифра может быть разовой заниженной, поскольку постоянно поступают новые данные. Однако он всегда «догоняет» при следующем вызове - он должен учитывать все поступившие данные, за исключением того, что он поступил только в момент нового вызова. Постоянно возвращать 0 при наличии данных не соответствует условию выше.
Первое предупреждение: за доступность отвечают конкретные подклассы InputStream
InputStream
это абстрактный класс. У него нет источника данных. Бессмысленно иметь доступные данные. Следовательно, Javadoc для available()
также утверждает:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
И действительно, конкретные классы входного потока переопределяют available (), предоставляя значимые значения, а не постоянные 0.
Второе предупреждение: убедитесь, что вы используете возврат каретки при вводе ввода в Windows.
При использовании System.in
ваша программа получает ввод только тогда, когда командная оболочка передает его. Если вы используете перенаправление файлов / pipe (например, somefile> java myJavaApp или somecommand | java myJavaApp), то входные данные обычно передаются немедленно. Однако, если вы вводите вручную, передача данных может быть отложена. Например, в оболочке windows cmd.exe данные буферизуются в оболочке cmd.exe. Данные передаются только в исполняющую Java-программу после возврата каретки (control-m или <enter>
). Это ограничение среды исполнения. Конечно, InputStream.available () будет возвращать 0 до тех пор, пока оболочка буферизует данные - это правильное поведение; на данный момент нет доступных данных. Как только данные доступны из оболочки, метод возвращает значение> 0. Примечание: Cygwin использует cmd.
Самое простое решение (без блокировки, поэтому не требуется тайм-аут)
Просто используйте это:
byte[] inputData = new byte[1024];
int result = is.read(inputData, 0, is.available());
// result will indicate number of bytes read; -1 for EOF with no data read.
ИЛИ эквивалентно,
BufferedReader br = new BufferedReader(new InputStreamReader(System.in, Charset.forName("ISO-8859-1")),1024);
// ...
// inside some iteration / processing logic:
if (br.ready()) {
int readCount = br.read(inputData, bufferOffset, inputData.length-bufferOffset);
}
Richer Solution (максимально заполняет буфер в течение периода ожидания)
Объявите это:
public static int readInputStreamWithTimeout(InputStream is, byte[] b, int timeoutMillis)
throws IOException {
int bufferOffset = 0;
long maxTimeMillis = System.currentTimeMillis() + timeoutMillis;
while (System.currentTimeMillis() < maxTimeMillis && bufferOffset < b.length) {
int readLength = java.lang.Math.min(is.available(),b.length-bufferOffset);
// can alternatively use bufferedReader, guarded by isReady():
int readResult = is.read(b, bufferOffset, readLength);
if (readResult == -1) break;
bufferOffset += readResult;
}
return bufferOffset;
}
Тогда используйте это:
byte[] inputData = new byte[1024];
int readCount = readInputStreamWithTimeout(System.in, inputData, 6000); // 6 second timeout
// readCount will indicate number of bytes read; -1 for EOF with no data read.
is.available() > 1024
это предложение не удастся. Конечно, есть потоки, которые возвращают ноль. SSLSockets например до недавнего времени. Вы не можете полагаться на это.