4 * Copyright (C) 2001-2004 Ho Ngoc Duc
5 * Copyright (C) 2016-2022 Hiroshi Miura
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 import org.jetbrains.annotations.NotNull;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.RandomAccessFile;
30 * RandomAccessInputStream.
31 * Buffering RandomAccessFile and provide InputStream interface.
34 * @author Hiroshi Miura
36 public class RandomAccessInputStream extends InputStream {
37 private static final int DEFAULT_BUFSIZE = 4096;
38 private final RandomAccessFile in;
39 private final byte[] inbuf;
40 private final int bufsize;
42 private long currentpos = 0;
43 private long startpos = -1;
44 private long endpos = -1;
45 private long mark = 0;
49 * Constructor of RandomAccessInputStream, accept RandomAccessFile and buffer size.
50 * @param inFile RandomAccessFile file.
51 * @param bufsize buffer size.
53 public RandomAccessInputStream(final RandomAccessFile inFile, final int bufsize) {
55 this.bufsize = bufsize;
56 inbuf = new byte[bufsize];
60 * Construct RandomAccessInputStream from file.
62 * @param inFile RandomAccessFile
64 public RandomAccessInputStream(final RandomAccessFile inFile) {
65 this(inFile, DEFAULT_BUFSIZE);
69 * Construct RandomAccessInputStream from filename.
71 * @param file to read with random access.
72 * @param mode open mode.
73 * @exception IOException if an I/O error has occurred.
75 public RandomAccessInputStream(final String file, final String mode) throws IOException {
76 this(new RandomAccessFile(file, mode));
83 public final int available() throws IOException {
84 long available = length() - position();
85 if (available > Integer.MAX_VALUE) {
86 return Integer.MAX_VALUE;
88 return (int) available;
95 public final void close() throws IOException {
102 * @return length of file in byte.
103 * @exception IOException if an I/O error has occurred.
105 public final long length() throws IOException {
109 public final int getLength() throws IOException {
110 return (int) length();
115 * Get cursor position.
117 * @return position in byte.
118 * @exception IOException if an I/O error has occurred.
120 public final long position() throws IOException {
125 public final int getPos() throws IOException {
126 return (int) position();
133 public final synchronized void mark(final int markpos) {
141 public final boolean markSupported() {
149 public final synchronized int read() throws IOException {
150 int c = read(currentpos);
159 * Read one byte from specified position.
160 * This method does not modify this stream's position.
161 * If the given position is greater than the file's current size then no bytes are read and return -1.
162 * @param pos position to read.
163 * @return -1 when position is greater than the file's current size, otherwise byte value.
165 public int read(long pos) {
166 if (pos < startpos || pos > endpos) {
167 long blockstart = (pos/ bufsize) * bufsize;
172 } catch (IOException e) {
175 startpos = blockstart;
176 endpos = blockstart + n - 1;
177 if (pos < startpos || pos > endpos) {
181 return inbuf[(int) (pos - startpos)] & 0xff;
188 public final int read(final byte @NotNull [] buf, final int off, final int len) throws IOException {
191 int c = read(currentpos);
195 buf[off + idx++] = (byte) c;
203 * Read full data to byte buffer.
205 * @param buf buffer to store data.
206 * @exception IOException if an I/O error has occurred.
208 public final void readFully(final byte[] buf) throws IOException {
210 while (idx < buf.length) {
211 int c = read(currentpos);
213 throw new IOException();
215 buf[idx++] = (byte) c;
224 public final synchronized void reset() throws IOException {
229 * Seek file position.
231 * when specified position is beyond of end of the file, position is set to end of file.
233 * @param pos file position in byte.
234 * @exception IOException if an I/O error has occurred.
236 public final void seek(final long pos) throws IOException {
238 throw new IOException("seek position is less than 0");
240 currentpos = Math.min(pos, length());
245 * Skip n byte of input stream.
247 * when n is less than 0, it seek backward.
249 * @param n the number of bytes to be skipped.
250 * @return the actual number of bytes skipped.
251 * @throws IOException if the stream does not support seek, or if some other I/O error occurs.
254 public final long skip(final long n) throws IOException {
255 long previous = currentpos;
256 if (n < 0 && currentpos + n < 0) {
258 } else if (currentpos + n > length()) {
259 currentpos = length();
263 return currentpos - previous;