我目前正在嘗試創建一個將幾個ZipFile
合併成一個大的方法。因此我創建了一個輸出文件和一個列表InputStream
s的方法。Java - 確定一個ZipInputStream是否包含一個條目
這些InputStream
s後來轉換成ZipInputStream
s。這工作正常!
但是,當文件已被添加到存檔時,我遇到了麻煩。在這一點上,我需要覆蓋已添加的條目(InputStream
s具有較高索引(列表中較低)應覆蓋具有較低索引的流中的文件)。我也知道如何做到這一點:如果存檔需要覆蓋它,我只是不添加條目。 但問題是我如何檢查一個條目是否包含在ZipInputStream
中,這樣我可以跳過添加當前流的條目?
我迄今爲止代碼:
public static void makeNewZipFromInputStreamList(File outputFile,
ArrayList<InputStream> inputStreamList,
ArrayList<String> includeList, ArrayList<String> excludeList)
throws IOException, IllegalArgumentException {
final int sizeOfLists[] = new int[] { inputStreamList.size(),
includeList.size(), excludeList.size() };
if ((sizeOfLists[0] != sizeOfLists[1])
|| (sizeOfLists[0] != sizeOfLists[2])
|| (sizeOfLists[1] != sizeOfLists[2]))
throw new IllegalArgumentException(
"The ArrayLists do not have the same size ("
+ sizeOfLists[0] + ", " + sizeOfLists[1] + ", "
+ sizeOfLists[2] + ")");
final ZipOutputStream zipOutputFile = new ZipOutputStream(
new FileOutputStream(outputFile));
final int size = sizeOfLists[0];
InputStream inputStreamTempArray[] = inputStreamList
.toArray(new InputStream[size]);
String includeArray[] = includeList.toArray(new String[size]);
String excludeArray[] = excludeList.toArray(new String[size]);
int i, j;
ZipInputStream stream, streamTmp;
ZipInputStream inputStreamArray[] = new ZipInputStream[size];
String include, exclude, fileName;
ZipEntry entry;
for (i = 0; i < size; i++) {
inputStreamArray[i] = new ZipInputStream(inputStreamTempArray[i]);
if (includeArray[i] == null) {
includeArray[i] = "";
}
if (excludeArray[i] == null) {
excludeArray[i] = "";
}
}
for (i = 0; i < size; i++) {
while ((entry = inputStreamArray[i].getNextEntry()) != null) {
fileName = entry.getName();
for (j = i + 1; j < size; j++) {
// Check if the entry exists in the following archives (Then skip this entry)
}
if (fileName.matches(includeArray[i]) || !fileName.matches(excludeArray[i])) {
zipOutputFile.putNextEntry(entry);
if (!entry.isDirectory()) {
copyStream(inputStreamArray[i], zipOutputFile, false, false);
}
}
}
inputStreamArray[i].close();
}
zipOutputFile.close();
}
copyStream:
private static boolean copyStream(final InputStream is,
final OutputStream os, boolean closeInputStream,
boolean closeOutputStream) {
try {
final byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
if (closeInputStream) {
is.close();
}
if (closeOutputStream) {
os.close();
}
return true;
} catch (final IOException e) {
e.printStackTrace();
}
return false;
}
編輯:
我有想法,只是追加倒過來意思是從開始的條目列表的末尾,如果一個條目已經被放置,它會跳過。
當我這樣做,我得到一個非常奇怪的錯誤:
java.util.zip.ZipException: invalid entry compressed size (expected 1506 but got 1507 bytes)
at java.util.zip.ZipOutputStream.closeEntry(Unknown Source)
at java.util.zip.ZipOutputStream.putNextEntry(Unknown Source)
at io.brainstone.github.installer.FileUtils.makeNewZipFromInputStreamList(FileUtils.java:304)
at io.brainstone.github.installer.Main.startInstalling(Main.java:224)
at io.brainstone.github.installer.Window$3$1.run(Window.java:183)
這是我當前的代碼:
public static void makeNewZipFromInputStreamList(File outputFile,
ArrayList<InputStream> inputStreamList,
ArrayList<String> includeList, ArrayList<String> excludeList)
throws IOException, IllegalArgumentException {
final int sizeOfLists[] = new int[] { inputStreamList.size(),
includeList.size(), excludeList.size() };
if ((sizeOfLists[0] != sizeOfLists[1])
|| (sizeOfLists[0] != sizeOfLists[2])
|| (sizeOfLists[1] != sizeOfLists[2]))
throw new IllegalArgumentException(
"The ArrayLists do not have the same size ("
+ sizeOfLists[0] + ", " + sizeOfLists[1] + ", "
+ sizeOfLists[2] + ")");
final ZipOutputStream zipOutputFile = new ZipOutputStream(
new FileOutputStream(outputFile));
final int size = sizeOfLists[0];
final InputStream inputStreamTempArray[] = inputStreamList
.toArray(new InputStream[size]);
final String includeArray[] = includeList.toArray(new String[size]);
final String excludeArray[] = excludeList.toArray(new String[size]);
final ZipInputStream inputStreamArray[] = new ZipInputStream[size];
HashMap<String, Object[]> tmp;
int i, j;
String fileName;
ZipEntry entry;
for (i = size - 1; i >= 0; i--) {
System.out.println(i);
inputStreamArray[i] = new ZipInputStream(inputStreamTempArray[i]);
if (includeArray[i] == null) {
includeArray[i] = "";
}
if (excludeArray[i] == null) {
excludeArray[i] = "";
}
while ((entry = inputStreamArray[i].getNextEntry()) != null) {
fileName = entry.getName();
if (fileName.matches(includeArray[i])
|| !fileName.matches(excludeArray[i])) {
// Here is where I would check if a entry is already put.
// Probably just by catching the exception thrown in this
// case
zipOutputFile.putNextEntry(entry);
if (!entry.isDirectory()) {
copyStream(inputStreamArray[i], zipOutputFile, false,
false);
}
}
}
inputStreamArray[i].close();
}
zipOutputFile.close();
}
這個想法非常好!但是不能以這種方式實現,因爲在第一次迭代完畢後,您忘記了ZipInputStream已經結束了。你也忘了變量'i'不能在第二個for循環中使用。 – BrainStone
@YannickSchinko好吧,你有想法然後:)。出於清晰的原因,我儘可能簡潔地說明。 – yair
@YannickSchinko不用等一下,第二次迭代**不會超過'ZipInputStream',而是在地圖**上。 – yair