Skip to content

Commit f5d0579

Browse files
committed
Revert "'#2614: Remove BufferedRandomAccessFile, as it does not help here."
This reverts commit 2e7fe94.
1 parent 8f388f0 commit f5d0579

File tree

2 files changed

+199
-5
lines changed

2 files changed

+199
-5
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright 2015 The Apache Software Foundation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package iped.engine.io;
17+
18+
import java.io.File;
19+
import java.io.FileNotFoundException;
20+
import java.io.IOException;
21+
import java.io.RandomAccessFile;
22+
23+
/**
24+
* This class is a version of the one published at
25+
* https://code.google.com/p/jmzreader/wiki/BufferedRandomAccessFile augmented
26+
* to handle unsigned bytes. The original class is published under Apache 2.0
27+
* license. Fix is marked below
28+
*
29+
* This is an optimized version of the RandomAccessFile class as described by
30+
* Nick Zhang on JavaWorld.com. The article can be found at
31+
* http://www.javaworld.com/javaworld/javatips/jw-javatip26.html
32+
*
33+
* @author jg
34+
*/
35+
public class BufferedRandomAccessFile extends RandomAccessFile {
36+
/**
37+
* Uses a byte instead of a char buffer for efficiency reasons.
38+
*/
39+
private final byte[] buffer;
40+
private int bufend = 0;
41+
private int bufpos = 0;
42+
43+
/**
44+
* The position inside the actual file.
45+
*/
46+
private long realpos = 0;
47+
48+
/**
49+
* Creates a new instance of the BufferedRandomAccessFile.
50+
*
51+
* @param filename
52+
* The path of the file to open.
53+
* @param mode
54+
* Specifies the mode to use ("r", "rw", etc.) See the
55+
* BufferedLineReader documentation for more information.
56+
* @param bufsize
57+
* The buffer size (in bytes) to use.
58+
* @throws FileNotFoundException
59+
* If the mode is "r" but the given string does not denote an
60+
* existing regular file, or if the mode begins with "rw" but the
61+
* given string does not denote an existing, writable regular file
62+
* and a new regular file of that name cannot be created, or if some
63+
* other error occurs while opening or creating the file.
64+
*/
65+
public BufferedRandomAccessFile(String filename, String mode, int bufsize) throws FileNotFoundException {
66+
super(filename, mode);
67+
buffer = new byte[bufsize];
68+
}
69+
70+
/**
71+
* Creates a new instance of the BufferedRandomAccessFile.
72+
*
73+
* @param file
74+
* The file to open.
75+
* @param mode
76+
* Specifies the mode to use ("r", "rw", etc.) See the
77+
* BufferedLineReader documentation for more information.
78+
* @param bufsize
79+
* The buffer size (in bytes) to use.
80+
* @throws FileNotFoundException
81+
* If the mode is "r" but the given file path does not denote an
82+
* existing regular file, or if the mode begins with "rw" but the
83+
* given file path does not denote an existing, writable regular
84+
* file and a new regular file of that name cannot be created, or if
85+
* some other error occurs while opening or creating the file.
86+
*/
87+
public BufferedRandomAccessFile(File file, String mode, int bufsize) throws FileNotFoundException {
88+
super(file, mode);
89+
buffer = new byte[bufsize];
90+
}
91+
92+
/**
93+
* {@inheritDoc}
94+
*/
95+
@Override
96+
public final int read() throws IOException {
97+
if (bufpos >= bufend && fillBuffer() < 0) {
98+
return -1;
99+
}
100+
if (bufend == 0) {
101+
return -1;
102+
}
103+
// FIX to handle unsigned bytes
104+
return (buffer[bufpos++] + 256) & 0xFF;
105+
// End of fix
106+
}
107+
108+
/**
109+
* Reads as much bytes as possible into the internal buffer.
110+
*
111+
* @return The total number of bytes read into the buffer, or -1 if there is no
112+
* more data because the end of the file has been reached.
113+
* @throws IOException
114+
* If the first byte cannot be read for any reason other than end of
115+
* file, or if the random access file has been closed, or if some
116+
* other I/O error occurs.
117+
*/
118+
private int fillBuffer() throws IOException {
119+
int n = super.read(buffer);
120+
121+
if (n >= 0) {
122+
realpos += n;
123+
bufend = n;
124+
bufpos = 0;
125+
}
126+
return n;
127+
}
128+
129+
/**
130+
* Clears the local buffer.
131+
*
132+
* @throws IOException
133+
* If an I/O error occurs.
134+
*/
135+
private void invalidate() throws IOException {
136+
bufend = 0;
137+
bufpos = 0;
138+
realpos = super.getFilePointer();
139+
}
140+
141+
/**
142+
* {@inheritDoc}
143+
*/
144+
@Override
145+
public int read(byte[] b, int off, int len) throws IOException {
146+
int curLen = len; // length of what is left to read (shrinks)
147+
int curOff = off; // offset where to put read data (grows)
148+
int totalRead = 0;
149+
150+
while (true) {
151+
int leftover = bufend - bufpos;
152+
if (curLen <= leftover) {
153+
System.arraycopy(buffer, bufpos, b, curOff, curLen);
154+
bufpos += curLen;
155+
return totalRead + curLen;
156+
}
157+
// curLen > leftover, we need to read more than what remains in buffer
158+
System.arraycopy(buffer, bufpos, b, curOff, leftover);
159+
totalRead += leftover;
160+
bufpos += leftover;
161+
if (fillBuffer() > 0) {
162+
curOff += leftover;
163+
curLen -= leftover;
164+
} else {
165+
if (totalRead == 0) {
166+
return -1;
167+
}
168+
return totalRead;
169+
}
170+
}
171+
}
172+
173+
/**
174+
* {@inheritDoc}
175+
*/
176+
@Override
177+
public long getFilePointer() throws IOException {
178+
return realpos - bufend + bufpos;
179+
}
180+
181+
/**
182+
* {@inheritDoc}
183+
*/
184+
@Override
185+
public void seek(long pos) throws IOException {
186+
long n = realpos - pos;
187+
if (n >= 0 && n <= bufend) {
188+
bufpos = bufend - (int) n;
189+
} else {
190+
super.seek(pos);
191+
invalidate();
192+
}
193+
}
194+
}
195+

iped-engine/src/main/java/iped/engine/io/ZIPInputStreamFactory.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import java.io.IOException;
77
import java.io.InputStream;
88
import java.io.OutputStream;
9-
import java.io.RandomAccessFile;
109
import java.nio.channels.ClosedChannelException;
1110
import java.nio.channels.SeekableByteChannel;
1211
import java.nio.charset.StandardCharsets;
@@ -107,15 +106,15 @@ private synchronized void init() throws IOException {
107106
while (true) {
108107
File segment = new File(file.getParentFile(), namePrefix + ".z" + String.format("%02d", ++num));
109108
if (segment.exists()) {
110-
RandomAccessFile raf = new RandomAccessFile(segment, "r");
111-
channels.add(new ReadOnlyRAFSeekableByteChannel(raf));
109+
BufferedRandomAccessFile braf = new BufferedRandomAccessFile(segment, "r", UFDR_BUF_SIZE);
110+
channels.add(new ReadOnlyRAFSeekableByteChannel(braf));
112111
} else {
113112
break;
114113
}
115114
}
116115
// main ufdr should be the last one
117-
RandomAccessFile raf = new RandomAccessFile(file, "r");
118-
channels.add(new ReadOnlyRAFSeekableByteChannel(raf));
116+
BufferedRandomAccessFile braf = new BufferedRandomAccessFile(file, "r", UFDR_BUF_SIZE);
117+
channels.add(new ReadOnlyRAFSeekableByteChannel(braf));
119118

120119
if (channels.size() == 1) {
121120
sbc = channels.get(0);

0 commit comments

Comments
 (0)