0

ZipFile現在、複数の を 1 つの大きなものにマージするメソッドを作成しようとしています。したがって、出力ファイルとInputStreams のリストを受け取るメソッドを作成しました。

これら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();
    }
4

2 に答える 2

0

これを解決する最も簡単な方法は、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();
    }

でもとにかくありがとう!

于 2013-08-06T17:01:29.143 に答える