ใช้ 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 คงที่
Second Caveat: ตรวจสอบให้แน่ใจว่าคุณใช้ carriage-return เมื่อพิมพ์อินพุตใน Windows
หากใช้System.in
โปรแกรมของคุณจะรับอินพุตเมื่อเชลล์คำสั่งของคุณส่งมอบเท่านั้น หากคุณใช้การเปลี่ยนเส้นทางไฟล์ / ไพพ์ (เช่น somefile> java myJavaApp หรือ somecommand | java myJavaApp) จากนั้นข้อมูลอินพุตจะถูกส่งทันที อย่างไรก็ตามหากคุณป้อนข้อมูลด้วยตนเองการส่งข้อมูลอาจล่าช้าได้ เช่นกับเชลล์ windows cmd.exe ข้อมูลจะถูกบัฟเฟอร์ภายในเชลล์ cmd.exe ข้อมูลถูกส่งผ่านไปยังโปรแกรม Java ที่ดำเนินการตามหลัง carriage-return (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 ตัวอย่างเช่นเมื่อเร็ว ๆ นี้ คุณไม่สามารถพึ่งพาสิ่งนี้ได้