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