zip/compress a folder full of files on android

前端 未结 6 920
盖世英雄少女心
盖世英雄少女心 2020-12-05 10:33

I need to zip up a \"project\" folder to allow users to share projects via email. I found a class for zipping up multiple files into one zip, but I need to keep the folder s

相关标签:
6条回答
  • 2020-12-05 11:03
    public static boolean zip(File sourceFile, File zipFile) {
        List<File> fileList = getSubFiles(sourceFile, true);
        ZipOutputStream zipOutputStream = null;
        try {
            zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
            int bufferSize = 1024;
            byte[] buf = new byte[bufferSize];
            ZipEntry zipEntry;
            for(int i = 0; i < fileList.size(); i++) {
                File file = fileList.get(i);
                zipEntry = new ZipEntry(sourceFile.toURI().relativize(file.toURI()).getPath());
                zipOutputStream.putNextEntry(zipEntry);
                if (!file.isDirectory()) {
                    InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
                    int readLength;
                    while ((readLength = inputStream.read(buf, 0, bufferSize)) != -1) {
                        zipOutputStream.write(buf, 0, readLength);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            IoUtils.closeOS(zipOutputStream);
        }
        return true;
    }    
    
    public static List<File> getSubFiles(File baseDir, boolean isContainFolder) {
        List<File> fileList = new ArrayList<>();
        File[] tmpList = baseDir.listFiles();
        for (File file : tmpList) {
            if (file.isFile()) {
                fileList.add(file);
            }
            if (file.isDirectory()) {
                if (isContainFolder) {
                    fileList.add(file); //key code
                }
                fileList.addAll(getSubFiles(file));
            }
        }
        return fileList;
    }
    
    0 讨论(0)
  • 2020-12-05 11:08

    I have reworked the code from HailZeon to work properly under windows. Zip Entries must be closed before new ones are started and a starting "/" at entry names like "/file.txt" makes also problems

    /**
     * Zips a Folder to "[Folder].zip"
     * @param toZipFolder Folder to be zipped
     * @return the resulting ZipFile
     */
    public static File zipFolder(File toZipFolder) {
        File ZipFile = new File(toZipFolder.getParent(), format("%s.zip", toZipFolder.getName()));
        try {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(ZipFile));
            zipSubFolder(out, toZipFolder, toZipFolder.getPath().length());
            out.close();
            return ZipFile;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
    
    /**
     * Main zip Function
     * @param out Target ZipStream
     * @param folder Folder to be zipped
     * @param basePathLength Length of original Folder Path (for recursion)
     */
    private static void zipSubFolder(ZipOutputStream out, File folder, int basePathLength) throws IOException {
    
        final int BUFFER = 2048;
    
        File[] fileList = folder.listFiles();
        BufferedInputStream origin = null;
        for (File file : fileList) {
            if (file.isDirectory()) {
                zipSubFolder(out, file, basePathLength);
            } else {
                byte data[] = new byte[BUFFER];
    
                String unmodifiedFilePath = file.getPath();
                String relativePath = unmodifiedFilePath.substring(basePathLength + 1);
    
                FileInputStream fi = new FileInputStream(unmodifiedFilePath);
                origin = new BufferedInputStream(fi, BUFFER);
    
                ZipEntry entry = new ZipEntry(relativePath);
                entry.setTime(file.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
    
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
                out.closeEntry();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 11:20

    This code should do the trick.

    Note: you must add file write permissions to your app by adding the WRITE_EXTERNAL_STORAGE permission to your manifest.xml file.

    /*
     * 
     * Zips a file at a location and places the resulting zip file at the toLocation
     * Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip");
     */
    
    public boolean zipFileAtPath(String sourcePath, String toLocation) {
        final int BUFFER = 2048;
    
        File sourceFile = new File(sourcePath);
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(toLocation);
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));
            if (sourceFile.isDirectory()) {
                zipSubFolder(out, sourceFile, sourceFile.getParent().length());
            } else {
                byte data[] = new byte[BUFFER];
                FileInputStream fi = new FileInputStream(sourcePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
                entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
            }
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    
    /*
     * 
     * Zips a subfolder
     * 
     */
    
    private void zipSubFolder(ZipOutputStream out, File folder,
            int basePathLength) throws IOException {
    
        final int BUFFER = 2048;
    
        File[] fileList = folder.listFiles();
        BufferedInputStream origin = null;
        for (File file : fileList) {
            if (file.isDirectory()) {
                zipSubFolder(out, file, basePathLength);
            } else {
                byte data[] = new byte[BUFFER];
                String unmodifiedFilePath = file.getPath();
                String relativePath = unmodifiedFilePath
                        .substring(basePathLength);
                FileInputStream fi = new FileInputStream(unmodifiedFilePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(relativePath);
                entry.setTime(file.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
            }
        }
    }
    
    /*
     * gets the last path component
     * 
     * Example: getLastPathComponent("downloads/example/fileToZip");
     * Result: "fileToZip"
     */
    public String getLastPathComponent(String filePath) {
        String[] segments = filePath.split("/");
        if (segments.length == 0)
            return "";
        String lastPathComponent = segments[segments.length - 1];
        return lastPathComponent;
    }
    
    0 讨论(0)
  • 2020-12-05 11:21

    this is how I do it:

    private static void zipFolder(String inputFolderPath, String outZipPath) {
        try {
            FileOutputStream fos = new FileOutputStream(outZipPath);
            ZipOutputStream zos = new ZipOutputStream(fos);
            File srcFile = new File(inputFolderPath);
            File[] files = srcFile.listFiles();
            Log.d("", "Zip directory: " + srcFile.getName());
            for (int i = 0; i < files.length; i++) {
                Log.d("", "Adding file: " + files[i].getName());
                byte[] buffer = new byte[1024];
                FileInputStream fis = new FileInputStream(files[i]);
                zos.putNextEntry(new ZipEntry(files[i].getName()));
                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }
                zos.closeEntry();
                fis.close();
            }
            zos.close();
        } catch (IOException ioe) {
            Log.e("", ioe.getMessage());
        }
    }
    
    0 讨论(0)
  • 2020-12-05 11:22

    If you use a java.util.zip object then you can write a script that does not modify the directory structure.

    0 讨论(0)
  • 2020-12-05 11:23

    Use the zip4j library from this location. Import the jar file to your "app/libs/" folder. And use the following code to zip your directories/files...

    try {
        File input = new File("path/to/your/input/fileOrFolder");
        String destinationPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "zippedItem.zip";
        ZipParameters parameters = new ZipParameters();
        parameters.setCompressionMethod(Zip4jConstants.COMP_STORE);
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        File output = new File(destinationPath);
        ZipFile zipFile = new ZipFile(output);
        // .addFolder or .addFile depending on your input
        if (sourceFile.isDirectory())
            zipFile.addFolder(input, parameters);
        else
            zipFile.addFile(input, parameters);
        // Your input file/directory has been zipped at this point and you
        // can access it as a normal file using the following line of code
        File zippedFile = zipFile.getFile();
    } catch (ZipException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    
    0 讨论(0)
提交回复
热议问题