Home >Java >javaTutorial >How to Implement a Timed Read from an InputStream Without Threading?

How to Implement a Timed Read from an InputStream Without Threading?

Susan Sarandon
Susan SarandonOriginal
2024-12-26 15:54:11891browse

How to Implement a Timed Read from an InputStream Without Threading?

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 &amp;&amp; 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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn