|
15 | 15 |
|
16 | 16 | import static dev.zarr.zarrjava.utils.ZipUtils.getZipCommentFromBuffer; |
17 | 17 |
|
| 18 | + |
| 19 | +/** A Store implementation that provides read-only access to a zip archive stored in an underlying Store. |
| 20 | + * Compared to BufferedZipStore, this implementation reads directly from the zip archive without parsing |
| 21 | + * its contents into a buffer store first making it more efficient for read-only access to large zip archives. |
| 22 | + */ |
18 | 23 | public class ReadOnlyZipStore implements Store, Store.ListableStore { |
19 | 24 |
|
20 | 25 | private final StoreHandle underlyingStore; |
@@ -69,21 +74,24 @@ public ByteBuffer get(String[] keys, long start, long end) { |
69 | 74 | try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new ByteBufferBackedInputStream(buffer))) { |
70 | 75 | ZipArchiveEntry entry; |
71 | 76 | while ((entry = zis.getNextEntry()) != null) { |
72 | | - if (entry.isDirectory() || !entry.getName().equals(resolveKeys(keys))) { |
73 | | - continue; |
74 | | - } |
75 | | - ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
76 | | - if (end == -1) { |
77 | | - end = entry.getSize(); |
| 77 | + String entryName = entry.getName(); |
| 78 | + |
| 79 | + if (entryName.startsWith("/")) { |
| 80 | + entryName = entryName.substring(1); |
78 | 81 | } |
79 | | - if (start > end) { |
80 | | - throw new IllegalArgumentException("Start position can not be larger than end position. Got start=" + start + ", end=" + end); |
| 82 | + if (entry.isDirectory() || !entryName.equals(resolveKeys(keys))) { |
| 83 | + continue; |
81 | 84 | } |
82 | | - if (start < 0 || end > entry.getSize()) { |
83 | | - throw new IllegalArgumentException("Start and end positions must be within the bounds of the zip entry size. Entry size=" + entry.getSize() + ", got start=" + start + ", end=" + end); |
| 85 | + |
| 86 | + if (zis.skip(start) != start) { |
| 87 | + throw new IOException("Failed to skip to start position " + start + " in zip entry " + entryName); |
84 | 88 | } |
85 | | - zis.skip(start); |
86 | | - long bytesToRead = end - start; |
| 89 | + |
| 90 | + long bytesToRead; |
| 91 | + if (end != -1) bytesToRead = end - start; |
| 92 | + else bytesToRead = Long.MAX_VALUE; |
| 93 | + |
| 94 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
87 | 95 | byte[] bufferArray = new byte[8192]; |
88 | 96 | int len; |
89 | 97 | while (bytesToRead > 0 && (len = zis.read(bufferArray, 0, (int) Math.min(bufferArray.length, bytesToRead))) != -1) { |
@@ -144,11 +152,15 @@ public Stream<String[]> list(String[] keys) { |
144 | 152 | ZipArchiveEntry entry; |
145 | 153 | String prefix = resolveKeys(keys); |
146 | 154 | while ((entry = zis.getNextEntry()) != null) { |
147 | | - String entryKey = entry.getName(); |
148 | | - if (!entryKey.startsWith(prefix) || entryKey.equals(prefix)) { |
| 155 | + String entryName = entry.getName(); |
| 156 | + if (entryName.startsWith("/")) { |
| 157 | + entryName = entryName.substring(1); |
| 158 | + } |
| 159 | + |
| 160 | + if (!entryName.startsWith(prefix) || entryName.equals(prefix)) { |
149 | 161 | continue; |
150 | 162 | } |
151 | | - String[] entryKeys = resolveEntryKeys(entryKey.substring(prefix.length())); |
| 163 | + String[] entryKeys = resolveEntryKeys(entryName.substring(prefix.length())); |
152 | 164 | builder.add(entryKeys); |
153 | 165 | } |
154 | 166 | } catch (IOException e) { |
|
0 commit comments