İnputStream.available () kullanma
System.in.available () 'nın 0 döndürmesi her zaman kabul edilebilir.
Bunun tersini buldum - her zaman mevcut bayt sayısı için en iyi değeri döndürür. Javadoc için 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.
Zamanlama / bayatlık nedeniyle bir tahmin kaçınılmazdır. Rakam, bir defaya mahsus eksik tahmin olabilir, çünkü sürekli yeni veriler gelmektedir. Ancak, her zaman bir sonraki aramada "yetişir" - gelen tüm verileri hesaba katmalı, yeni arama anında gelen verileri engellemelidir. Veri olduğunda kalıcı olarak 0 döndürmek yukarıdaki koşulda başarısız olur.
İlk Uyarı: InputStream'in somut alt sınıfları mevcutlardan sorumludur ()
InputStream
soyut bir sınıftır. Veri kaynağı yoktur. Mevcut verilere sahip olmasının anlamı yok. Bu nedenle, javadoc available()
ayrıca şunları belirtir:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
Ve aslında, somut girdi akışı sınıfları available () 'u geçersiz kılar ve sabit 0'lar yerine anlamlı değerler sağlar.
İkinci Uyarı: Windows'ta giriş yazarken satır başı kullandığınızdan emin olun.
Kullanıyorsanız System.in
, programınız yalnızca komut kabuğunuz onu verdiğinde girdi alır. Dosya yeniden yönlendirme / boruları kullanıyorsanız (örneğin, dosya> java myJavaApp veya bazı komutlar | java myJavaApp), bu durumda giriş verileri genellikle hemen teslim edilir. Ancak, girişi manuel olarak yazarsanız, veri aktarımı gecikebilir. Örneğin, windows cmd.exe kabuğunda veriler cmd.exe kabuğunda arabelleğe alınır. Veriler, yalnızca carriage-return (control-m veya <enter>
) sonrasında yürütülen java programına aktarılır . Bu, yürütme ortamının bir sınırlamasıdır. Tabii ki, InputStream.available (), kabuk verileri tamponladığı sürece 0 döndürür - bu doğru davranış; o noktada mevcut veri yok. Veriler kabuktan elde edilir edilmez, yöntem> 0 değerini döndürür. Not: Cygwin cmd kullanır.
En basit çözüm (engelleme yok, bu nedenle zaman aşımı gerekmez)
Sadece şunu kullan:
byte[] inputData = new byte[1024];
int result = is.read(inputData, 0, is.available());
Veya eşdeğer olarak,
BufferedReader br = new BufferedReader(new InputStreamReader(System.in, Charset.forName("ISO-8859-1")),1024);
if (br.ready()) {
int readCount = br.read(inputData, bufferOffset, inputData.length-bufferOffset);
}
Daha Zengin Çözüm (zaman aşımı süresi içinde tamponu en fazla doldurur)
Bunu beyan edin:
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);
int readResult = is.read(b, bufferOffset, readLength);
if (readResult == -1) break;
bufferOffset += readResult;
}
return bufferOffset;
}
O zaman şunu kullan:
byte[] inputData = new byte[1024];
int readCount = readInputStreamWithTimeout(System.in, inputData, 6000);
is.available() > 1024
bu öneri başarısız olacaktır. Kesinlikle sıfır döndüren akışlar vardır. Örneğin yakın zamana kadar SSLSockets. Buna güvenemezsin.