使用Android中的ZipOutputStream将最多24mb文件压缩为.zip

时间:2016-02-25 22:06:04

标签: java android zipoutputstream

我正在尝试将目录从一个区域(sdCard/someFolder)压缩到第二个目录(sdCard/Download),直到.zip文件大小变为5mb。然后,我想创建一个新的.zip文件,将新文件填充到5mb等等。

目前,我的代码成功地将文件压缩到.zip目录中,但其中一个.zip目录总是会损坏。当我的for循环退出Files[]的{​​{1}}时,我会看到这一点,并启动22 objects Files[]的下一个目录。我相信我正在丢失一些旧的OutputStreams。在第二次尝试for循环后,4 objects变为空。任何帮助就足够了。

out.putNextEntry()

}

private static void addDirToArchive(ZipOutputStream out, FileOutputStream destinationDir, File sdCardMNDLogs)
{
    File[] listOfFiles = sdCardMNDLogs.listFiles();

    BufferedInputStream origin = null;

    Log.i(TAG3, "Reading directory: " + sdCardMNDLogs.getName());

    try{

    byte[] buffer = new byte[BUFFER];
    for(int i = 0; i < listOfFiles.length; i++)
    {
        if(listOfFiles[i].isDirectory())
        {
            addDirToArchive(out, destinationDir, listOfFiles[i]);
            continue;
        }
        try 
        {
            FileInputStream fis = new FileInputStream(listOfFiles[i]);
            origin = new BufferedInputStream(fis,BUFFER);
            ZipEntry ze = new ZipEntry(listOfFiles[i].getName());

            if(currentZipFileSize >= EMAIL_SIZE)
            {
                out.close();
                Log.d(emailTAG, "Creating new zipfile: /Download/MND/nwdLogs_" + i);
                out = new ZipOutputStream(new FileOutputStream(new File(sdCard.getAbsolutePath() + "/Download/MND/nwdLogs_ " + i + ".zip")));
                currentZipFileSize = 0;
            }
            out.putNextEntry(ze);
            int length;
            Log.i(TAG3, "Adding file: " + listOfFiles[i].getName());
            while((length = origin.read(buffer, 0, BUFFER)) != -1)
            {
                out.write(buffer, 0, length);
            }
            out.closeEntry();
            origin.close();
            currentZipFileSize = currentZipFileSize + ze.getCompressedSize();
        }
        catch(IOException ioe)
        {
            Log.e(TAG3, "IOException: " + ioe);
        }
    }
    }
    finally
    {
        try {
            out.close();
    } catch (IOException e) 
    {
        e.printStackTrace();
    }
}

1 个答案:

答案 0 :(得分:2)

我怀疑问题是您在打开下一个ZIP文件之前没有调用out.close()。我的理解是ZIP的索引仅在ZIP关闭时写入,因此如果您忽略关闭索引将会丢失:因此损坏。

另请注意,您无需关闭fisorigin。只需关闭origin ...即可关闭fis

更新 - 修复原始关闭错误后,还有更多内容:

  1. 您添加了finally块以关闭out。那是错的。您不希望addDirToArchive关闭out。这可能是您例外的原因。

  2. 完成此操作后会发生一些问题:

    if (currentZipFileSize >= EMAIL_SIZE)
        {
            out.close();
            out = new ZipOutputStream(new FileOutputStream(...));
            currentZipFileSize = 0;
        }
    

    由于out是本地参数,因此调用者不会看到更改 你做。因此:

    • 当您在来电者中拨打out.close()时,您可能正在关闭 原始的ZIP(已经关闭)...不是当前的

    • 如果您致电addDirToArchive(out, destinationDir, dirName) 多次,在后续调用中,您可以传递一个封闭的ZIP文件。

  3. 您的异常处理被误导(IMO)。如果将文件写入ZIP时出现I / O错误,则不希望记录消息并继续。你想摆脱困境。要么完全崩溃应用程序,要么停止做你正在做的事情。在这种情况下,您&#34;流已关闭&#34;显然是你的代码中的一个错误,你的异常处理实际上告诉应用程序忽略它。

  4. 一些建议:

    • 如果您要分担跨多种方法打开和关闭资源的责任,您需要非常小心哪些代码负责关闭什么。你需要了解自己在做什么。

    • 盲目地应用(所谓的)&#34;解决方案&#34; (比如finally的东西)...&#39;有人说&#34; XXX是最佳实践&#34;或者&#34;总是做XXX&#34; ...会让你陷入困境。你需要1)了解&#34;解决方案&#34; 2,思考关于解决方案是否真正满足您的需求。