gpt4 book ai didi

java - 在 Android 中使用 ZipOutputStream 将最多 24mb 的文件压缩成 .zip

转载 作者:可可西里 更新时间:2023-11-01 11:42:41 25 4
gpt4 key购买 nike

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

目前,我的代码成功地将文件压缩到 .zip 目录中,但其中一个 .zip 目录总是损坏。当我的 for 循环退出第一个 Files[] of 22 objects 并开始下一个目录 Files[] of 时,我看到了这一点4 个对象。我相信我失去了对旧 OutputStreams 的一些清理。 out.putNextEntry() 在 for 循环的第二次尝试后变为 null。任何帮助就足够了。

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();
}
}

FileOutputStream destinationDir = new FileOutputStream(sdCard.getAbsolutePath() + "/Download/Dir/nwdLogs.zip");
ZipOutputStream out = new ZipOutputStream(destinationDir);

currentZipFileSize = 0;
addDirToArchive(out, destinationDir, dirName);
out.close();
destinationDir.close();

最佳答案

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

另外,请注意您不需要同时关闭 fisorigin。只需关闭 origin ... 它就会关闭 fis


更新 - 虽然您修复了最初的关闭错误,但还有更多错误:

  1. 您已经添加了一个 finally block 来关闭 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 错误,您不希望记录消息并继续操作。你想摆脱困境。要么完全崩溃应用程序,要么停止做你正在做的事情。在这种情况下,您的“流已关闭”显然是代码中的一个错误,您的异常处理实际上是在告诉应用忽略它。

一些建议:

  • 如果您将打开和关闭资源的责任分摊到多个方法中,您需要非常注意哪些代码负责关闭哪些内容。你需要明白你在做什么。

  • 盲目地应用(所谓的)“解决方案”(比如 finally 东西)...因为有人说“XXX 是最佳实践”或“总是做 XXX”...会给你带来麻烦。您需要 1) 了解“解决方案”的作用,以及 2) 思考该解决方案是否真正满足了您的需求。

关于java - 在 Android 中使用 ZipOutputStream 将最多 24mb 的文件压缩成 .zip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35639325/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com