Використання 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, коли є дані, не відповідає умові вище.
First Caveat: Бетонні підкласи InputStream відповідають за доступні ()
InputStream
- абстрактний клас. У ньому немає джерела даних. Немає сенсу мати доступні дані. Отже, javadoc для available()
також заявляє:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
Дійсно, конкретні класи вхідного потоку переосмислюють наявні (), забезпечуючи значущі значення, а не постійні 0.
Другий застереження: переконайтеся, що ви використовуєте повернення каретки під час введення вводу в Windows.
Якщо використовується System.in
, ваша програма отримує вхід лише тоді, коли ваша командна оболонка передасть її. Якщо ви використовуєте переадресацію файлів / файлів (наприклад, деякий файл> java myJavaApp або деякийкоманд | 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);
}
Рішучіше рішення (максимально заповнює буфер протягом періоду очікування)
Заявіть про це:
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, наприклад, до недавнього часу. Ви не можете розраховувати на це.