我目前正在尝试创建一种将几个ZipFile
s 合并为一个大的方法。因此,我创建了一个采用输出文件和InputStream
s 列表的方法。
这些InputStream
s 稍后被转换为ZipInputStream
s。这很好用!
但是当文件已经添加到存档中时,我遇到了麻烦。此时我需要覆盖已添加的条目(InputStream
具有较高索引(列表中较低)的 s 应该覆盖具有较低索引的流中的文件)。我也知道怎么做:如果存档需要覆盖它,我只是不添加条目。但问题是如何检查条目是否包含在 a 中,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();
}
复制流:
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();
}