-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathRandomAccessInputStream.java
More file actions
executable file
·130 lines (114 loc) · 3.73 KB
/
RandomAccessInputStream.java
File metadata and controls
executable file
·130 lines (114 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
/** This class uses a memory cache to allow seeking within
an InputStream. Based on the JAI MemoryCacheSeekableStream class.
Can also be constructed from a RandomAccessFile, which uses less
memory since the memory cache is not required.
Copied and adapted from http://imagej.nih.gov/ij/developer/source/ij/io/RandomAccessStream.java.html (public domain)
*/
public final class RandomAccessInputStream extends InputStream {
private static final int BLOCK_SIZE = 1024;
private static final int BLOCK_MASK = 1023;
private static final int BLOCK_SHIFT = 10;
private InputStream src;
private RandomAccessFile ras;
private long pointer;
private List<byte[]> data;
private long length;
private boolean foundEOS;
/** Constructs a RandomAccessStream from an InputStream. Seeking
backwards is supported using a memory cache. */
public RandomAccessInputStream(InputStream inputstream) {
pointer = 0L;
data = new ArrayList<byte[]>();
length = 0L;
foundEOS = false;
src = inputstream;
}
/** Constructs a RandomAccessStream from an RandomAccessFile. */
public RandomAccessInputStream(RandomAccessFile ras) {
this.ras = ras;
}
public long getOffset() throws IOException {
if (ras!=null)
return ras.getFilePointer();
else
return pointer;
}
public int read() throws IOException {
if (ras!=null)
return ras.read();
long l = pointer + 1L;
long l1 = readUntil(l);
if (l1>=l) {
byte abyte0[] = data.get((int)(pointer>>BLOCK_SHIFT));
return abyte0[(int)(pointer++ & BLOCK_MASK)] & 0xff;
} else
return -1;
}
public int read(byte[] bytes, int off, int len) throws IOException {
if(bytes == null)
throw new NullPointerException();
if (ras!=null)
return ras.read(bytes, off, len);
if (off<0 || len<0 || off+len>bytes.length)
throw new IndexOutOfBoundsException();
if (len == 0)
return 0;
long l = readUntil(pointer+len);
if (l<=pointer)
return -1;
else {
byte abyte1[] = data.get((int)(pointer >> BLOCK_SHIFT));
int k = Math.min(len, BLOCK_SIZE - (int)(pointer & BLOCK_MASK));
System.arraycopy(abyte1, (int)(pointer & BLOCK_MASK), bytes, off, k);
pointer += k;
return k;
}
}
private long readUntil(long l) throws IOException {
if (l<length)
return l;
if (foundEOS)
return length;
int i = (int)(l>>BLOCK_SHIFT);
int j = (int)(length>>BLOCK_SHIFT);
for (int k=j; k<=i; k++) {
byte abyte0[] = new byte[BLOCK_SIZE];
data.add(abyte0);
int i1 = BLOCK_SIZE;
int j1 = 0;
while (i1>0) {
int k1 = src.read(abyte0, j1, i1);
if (k1==-1) {
foundEOS = true;
return length;
}
j1 += k1;
i1 -= k1;
length += k1;
}
}
return length;
}
public void seek(long loc) throws IOException {
if (ras!=null)
{ras.seek(loc); return;}
if (loc<0L)
pointer = 0L;
else
pointer = loc;
}
public void close() throws IOException {
if (ras!=null)
ras.close();
else {
data.clear();
src.close();
}
}
}