Uses 204K of libraries. Click here for Pure Java version (5541L/31K).
1 | // bit slow but works |
2 | |
3 | !include once #1034352 // zip4j |
4 | |
5 | import java.nio.charset.Charset; |
6 | |
7 | srecord noeq Zip4j_CopySubSetOfZipFile_workingBackup(File zipIn, File zipOut, IPred<S> fileFilter) { |
8 | delegate ProgressMonitor to net.lingala.zip4j.progress. |
9 | |
10 | ZipModel zipModel; |
11 | new HeaderWriter headerWriter; |
12 | new ProgressMonitor progressMonitor; |
13 | int bufferSize = InternalZipConstants.BUFF_SIZE; |
14 | Charset charset; |
15 | |
16 | run { |
17 | try (var randomAccessFile = new RandomAccessFile(zipIn, RandomAccessFileMode.READ.getValue())) { |
18 | zipModel = new HeaderReader().readAllHeaders(randomAccessFile, buildConfig()); |
19 | zipModel.setZipFile(zipIn); |
20 | } |
21 | |
22 | temp outputStream = new SplitOutputStream(zipOut); |
23 | temp inputStream = new RandomAccessFile(zipModel.getZipFile(), RandomAccessFileMode.READ.getValue()); |
24 | |
25 | long currentFileCopyPointer = 0; |
26 | L<FileHeader> sortedFileHeaders = sortedByComparator(zipModel.getCentralDirectory().getFileHeaders(), (o1, o2) -> { |
27 | if (eq(o1.getFileName(), o2.getFileName())) ret 0; |
28 | ret cmp(o1.getOffsetLocalHeader(), o2.getOffsetLocalHeader()); |
29 | }); |
30 | |
31 | int count = 0; |
32 | for (fileHeader : sortedFileHeaders) { |
33 | long fpIn = inputStream.getFilePointer(); |
34 | long fp = outputStream.getFilePointer(); |
35 | long lengthOfCurrentEntry = getOffsetOfNextEntry(sortedFileHeaders, fileHeader, zipModel) - fp; |
36 | bool shouldCopy = fileFilter.get(fileHeader.getFileName()); |
37 | if (count++ < 10) |
38 | printVars(+fpIn, +fp, +lengthOfCurrentEntry, +shouldCopy); |
39 | if (!shouldCopy) { |
40 | updateHeaders(sortedFileHeaders, fileHeader, lengthOfCurrentEntry); |
41 | |
42 | if (!zipModel.getCentralDirectory().getFileHeaders().remove(fileHeader)) { |
43 | throw new ZipException("Could not remove entry from list of central directory headers"); |
44 | } |
45 | |
46 | currentFileCopyPointer += lengthOfCurrentEntry; |
47 | } else { |
48 | // copy complete entry without any changes |
49 | currentFileCopyPointer += copyFile(inputStream, outputStream, |
50 | currentFileCopyPointer, |
51 | lengthOfCurrentEntry, progressMonitor, |
52 | buildConfig().getBufferSize()); |
53 | } |
54 | } |
55 | |
56 | headerWriter.finalizeZipFile(zipModel, outputStream, buildConfig().getCharset()); |
57 | } |
58 | |
59 | long getOffsetOfNextEntry(L<FileHeader> sortedFileHeaders, |
60 | FileHeader fileHeader, ZipModel zipModel) throws ZipException { |
61 | int indexOfFileHeader = getIndexOfFileHeader(sortedFileHeaders, fileHeader); |
62 | |
63 | if (indexOfFileHeader == sortedFileHeaders.size() - 1) |
64 | ret HeaderUtil.getOffsetStartOfCentralDirectory(zipModel); |
65 | else |
66 | ret sortedFileHeaders.get(indexOfFileHeader + 1).getOffsetLocalHeader(); |
67 | } |
68 | |
69 | long copyFile(RandomAccessFile randomAccessFile, |
70 | OutputStream outputStream, long start, long length, |
71 | ProgressMonitor progressMonitor, int bufferSize) throws IOException { |
72 | net.lingala.zip4j.util.FileUtils.copyFile(randomAccessFile, outputStream, start, start + length, progressMonitor, bufferSize); |
73 | ret length; |
74 | } |
75 | |
76 | private void updateHeaders(List<FileHeader> sortedFileHeaders, FileHeader fileHeaderThatWasRemoved, |
77 | long offsetToSubtract) throws ZipException { |
78 | updateOffsetsForAllSubsequentFileHeaders(sortedFileHeaders, zipModel, fileHeaderThatWasRemoved, negate(offsetToSubtract)); |
79 | |
80 | EndOfCentralDirectoryRecord endOfCentralDirectoryRecord = zipModel.getEndOfCentralDirectoryRecord(); |
81 | endOfCentralDirectoryRecord.setOffsetOfStartOfCentralDirectory( |
82 | endOfCentralDirectoryRecord.getOffsetOfStartOfCentralDirectory() - offsetToSubtract); |
83 | endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectory( |
84 | endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectory() - 1); |
85 | |
86 | if (endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectoryOnThisDisk() > 0) { |
87 | endOfCentralDirectoryRecord.setTotalNumberOfEntriesInCentralDirectoryOnThisDisk( |
88 | endOfCentralDirectoryRecord.getTotalNumberOfEntriesInCentralDirectoryOnThisDisk() - 1); |
89 | } |
90 | |
91 | if (zipModel.isZip64Format()) { |
92 | zipModel.getZip64EndOfCentralDirectoryRecord().setOffsetStartCentralDirectoryWRTStartDiskNumber( |
93 | zipModel.getZip64EndOfCentralDirectoryRecord().getOffsetStartCentralDirectoryWRTStartDiskNumber() - offsetToSubtract); |
94 | |
95 | zipModel.getZip64EndOfCentralDirectoryRecord().setTotalNumberOfEntriesInCentralDirectoryOnThisDisk( |
96 | zipModel.getZip64EndOfCentralDirectoryRecord().getTotalNumberOfEntriesInCentralDirectory() - 1); |
97 | |
98 | zipModel.getZip64EndOfCentralDirectoryLocator().setOffsetZip64EndOfCentralDirectoryRecord( |
99 | zipModel.getZip64EndOfCentralDirectoryLocator().getOffsetZip64EndOfCentralDirectoryRecord() - offsetToSubtract); |
100 | } |
101 | } |
102 | |
103 | private long negate(long val) { |
104 | if (val == Long.MIN_VALUE) { |
105 | throw new ArithmeticException("long overflow"); |
106 | } |
107 | |
108 | return -val; |
109 | } |
110 | |
111 | Zip4jConfig buildConfig() { |
112 | return new Zip4jConfig(charset, bufferSize); |
113 | } |
114 | |
115 | int getIndexOfFileHeader(List<FileHeader> allFileHeaders, FileHeader fileHeaderForIndex) throws ZipException { |
116 | for (int i = 0; i < allFileHeaders.size(); i++) { |
117 | FileHeader fileHeader = allFileHeaders.get(i); |
118 | if (fileHeader.equals(fileHeaderForIndex)) { |
119 | return i; |
120 | } |
121 | } |
122 | |
123 | throw new ZipException("Could not find file header in list of central directory file headers"); |
124 | } |
125 | |
126 | void updateOffsetsForAllSubsequentFileHeaders(List<FileHeader> sortedFileHeaders, ZipModel zipModel, |
127 | FileHeader fileHeaderModified, long offsetToAdd) throws ZipException { |
128 | int indexOfFileHeader = getIndexOfFileHeader(sortedFileHeaders, fileHeaderModified); |
129 | |
130 | if (indexOfFileHeader == -1) { |
131 | throw new ZipException("Could not locate modified file header in zipModel"); |
132 | } |
133 | |
134 | for (int i = indexOfFileHeader + 1; i < sortedFileHeaders.size(); i++) { |
135 | FileHeader fileHeaderToUpdate = sortedFileHeaders.get(i); |
136 | fileHeaderToUpdate.setOffsetLocalHeader(fileHeaderToUpdate.getOffsetLocalHeader() + offsetToAdd); |
137 | |
138 | if (zipModel.isZip64Format() |
139 | && fileHeaderToUpdate.getZip64ExtendedInfo() != null |
140 | && fileHeaderToUpdate.getZip64ExtendedInfo().getOffsetLocalHeader() != -1) { |
141 | |
142 | fileHeaderToUpdate.getZip64ExtendedInfo().setOffsetLocalHeader( |
143 | fileHeaderToUpdate.getZip64ExtendedInfo().getOffsetLocalHeader() + offsetToAdd |
144 | ); |
145 | } |
146 | } |
147 | } |
148 | } |
Began life as a copy of #1034351
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1034354 |
Snippet name: | Zip4j_CopySubSetOfZipFile_workingBackup |
Eternal ID of this version: | #1034354/6 |
Text MD5: | f2d6f6e9bb0c5f6b1ed32f80e55cf9c6 |
Transpilation MD5: | 71ad3912e50c9f4528d47a28aa27c420 |
Author: | stefan |
Category: | javax / io |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-02-03 06:02:21 |
Source code size: | 6575 bytes / 148 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 171 / 258 |
Version history: | 5 change(s) |
Referenced in: | [show references] |