Java 是否可以从InputStream读取超时?
具体来说,问题是编写这样的方法:
int maybeRead(InputStream in, long timeout)
如果数据在“超时”毫秒内可用,则返回值与in.read()相同,否则为-2。在方法返回之前,所有产生的线程必须退出。
为避免自变量,此处的主题为java.io.InputStream,如Sun(任何Java版本)所记录。请注意,这并不像看起来那么简单。以下是Sun的文档直接支持的一些事实。
- in.read()方法可能是不可中断的。
将InputStream包装在Reader或InterruptibleChannel中没有帮助,因为所有这些类都可以做的是InputStream的调用方法。如果可以使用这些类,则可以编写一个直接在InputStream上执行相同逻辑的解决方案。
in.available()返回0始终是可接受的。
- in.close()方法可能会阻止或不执行任何操作。
- 没有杀死另一线程的一般方法。
回答:
使用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会导致上述情况失败。
:InputStream
的具体子类负责available()
InputStream
是一个抽象类。它没有数据源。拥有可用数据毫无意义。因此,javadoc available()也指出:
The available method for class InputStream always returns 0.This method should be overridden by subclasses.
实际上,具体的输入流类确实会覆盖available(),提供有意义的值,而不是恒定的0。
:确保在Windows中键入输入时使用回车符。
如果使用System.in
,则程序仅在命令外壳程序移交时才接收输入。如果你使用文件重定向/管道(例如somefile> java myJavaApp
或somecommand | java myJavaApp
),则通常会立即移交输入数据。但是,如果你手动键入输入,则数据切换可能会延迟。例如,使用Windows cmd.exe Shell
,数据将缓存在cmd.exe Shell
中。数据仅在回车(控制-m或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.
以上是 Java 是否可以从InputStream读取超时? 的全部内容, 来源链接: utcz.com/qa/434508.html