1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.input;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.RandomAccessFile;
24 import java.util.Objects;
25
26 import org.apache.commons.io.RandomAccessFileMode;
27 import org.apache.commons.io.build.AbstractOrigin;
28 import org.apache.commons.io.build.AbstractStreamBuilder;
29
30
31
32
33
34
35
36
37
38
39 public class RandomAccessFileInputStream extends InputStream {
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public static class Builder extends AbstractStreamBuilder<RandomAccessFileInputStream, Builder> {
60
61 private RandomAccessFile randomAccessFile;
62 private boolean closeOnClose;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 @SuppressWarnings("resource")
86 @Override
87 public RandomAccessFileInputStream get() throws IOException {
88 if (randomAccessFile != null) {
89 if (getOrigin() != null) {
90 throw new IllegalStateException(String.format("Only set one of RandomAccessFile (%s) or origin (%s)", randomAccessFile, getOrigin()));
91 }
92 return new RandomAccessFileInputStream(randomAccessFile, closeOnClose);
93 }
94 return new RandomAccessFileInputStream(RandomAccessFileMode.READ_ONLY.create(checkOrigin().getFile()), closeOnClose);
95 }
96
97
98
99
100
101
102
103 public Builder setCloseOnClose(final boolean closeOnClose) {
104 this.closeOnClose = closeOnClose;
105 return this;
106 }
107
108
109
110
111
112
113
114 public Builder setRandomAccessFile(final RandomAccessFile randomAccessFile) {
115 this.randomAccessFile = randomAccessFile;
116 return this;
117 }
118
119 }
120
121
122
123
124
125
126
127 public static Builder builder() {
128 return new Builder();
129 }
130
131 private final boolean closeOnClose;
132 private final RandomAccessFile randomAccessFile;
133
134
135
136
137
138
139
140 @Deprecated
141 public RandomAccessFileInputStream(final RandomAccessFile file) {
142 this(file, false);
143 }
144
145
146
147
148
149
150
151
152 @Deprecated
153 public RandomAccessFileInputStream(final RandomAccessFile file, final boolean closeOnClose) {
154 this.randomAccessFile = Objects.requireNonNull(file, "file");
155 this.closeOnClose = closeOnClose;
156 }
157
158
159
160
161
162
163
164
165
166 @Override
167 public int available() throws IOException {
168 final long avail = availableLong();
169 if (avail > Integer.MAX_VALUE) {
170 return Integer.MAX_VALUE;
171 }
172 return (int) avail;
173 }
174
175
176
177
178
179
180
181 public long availableLong() throws IOException {
182 return randomAccessFile.length() - randomAccessFile.getFilePointer();
183 }
184
185 @Override
186 public void close() throws IOException {
187 super.close();
188 if (closeOnClose) {
189 randomAccessFile.close();
190 }
191 }
192
193
194
195
196
197
198 public RandomAccessFile getRandomAccessFile() {
199 return randomAccessFile;
200 }
201
202
203
204
205
206
207 public boolean isCloseOnClose() {
208 return closeOnClose;
209 }
210
211 @Override
212 public int read() throws IOException {
213 return randomAccessFile.read();
214 }
215
216 @Override
217 public int read(final byte[] bytes) throws IOException {
218 return randomAccessFile.read(bytes);
219 }
220
221 @Override
222 public int read(final byte[] bytes, final int offset, final int length) throws IOException {
223 return randomAccessFile.read(bytes, offset, length);
224 }
225
226 @Override
227 public long skip(final long skipCount) throws IOException {
228 if (skipCount <= 0) {
229 return 0;
230 }
231 final long filePointer = randomAccessFile.getFilePointer();
232 final long fileLength = randomAccessFile.length();
233 if (filePointer >= fileLength) {
234 return 0;
235 }
236 final long targetPos = filePointer + skipCount;
237 final long newPos = targetPos > fileLength ? fileLength - 1 : targetPos;
238 if (newPos > 0) {
239 randomAccessFile.seek(newPos);
240 }
241 return randomAccessFile.getFilePointer() - filePointer;
242 }
243 }