[英]Java - Determine if a ZipInputStream contains a Entry
I'm currently trying to create a method that merges several ZipFile
s into one big. 我目前正在尝试创建一种将多个
ZipFile
合并为一个大的方法。 Therefore I created a method that takes a output file and a list of InputStream
s. 因此,我创建了一个采用输出文件和
InputStream
列表的方法。
These InputStream
s are later transformed into ZipInputStream
s. 这些
InputStream
稍后将转换为ZipInputStream
。 That works fine! 很好!
But I have trouble when a file has already been added to the archive. 但是当文件已经添加到存档中时,我遇到了麻烦。 At this point I need to override the entry already added (
InputStream
s with a higher index (lower in the list) should override the files from streams with a lower index). 在这一点上,我需要覆盖已经添加的条目(具有较高索引(列表中较低)的
InputStream
应当覆盖具有较低索引的流中的文件)。 I also know how to do that: I just do not add the entry if a archive that would need to override it. 我也知道该怎么做:如果需要覆盖它,我只是不添加该条目。 But the problem is how could I check if a entry is contained in a
ZipInputStream
so I can skip the addition of the entry for the current stream? 但是问题是如何检查
ZipInputStream
是否包含条目,以便可以跳过当前流的条目添加?
My code so far: 到目前为止,我的代码:
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: 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;
}
EDIT: 编辑:
I had the idea to just append the entries the other way round meaning starting from the end of the list and if a entry is already put it is just going to skip. 我有一个想法,就是以相反的方式附加条目,即从列表的末尾开始,如果条目已经放置,则将跳过该条目。
When I'm doing this I get a really weird error: 当我这样做时,我会收到一个非常奇怪的错误:
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)
This is my current code: 这是我当前的代码:
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();
}
fileName
to entry
. fileName
到entry
的映射。 Iterate over the map's entries and put them to zipOutputFile
. 遍历地图的条目,并将其放入
zipOutputFile
。
// (1) here all entries will be stored, overriding low-indexed with high-indexed final Map<String, ZipEntry> fileNameToZipEntry = new HashMap<String, ZipEntry>(); // (2) Iterate over all entries and store in map, overriding low-indexed for (i = 0; i < size; i++) { while ((entry = inputStreamArray[i].getNextEntry()) != null) { fileName = entry.getName(); fileNameToZipEntry.put(fileName, entry); } inputStreamArray[i].close(); } // (3) Iterating the map that holds only the entries required for zipOutputFile int j = 0; for ( Set<Map.Entry<String, ZipEntry>> mapEntry : fileNameToZipEntry.entrySet() ) { if (fileName.matches(includeArray[j]) || !fileName.matches(excludeArray[j])) { zipOutputFile.putNextEntry(entry); if (!entry.isDirectory()) { copyStream(inputStreamArray[j], zipOutputFile, false, false); } } j++; }
The simplest way to solve this is iterating backwards through the ArrayLists. 解决此问题的最简单方法是向后遍历ArrayList。
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--) {
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])) {
try {
zipOutputFile.putNextEntry(entry);
if (!entry.isDirectory()) {
copyStream(inputStreamArray[i], zipOutputFile,
false, false);
}
} catch (ZipException ex) {
if (!ex.getMessage()
.matches("duplicate entry: .*\\..*")) {
throw new RuntimeException(
"Unexpected " + ex.getClass() + " (\""
+ ex.getMessage()
+ "\")\n(only duplicate entry execptions are expected!)",
ex);
}
}
}
}
inputStreamArray[i].close();
}
zipOutputFile.close();
}
But thank you anyways! 但是还是谢谢你!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.