3

より多くのフォルダーを含むフォルダーと、画像とオーディオファイルを含む各フォルダーを読み取るために、Java(Androidアプリの場合)でアルゴリズムを作成する必要があるため、構造は次のようになります。mainDir/categorySubfolder/myFile1.jpg

私の問題は、アーカイブのサイズを16 MBに制限し、実行時に、メインmainDirフォルダーのすべてのファイルを含めるために必要な数のアーカイブを作成する必要があることです。

ネットからいくつかの例を試し、Javaのドキュメントを読みましたが、必要な方法ですべてを理解してまとめることができません。誰かが以前にこれをしたことがありますか、それとも私のためのリンクや例がありますか?

再帰的な方法でファイルの読み取りを解決しましたが、zip作成のロジックを記述できません。

私は提案やより良い実例を受け入れています。

4

3 に答える 3

7

zip4jは、マルチパートzipファイルを作成できる優れたライブラリです。

net.lingala.zip4j.core.ZipFile zipFile = new ZipFile("out.zip");
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
zipFile.createZipFileFromFolder("path/to/source/dir", parameters, true, maximum size);

あなたは彼らのウェブサイトでより多くの例を見つけることができます。

于 2014-09-16T23:22:09.957 に答える
2

以下のコード/クラスを使用して、大量/サイズのファイルを分割して圧縮しています。私はこのクラスを以下でテストしました

  • 非圧縮ファイルの数:116
  • 合計サイズ(非圧縮):29.1 GB
  • ZIPファイルのサイズ制限(それぞれ):3 GB [MAX_ZIP_SIZE]
  • 合計サイズ(圧縮):7.85 GB
  • ZIPファイルの数(MAX_ZIP_SIZEとして指定):3

MAX_ZIP_SIZEの値を16(MB)1024 1024 = 16777216-22(zipヘッダーサイズ)= 16777194に変更する必要があります。
私のコードでは、MAX_ZIP_SIZEを3 GBに設定しています(ZIPにはさまざまな点で4 GBの制限があります)。

最終的な長いMAX_ZIP_SIZE=3221225472L; // 3 GB

package com.company;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class QdeZip {

    public static String createZIP(String directoryPath, String zipFileName, String filesToZip) {
        try {
            final int BUFFER = 104857600; // 100MB
            final long MAX_ZIP_SIZE = 3221225472L; //3 GB
            long currentSize = 0;
            int zipSplitCount = 0;
            String files[] = filesToZip.split(",");
            if (!directoryPath.endsWith("/")) {
                directoryPath = directoryPath + "/";
            }
            byte fileRAW[] = new byte[BUFFER];
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toUpperCase()));
            ZipEntry zipEntry;
            FileInputStream entryFile;
            for (String aFile : files) {
                zipEntry = new ZipEntry(aFile);
                if (currentSize >= MAX_ZIP_SIZE) {
                    zipSplitCount++;
                    //zipOut.closeEntry();
                    zipOut.close();
                    zipOut = new ZipOutputStream(new FileOutputStream(directoryPath + zipFileName.toLowerCase().replace(".zip", "_" + zipSplitCount + ".zip").toUpperCase()));
                    currentSize = 0;
                }
                zipOut.putNextEntry(zipEntry);
                entryFile = new FileInputStream(directoryPath + aFile);

                int count;
                while ((count = entryFile.read(fileRAW, 0, BUFFER)) != -1) {
                    zipOut.write(fileRAW, 0, count);

                    //System.out.println("number of Bytes read = " + count);
                }
                entryFile.close();
                zipOut.closeEntry();
                currentSize += zipEntry.getCompressedSize();
            }

            zipOut.close();
            //System.out.println(directory + " -" + zipFileName + " -Number of Files = " + files.length);
        } catch (FileNotFoundException e) {
            return "FileNotFoundException = " + e.getMessage();
        } catch (IOException e) {
            return "IOException = " + e.getMessage();
        } catch (Exception e) {
            return "Exception = " + e.getMessage();
        }

        return "1";
    }
}

私はそれを処理するためにすべての例外メッセージを文字列として返しました。これはプロジェクトに関連する私自身のケースです。

于 2017-11-06T11:01:29.397 に答える
0

私が見る限り、巨大なzipファイルを複数のボリュームに分割する方法は?これまでのアーカイブサイズを追跡することを提案しているだけで、任意の値(最大値よりも小さい値)に近づくと、新しいファイルを開始することを決定します。したがって、16MBの制限の場合、値を10MBに設定し、これに達するたびに新しいzipを開始できますが、9MBに達し、次のファイルが8MBに圧縮されると、制限よりも大きいzipになります。

その投稿で与えられたコードは、1)ZipEntryが作成される前にサイズを取得したため、常に0であり、2)zipを書き出さなかったために機能しなかったようです:-)それを間違えました-私に知らせてください。

以下は私のために働きます。簡単にするために、ラッパーから取り出して、すべてmain(String args [])に入れました。このコードを改善できる方法はたくさんあります:-)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ChunkedZipTwo {

    static final long MAX_LIMIT = 10 * 1000 * 1024; //10MB limit - hopefully this 

    public static void main(String[] args) throws Exception {
        String[] files = {"file1", "file2", "file3"};
        int i = 0;
        boolean needNewFile = false;
        long overallSize = 0;
        ZipOutputStream out = getOutputStream(i);
        byte[] buffer = new byte[1024];

        for (String thisFileName : files) {
            if (overallSize > MAX_LIMIT) {
                out.close();
                i++;
                out = getOutputStream(i);
                overallSize = 0;
            }

            FileInputStream in = new FileInputStream(thisFileName);
            ZipEntry ze = new ZipEntry(thisFileName);
            out.putNextEntry(ze);
            int len;
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            out.closeEntry();
            in.close();
            overallSize += ze.getCompressedSize();
        }
        out.close();
    }

    public static ZipOutputStream getOutputStream(int i) throws IOException {
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream("bigfile" + i + ".zip"));
        out.setLevel(Deflater.DEFAULT_COMPRESSION);
        return out;
    }
}   
于 2012-06-20T12:38:17.200 に答える