Languages
[Edit]
EN

Java - read from a InputStream with timeout

9 points
Created by:
Kourtney-White
635

In this short article, we would like to show a simple way how we can set timeout for each read operation in InputStream class in Java.

Simple answer:

If object that provides input stream doesn't support timeout parameter it is necessary to override read() method adding timeout logic.

 

Practical example

In this section you can find reusable TimeoutInputStream class that can be used when object that provides input stream doesn't support timeout parameter.

Example Program.java file:

package com.example;

import java.io.IOException;
import java.io.InputStream;
import java.io.DataInputStream;

public class Program {

    private static final Runtime RUNTIME = Runtime.getRuntime();

    public static void main(String[] args) throws IOException {
        // ...
        int timeout = 5000;  // 5 seconds
        // ...
        Process process = RUNTIME.exec(new String[] {"node.exe", "script.js"});  // it runs: node.exe script.js
        DataInputStream inputStream = new DataInputStream(new TimeoutInputStream(process.getInputStream(), timeout));
        DataInputStream errorStream = new DataInputStream(new TimeoutInputStream(process.getErrorStream(), timeout));
        // ...
        short a = inputStream .readShort();  // waits for 2 bytes or throws IOException
        short b = inputStream .readShort();  // waits for 2 bytes or throws IOException
        short c = inputStream .readShort();  // waits for 2 bytes or throws IOException
        // ...
    }
}

 

Example TimeoutInputStream.java file:

package com.example;

import java.io.IOException;
import java.io.InputStream;

public class TimeoutInputStream extends InputStream {
    
    private static final int STEP = 200000;  // in nanoseconds from 0 to 999999 (inclusive)

    private long timeout;
    private InputStream stream;

    private volatile boolean looped = true;

    public TimeoutInputStream(InputStream stream, int timeout) {
        super();
        this.timeout = 1000000L * timeout;
        this.stream = stream;
    }

    @Override
    public int read() throws IOException {
        int a = this.stream.available();
        if (a >= 1) {
            return this.stream.read();
        }
        long t1 = System.nanoTime();
        while (this.looped) {
            try {
                Thread.sleep(0, STEP);
            } catch (InterruptedException e) {
                throw new IOException("Waiting operation stopped.", e);
            }
            int b = this.stream.available();
            if (b == 0) {
                long t2 = System.nanoTime();
                if (t2 - t1 > timeout) {
                    throw new IOException("Read operation timeout.");
                }
            } else {
                return this.stream.read();
            }
        }
        throw new IOException("Stream is closed.");
    }

    @Override
    public void close() throws IOException {
        this.looped = false;  // only to speed up read() method breaking
        super.close();
    }
}

Note: InputStream read(byte[] buffer) methods family doesn't throw IOException, they just returns number of read bytes even error occurred inside.

 

Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join