Java 以编程方式生成zip会创建无效的zip[android]

Java 以编程方式生成zip会创建无效的zip[android],java,android,fileinputstream,zipoutputstream,Java,Android,Fileinputstream,Zipoutputstream,我有一个文件夹,里面有3张图片,我想把它们压缩并发送电子邮件。我有一种方法可以做到这一点,我在以前的问题中使用过这种方法,效果很好。然而,这一次它不断生成一个无效的zip,当我打开zip时,里面只有一张大小为0的图片。 但我似乎不明白为什么。方法如下: //generate the zip file for the picture String zipFile = context.getExternalFilesDir(null) + "/ArcFlash/Checkli

我有一个文件夹,里面有3张图片,我想把它们压缩并发送电子邮件。我有一种方法可以做到这一点,我在以前的问题中使用过这种方法,效果很好。然而,这一次它不断生成一个无效的zip,当我打开zip时,里面只有一张大小为0的图片。 但我似乎不明白为什么。方法如下:

      //generate the zip file for the picture
      String zipFile = context.getExternalFilesDir(null) + "/ArcFlash/Checklist.zip";
      String srcDir = context.getExternalFilesDir(null) + "/ArcFlash/CheckListMedia";

      FileOutputStream fos = new FileOutputStream(zipFile);

      ZipOutputStream zos = new ZipOutputStream(fos);

      File srcFile = new File(srcDir);

      addDirToArchive(zos, srcFile, context);
下面是我的
addDirToArchive
方法,它生成zip文件:

private static void addDirToArchive(ZipOutputStream zos, File srcFile, Context ctx)
{
    File[] files = srcFile.listFiles();

    for (int i = 0; i < files.length; i++)
    {
        // if the file is directory, use recursion
        if (files[i].isDirectory())
        {
            addDirToArchive(zos, files[i], ctx);
            continue;
        }
        try
        {
            System.out.println("tAdding file: " + files[i].getName());

            // create byte buffer
            byte[] buffer = new byte[1024];//2048

            FileInputStream fis = new FileInputStream(files[i]);

            String target = ctx.getExternalFilesDir(null) + "/";
            String oldPath = files[i].getPath();
            String newPath = oldPath.replace(target, "");

            zos.putNextEntry(new ZipEntry(newPath));
            int length;
            while ((length = fis.read(buffer)) > 0)
            {
                zos.write(buffer, 0, length);
            }

            zos.closeEntry();

            // close the InputStream
            fis.close();
        }
        catch (Exception ex)
        {
            Log.i("customException", "error zipping: " + ex.getMessage());
        }
    }
}
private static void addDirToArchive(zipoutpstream zos、文件srcFile、上下文ctx)
{
File[]files=srcFile.listFiles();
对于(int i=0;i0)
{
写入(缓冲区,0,长度);
}
zos.closeEntry();
//关闭输入流
fis.close();
}
捕获(例外情况除外)
{
Log.i(“customException”,“错误压缩:”+ex.getMessage());
}
}
}
编辑

我强烈建议您使用此库压缩/解压缩内容:


使用下面的代码示例,下面是如何执行所需操作:

final Path basePath = Paths.get(context.getExternalFilesDir(null));
final Path srcDir = Paths.resolve("ArcFlash/CheckListMedia");

final Path zipFile = Paths.resolve("ArcFlash/Checklist.zip");
final Map<String, Object> env = new HashMap<>();
env.put("create", "true");
final URI zip = URI.create("jar:file:" + zipFile.toAbsolutePath().toString());

try (
    final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
) {
    Files.walkFileTree(srcDir, new CopyFileVisitor(srcDir, fs.getPath("/")));
}

确保在创建文件时添加了正确的头。

尝试使用Java 7提供的新ZIP文件系统,以实现我的情况。将返回报告我已尝试实现该代码,但大多数方法(如
FileVisitResult
)都获得了
无法解决的错误。与
路径相同
您的意思是
ProviderMismatchException
?是的,我注意到了这个错误;我已经修复了代码,请看
toDestination()
。以前是
dstdir.resolve(rel)
,现在是
dstdir.resolve(rel.toString())
。看到编辑部分,我贴了一张图片。我已经包含了所有必要的导入,但它仍然无法识别它您确定要导入
java.nio.file.FileSystem
public final class ZipZip
{
    public static void main(final String... args)
        throws IOException
    {
        final Map<String, Object> env = new HashMap<>();
        env.put("create", "true");
        final URI zip = URI.create("jar:file:/tmp/t.zip");

        final Path sourceFile = Paths.get("/tmp/foo.txt");

        Files.deleteIfExists(Paths.get("/tmp/t.zip"));

        try (
            final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
        ) {

            final Path zipdir = fs.getPath("/dir");
            Files.createDirectory(zipdir);

            final Path zipfile = zipdir.resolve("t.txt");
            Files.copy(sourceFile, zipfile);
        }
    }
}
public final class CopyFileVisitor
    implements FileVisitor<Path>
{
    private final Path srcdir;
    private final Path dstdir;

    public CopyFileVisitor(final Path srcdir, final Path dstdir)
    {
        this.srcdir = srcdir.toAbsolutePath();
        this.dstdir = dstdir.toAbsolutePath();
    }

    @Override
    public FileVisitResult preVisitDirectory(final Path dir,
        final BasicFileAttributes attrs)
        throws IOException
    {
        Files.createDirectories(toDestination(dir));
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(final Path file,
        final BasicFileAttributes attrs)
        throws IOException
    {
        System.out.printf("%s -> %s\n", file.toAbsolutePath(),
            toDestination(file));
        Files.copy(file, toDestination(file));
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc)
        throws IOException
    {
        throw exc;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc)
        throws IOException
    {
        if (exc != null)
            throw exc;
        return FileVisitResult.CONTINUE;
    }

    private Path toDestination(final Path victim)
    {
        final Path tmp = victim.toAbsolutePath();
        final Path rel = srcdir.relativize(tmp);
        return dstdir.resolve(rel.toString());
    }
}