ZipFile
現在、複数の を 1 つの大きなものにマージするメソッドを作成しようとしています。したがって、出力ファイルとInputStream
s のリストを受け取るメソッドを作成しました。
これらInputStream
の は後で に変換されZipInputStream
ます。それはうまくいきます!
しかし、ファイルが既にアーカイブに追加されていると問題が発生します。この時点で、既に追加されているエントリをオーバーライドする必要があります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();
}
コピーストリーム:
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();
}