Allow ZipPackIndex to work with any byte channel
This commit is contained in:
parent
0ecee529d7
commit
f1492cc829
|
|
@ -13,7 +13,9 @@ import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
@ -106,8 +108,16 @@ public class ZipPackIndex {
|
||||||
this.root = buildTree();
|
this.root = buildTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SeekableByteChannel obtainChannel(Path filePath) throws IOException {
|
||||||
|
try {
|
||||||
|
return FileChannel.open(filePath, StandardOpenOption.READ);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Files.newByteChannel(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ByteBuffer readCentralDirectory(Path filePath) throws IOException {
|
private static ByteBuffer readCentralDirectory(Path filePath) throws IOException {
|
||||||
try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ)) {
|
try (SeekableByteChannel channel = obtainChannel(filePath)) {
|
||||||
long fileSize = channel.size();
|
long fileSize = channel.size();
|
||||||
if (fileSize < EOCD_SIZE) return null;
|
if (fileSize < EOCD_SIZE) return null;
|
||||||
|
|
||||||
|
|
@ -117,7 +127,8 @@ public class ZipPackIndex {
|
||||||
|
|
||||||
long tailStart = fileSize - tailSize;
|
long tailStart = fileSize - tailSize;
|
||||||
while (tail.hasRemaining()) {
|
while (tail.hasRemaining()) {
|
||||||
int n = channel.read(tail, tailStart + tail.position());
|
channel.position(tailStart + tail.position());
|
||||||
|
int n = channel.read(tail);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -151,19 +162,22 @@ public class ZipPackIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try memory-mapping first; fall back to a heap copy if the OS refuses.
|
// Try memory-mapping first; fall back to a heap copy if the OS refuses.
|
||||||
try {
|
if (channel instanceof FileChannel fc) {
|
||||||
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, cdOffset, cdSize);
|
try {
|
||||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, cdOffset, cdSize);
|
||||||
return buf;
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
} catch (Exception ignored) {
|
return buf;
|
||||||
// mmap unavailable (e.g. some Linux mount flags, container restrictions);
|
} catch (Exception ignored) {
|
||||||
// read the central directory into a heap buffer instead.
|
// mmap unavailable (e.g. some Linux mount flags, container restrictions);
|
||||||
|
// read the central directory into a heap buffer instead.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.allocate((int) cdSize);
|
ByteBuffer buf = ByteBuffer.allocate((int) cdSize);
|
||||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
while (buf.hasRemaining()) {
|
while (buf.hasRemaining()) {
|
||||||
int n = channel.read(buf, cdOffset + buf.position());
|
channel.position(cdOffset + buf.position());
|
||||||
|
int n = channel.read(buf);
|
||||||
if (n < 0) throw new IOException("Truncated central directory during heap read");
|
if (n < 0) throw new IOException("Truncated central directory during heap read");
|
||||||
}
|
}
|
||||||
buf.flip();
|
buf.flip();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user