Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

148
LINES

< > BotCompany Repo | #1034354 // Zip4j_CopySubSetOfZipFile_workingBackup

JavaX fragment (include) [tags: use-pretranspiled]

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  
}

Author comment

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: 104 / 167
Version history: 5 change(s)
Referenced in: [show references]