如何在Java中解压缩分割卷zip?

时间:2011-11-14 01:47:12

标签: java zip

我需要重新组装一个100个部分的zip文件并提取内容。我尝试在输入流中简单地将zip卷连接在一起,但这不起作用。任何建议将不胜感激。

感谢。

3 个答案:

答案 0 :(得分:6)

以下是您可以从中开始的代码。它从多卷zip存档中提取单个文件条目:

package org.test.zip;

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class Main {

    public static void main(String[] args) throws IOException {
        ZipInputStream is = new ZipInputStream(new SequenceInputStream(Collections.enumeration(
            Arrays.asList(new FileInputStream("test.zip.001"), new FileInputStream("test.zip.002"), new FileInputStream("test.zip.003")))));
        try {
            for(ZipEntry entry = null; (entry = is.getNextEntry()) != null; ) {
                OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()));
                try {
                    final int bufferSize = 1024;
                    byte[] buffer = new byte[bufferSize];
                    for(int readBytes = -1; (readBytes = is.read(buffer, 0, bufferSize)) > -1; ) {
                        os.write(buffer, 0, readBytes);
                    }
                    os.flush();
                } finally {
                    os.close();
                }
            }
        } finally {
            is.close();
        }
    }
}

答案 1 :(得分:5)

只是为了让它更具动感 - 100%基于下面的mijer代码。

    private void CombineFiles (String[] files) throws FileNotFoundException, IOException {
    Vector<FileInputStream> v = new Vector<FileInputStream>(files.length);
    for (int x = 0; x < files.length; x++)
        v.add(new FileInputStream(inputDirectory + files[x]));

    Enumeration<FileInputStream> e = v.elements();

    SequenceInputStream sequenceInputStream = new SequenceInputStream(e);

    ZipInputStream is = new ZipInputStream(sequenceInputStream);
    try {
        for (ZipEntry entry = null; (entry = is.getNextEntry()) != null;) {
            OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()));
            try {
                final int bufferSize = 1024;
                byte[] buffer = new byte[bufferSize];
                for (int readBytes = -1; (readBytes = is.read(buffer, 0, bufferSize)) > -1;) {
                    os.write(buffer, 0, readBytes);
                }
                os.flush();
            } finally {
                os.close();
            }
        }
    } finally {
        is.close();
    }

}

答案 2 :(得分:0)

仅连接段数据对我不起作用。在这种情况下,这些段是使用Linux命令行zip(InfoZip 3.0版)创建的:

> zip -s 5m data.zip -r data/

已创建名为data.z01, data.z02, ..., data.zip的细分文件。

第一段data.z01包含跨度签名0x08074b50,如PKWARE的Zip文件格式规范中所述。这4个字节的存在使Java ZipInputStream忽略了存档中的所有条目。与非拆分存档相比,最后一个分区中的中央注册表还包含额外的分区信息,但不会导致ZipInputStream出现任何问题。

我要做的就是跳过生成签名。以下代码将从用zip -s进行了分段的存档中提取条目,并从Linux split逗号分割成的zip文件中提取条目,如下所示:split -d -b 5M data.zip data.zip.。该代码基于szhem。

public class ZipCat {
    private final static byte[] SPANNING_SIGNATURE = {0x50, 0x4b, 0x07, 0x08};

    public static void main(String[] args) throws IOException {
        List<InputStream> asList = new ArrayList<>();            
        byte[] buf4 = new byte[4];
        PushbackInputStream pis = new PushbackInputStream(new FileInputStream(args[0]), buf4.length);
        asList.add(pis);
        if (pis.read(buf4) != buf4.length) {
            throw new IOException(args[0] + " is too small for a zip file/segment");
        }
        if (!Arrays.equals(buf4, SPANNING_SIGNATURE)) {
            pis.unread(buf4, 0, buf4.length);
        }
        for (int i = 1; i < args.length; i++) {
            asList.add(new FileInputStream(args[i]));
        }

        try (ZipInputStream is = new ZipInputStream(new SequenceInputStream(Collections.enumeration(asList)))) {
            for (ZipEntry entry = null; (entry = is.getNextEntry()) != null;) {
                if (entry.isDirectory()) {
                    new File(entry.getName()).mkdirs();
                } else {
                    try (OutputStream os = new BufferedOutputStream(new FileOutputStream(entry.getName()))) {
                        byte[] buffer = new byte[1024];
                        int count = -1;
                        while ((count = is.read(buffer)) != -1) {
                            os.write(buffer, 0, count);
                        }
                    }
                }
            }
        }
    }
}