Verwenden von inputStream.available ()
Es ist immer akzeptabel, dass System.in.available () 0 zurückgibt.
Ich habe das Gegenteil gefunden - es gibt immer den besten Wert für die Anzahl der verfügbaren Bytes zurück. Javadoc für 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.
Eine Schätzung ist aufgrund des Timings / der Alterung unvermeidbar. Die Zahl kann eine einmalige Unterschätzung sein, da ständig neue Daten eintreffen. Es "holt" jedoch immer beim nächsten Anruf auf - es sollte alle eingehenden Daten berücksichtigen, abgesehen davon, dass sie gerade zum Zeitpunkt des neuen Anrufs eintreffen. Die dauerhafte Rückgabe von 0, wenn Daten vorhanden sind, schlägt die obige Bedingung fehl.
Erste Einschränkung: Konkrete Unterklassen von InputStream sind für die Verfügbarkeit verantwortlich ()
InputStream
ist eine abstrakte Klasse. Es hat keine Datenquelle. Es ist bedeutungslos, Daten zur Verfügung zu haben. Daher heißt es in javadoc available()
auch:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
Tatsächlich überschreiben die konkreten Eingabestreamklassen die verfügbaren () und liefern aussagekräftige Werte, keine konstanten Nullen.
Zweite Einschränkung: Stellen Sie sicher, dass Sie Wagenrücklauf verwenden, wenn Sie Eingaben in Windows eingeben.
Bei Verwendung System.in
erhält Ihr Programm nur Eingaben, wenn Ihre Befehlsshell sie übergibt. Wenn Sie Dateiumleitungen / Pipes verwenden (z. B. somefile> java myJavaApp oder somecommand | java myJavaApp), werden Eingabedaten normalerweise sofort übergeben. Wenn Sie die Eingabe jedoch manuell eingeben, kann sich die Datenübergabe verzögern. Beispiel: Bei der Windows-Shell cmd.exe werden die Daten in der Shell cmd.exe gepuffert. Daten werden erst nach Wagenrücklauf (control-m oder <enter>
) an das ausführende Java-Programm übergeben . Dies ist eine Einschränkung der Ausführungsumgebung. Natürlich gibt InputStream.available () 0 zurück, solange die Shell die Daten puffert - das ist korrektes Verhalten. Zu diesem Zeitpunkt sind keine Daten verfügbar. Sobald die Daten in der Shell verfügbar sind, gibt die Methode einen Wert> 0 zurück. Hinweis: Cygwin verwendet cmd.
Einfachste Lösung (keine Blockierung, daher keine Zeitüberschreitung erforderlich)
Verwenden Sie einfach dies:
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.
Oder gleichwertig,
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);
}
Reichhaltigere Lösung (füllt den Puffer innerhalb des Zeitlimits maximal aus)
Erklären Sie dies:
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;
}
Dann benutze dies:
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
dieser Vorschlag fehlschlägt. Es gibt sicherlich Streams, die Null zurückgeben. SSLSockets zum Beispiel bis vor kurzem. Darauf können Sie sich nicht verlassen.