Sử dụng inputStream.av Available ()
System.in.av Available () luôn được chấp nhận để trả về 0.
Tôi đã tìm thấy điều ngược lại - nó luôn trả về giá trị tốt nhất cho số byte có sẵn. Javadoc cho 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.
Một ước tính là không thể tránh khỏi do thời gian / độ cứng. Con số có thể được đánh giá thấp một lần vì dữ liệu mới liên tục đến. Tuy nhiên, nó luôn "bắt kịp" trong cuộc gọi tiếp theo - nó sẽ chiếm tất cả dữ liệu đã đến, thanh đến ngay tại thời điểm của cuộc gọi mới. Trả về 0 vĩnh viễn khi có dữ liệu không thành công với điều kiện trên.
Thông báo đầu tiên: Các lớp con cụ thể của InputStream chịu trách nhiệm về tính khả dụng ()
InputStream
là một lớp trừu tượng. Nó không có nguồn dữ liệu. Nó là vô nghĩa đối với nó để có dữ liệu có sẵn. Do đó, javadoc available()
cũng cho biết:
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
Và thực tế, các lớp luồng đầu vào cụ thể ghi đè có sẵn (), cung cấp các giá trị có ý nghĩa, không phải là 0 không đổi.
Thông báo thứ hai: Đảm bảo bạn sử dụng trả lại vận chuyển khi nhập dữ liệu vào Windows.
Nếu sử dụng System.in
, chương trình của bạn chỉ nhận được đầu vào khi shell lệnh của bạn chuyển giao nó. Nếu bạn đang sử dụng chuyển hướng / đường dẫn tệp (ví dụ: somefile> java myJavaApp hoặc somecommand | java myJavaApp), thì dữ liệu đầu vào thường được chuyển giao ngay lập tức. Tuy nhiên, nếu bạn nhập thủ công, thì việc chuyển dữ liệu có thể bị trì hoãn. Ví dụ: Với shell cmd.exe, dữ liệu được đệm trong shell cmd.exe. Dữ liệu chỉ được chuyển đến chương trình java thực thi sau khi trả về vận chuyển (control-m hoặc <enter>
). Đó là một hạn chế của môi trường thực thi. Tất nhiên, InputStream.av Available () sẽ trả về 0 miễn là trình bao đệm dữ liệu - đó là hành vi đúng; không có dữ liệu có sẵn tại thời điểm đó. Ngay khi dữ liệu có sẵn từ shell, phương thức trả về giá trị> 0. NB: Cygwin sử dụng cmd.
Giải pháp đơn giản nhất (không chặn, do đó không cần thời gian chờ)
Chỉ cần sử dụng này:
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.
HOẶC tương đương,
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);
}
Giải pháp phong phú hơn (lấp đầy tối đa bộ đệm trong khoảng thời gian chờ)
Khai báo điều này:
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;
}
Sau đó sử dụng:
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
đề nghị này sẽ thất bại. Có những luồng chắc chắn trả về 0. SSLSockets chẳng hạn cho đến gần đây. Bạn không thể dựa vào điều này.