Korzystanie z metody inputStream.available ()
Zawsze akceptowalne jest, aby System.in.available () zwracało 0.
Znalazłem coś przeciwnego - zawsze zwraca najlepszą wartość dla liczby dostępnych bajtów. Javadoc dla 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.
Oszacowanie jest nieuniknione ze względu na harmonogram / nieaktualność. Liczba ta może być jednorazowym niedoszacowaniem, ponieważ stale napływają nowe dane. Jednak zawsze „nadrabia zaległości” przy następnym wywołaniu - powinien uwzględniać wszystkie otrzymane dane, z wyjątkiem tego, że przychodzi tylko w momencie nowego połączenia. Trwałe zwracanie 0, gdy istnieją dane, nie spełnia powyższego warunku.
Pierwsze zastrzeżenie: konkretne podklasy InputStream są odpowiedzialne za available ()
InputStream
jest klasą abstrakcyjną. Nie ma źródła danych. Posiadanie dostępnych danych nie ma sensu. Dlatego javadoc dla available()
również stwierdza:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
I rzeczywiście, konkretne klasy strumienia wejściowego przesłaniają available (), dostarczając znaczące wartości, a nie stałe 0.
Drugie zastrzeżenie: upewnij się, że używasz powrotu karetki podczas wpisywania danych wejściowych w systemie Windows.
Jeśli używasz System.in
, twój program otrzymuje dane wejściowe tylko wtedy, gdy powłoka poleceń przekazuje je. Jeśli używasz przekierowań plików / potoków (np. Somefile> java myJavaApp lub somecommand | java myJavaApp), dane wejściowe są zwykle przekazywane natychmiast. Jeśli jednak ręcznie wpiszesz dane wejściowe, przekazanie danych może zostać opóźnione. Np. W powłoce cmd.exe systemu Windows dane są buforowane w powłoce cmd.exe. Dane są przekazywane do wykonującego się programu java tylko po powrocie karetki (control-m lub <enter>
). To jest ograniczenie środowiska wykonawczego. Oczywiście InputStream.available () zwraca 0 tak długo, jak długo powłoka buforuje dane - to poprawne zachowanie; w tym momencie nie ma dostępnych danych. Gdy tylko dane są dostępne z powłoki, metoda zwraca wartość> 0. NB: Cygwin używa cmd.
Najprostsze rozwiązanie (bez blokowania, więc nie jest wymagany limit czasu)
Po prostu użyj tego:
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.
LUB równoważnie,
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);
}
Bogatsze rozwiązanie (maksymalnie wypełnia bufor w określonym czasie)
Oświadcz, że:
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;
}
Następnie użyj tego:
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
ta sugestia się nie powiedzie. Z pewnością istnieją strumienie, które zwracają zero. SSLSockets do niedawna. Nie możesz na tym polegać.