EN
Java - read from a InputStream with timeout
9 points
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.
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:
xxxxxxxxxx
1
package com.example;
2
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.io.DataInputStream;
6
7
public class Program {
8
9
private static final Runtime RUNTIME = Runtime.getRuntime();
10
11
public static void main(String[] args) throws IOException {
12
// ...
13
int timeout = 5000; // 5 seconds
14
// ...
15
Process process = RUNTIME.exec(new String[] {"node.exe", "script.js"}); // it runs: node.exe script.js
16
DataInputStream inputStream = new DataInputStream(new TimeoutInputStream(process.getInputStream(), timeout));
17
DataInputStream errorStream = new DataInputStream(new TimeoutInputStream(process.getErrorStream(), timeout));
18
// ...
19
short a = inputStream .readShort(); // waits for 2 bytes or throws IOException
20
short b = inputStream .readShort(); // waits for 2 bytes or throws IOException
21
short c = inputStream .readShort(); // waits for 2 bytes or throws IOException
22
// ...
23
}
24
}
Example TimeoutInputStream.java
file:
xxxxxxxxxx
1
package com.example;
2
3
import java.io.IOException;
4
import java.io.InputStream;
5
6
public class TimeoutInputStream extends InputStream {
7
8
private static final int STEP = 200000; // in nanoseconds from 0 to 999999 (inclusive)
9
10
private long timeout;
11
private InputStream stream;
12
13
private volatile boolean looped = true;
14
15
public TimeoutInputStream(InputStream stream, int timeout) {
16
super();
17
this.timeout = 1000000L * timeout;
18
this.stream = stream;
19
}
20
21
22
public int read() throws IOException {
23
int a = this.stream.available();
24
if (a >= 1) {
25
return this.stream.read();
26
}
27
long t1 = System.nanoTime();
28
while (this.looped) {
29
try {
30
Thread.sleep(0, STEP);
31
} catch (InterruptedException e) {
32
throw new IOException("Waiting operation stopped.", e);
33
}
34
int b = this.stream.available();
35
if (b == 0) {
36
long t2 = System.nanoTime();
37
if (t2 - t1 > timeout) {
38
throw new IOException("Read operation timeout.");
39
}
40
} else {
41
return this.stream.read();
42
}
43
}
44
throw new IOException("Stream is closed.");
45
}
46
47
48
public void close() throws IOException {
49
this.looped = false; // only to speed up read() method breaking
50
super.close();
51
}
52
}
Note:
InputStream
read(byte[] buffer)
methods family doesn't throwIOException
, they just returns number of read bytes even error occurred inside.