Possible Timed Reads from an InputStream
The challenge lies in designing a method called maybeRead that returns the same result as in.read() if data is available within a specified timeout. Specifically, maybeRead returns -2 if no data is available within the given timeout.
Initially, it seems wrapping InputStream in a Reader or InterruptibleChannel could offer a solution, but both only pass through InputStream methods. Additionally, it is critical to avoid any thread spawn during this process.
Despite beliefs that in.available() always returns 0, documentation reveals it provides an estimate of the bytes available for reading without blocking. While this estimate may be underestimated, it catches up on the following call to account for new arrivals.
However, subclasses of InputStream handle their own implementation of available(), and concrete implementations override it to give meaningful values. Hence, simply using is.available() isn't sufficient.
For non-blocking and timeout-less reads, consider the following solutions:
byte[] inputData = new byte[1024]; int result = is.read(inputData, 0, is.available()); // -1 for EOF with no data read.
Or
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); }
For a more intricate solution that maximizes the buffer within a timeout, utilize the below method:
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; }
And use it as follows:
byte[] inputData = new byte[1024]; int readCount = readInputStreamWithTimeout(System.in, inputData, 6000); // 6 second timeout // readCount indicates bytes read; -1 for EOF with no data read.
The above is the detailed content of How to Implement a Timed Read from an InputStream Without Threading?. For more information, please follow other related articles on the PHP Chinese website!