How to speed up unzipping time in Java / Android?

后端 未结 6 1551
名媛妹妹
名媛妹妹 2020-12-02 08:42

Unzipping files on android seems to be dreadfully slow. At first I thought this was just the emulator but it appears to be the same on the phone. I\'ve tried different compr

相关标签:
6条回答
  • 2020-12-02 09:14

    The URL that helped me learn how to zip and unzip can be found here.

    I used that URL in conjuction with user3203118's answer above for unzipping. This is for future references for people who run in to this issue and need help solving it.

    Below is the ZipManager code I am using:

    public class ZipManager {
    
        private static final int BUFFER = 80000;
    
        public void zip(String[] _files, String zipFileName) {
            try {
                BufferedInputStream origin = null;
                FileOutputStream dest = new FileOutputStream(zipFileName);
                ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));
                byte data[] = new byte[BUFFER];
    
                for (int i = 0; i < _files.length; i++) {
                    Log.v("Compress", "Adding: " + _files[i]);
                    FileInputStream fi = new FileInputStream(_files[i]);
                    origin = new BufferedInputStream(fi, BUFFER);
    
                    ZipEntry entry = new ZipEntry(_files[i].substring(_files[i]
                        .lastIndexOf("/") + 1));
                    out.putNextEntry(entry);
                    int count;
    
                    while ((count = origin.read(data, 0, BUFFER)) != -1) {
                        out.write(data, 0, count);
                    }
                    origin.close();
                }
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void unzip(String _zipFile, String _targetLocation) {
    
    
            // create target location folder if not exist
            dirChecker(_targetLocation);
    
            try {
                FileInputStream fin = new FileInputStream(_zipFile);
                ZipInputStream zin = new ZipInputStream(fin);
                ZipEntry ze = null;
                while ((ze = zin.getNextEntry()) != null) {
    
                    // create dir if required while unzipping
                    if (ze.isDirectory()) {
                        dirChecker(ze.getName());
                    } else {
                        FileOutputStream fout = new FileOutputStream(
                        _targetLocation + "/" + ze.getName());
                        BufferedOutputStream bufout = new BufferedOutputStream(fout);
                        byte[] buffer = new byte[1024];
                        int read = 0;
                        while ((read = zin.read(buffer)) != -1) {
                            bufout.write(buffer, 0, read);
                        }
    
                        zin.closeEntry();
                        bufout.close();
                        fout.close();
                    }
                }
                zin.close();
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    
        private void dirChecker(String dir) {
            File f = new File(dir);
            if (!f.isDirectory()) {
                f.mkdirs();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 09:23

    Using above ideas and ideas from some other sources I have created this class

    Create this new class

    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import android.util.Log;
    
    public class DecompressFast {
     private String _zipFile; 
      private String _location; 
    
      public DecompressFast(String zipFile, String location) { 
        _zipFile = zipFile; 
        _location = location; 
        _dirChecker(""); 
      } 
    
      public void unzip() { 
        try  { 
          FileInputStream fin = new FileInputStream(_zipFile); 
          ZipInputStream zin = new ZipInputStream(fin); 
          ZipEntry ze = null; 
          while ((ze = zin.getNextEntry()) != null) { 
            Log.v("Decompress", "Unzipping " + ze.getName()); 
            if(ze.isDirectory()) { 
              _dirChecker(ze.getName()); 
            } else { 
              FileOutputStream fout = new FileOutputStream(_location +  ze.getName()); 
              BufferedOutputStream bufout = new BufferedOutputStream(fout);
              byte[] buffer = new byte[1024];
              int read = 0;
              while ((read = zin.read(buffer)) != -1) {
                  bufout.write(buffer, 0, read);
              }
              bufout.close();
              zin.closeEntry(); 
              fout.close(); 
            }    
          } 
          zin.close(); 
          Log.d("Unzip", "Unzipping complete. path :  " +_location );
        } catch(Exception e) { 
          Log.e("Decompress", "unzip", e); 
          Log.d("Unzip", "Unzipping failed");
        } 
      } 
    
      private void _dirChecker(String dir) { 
        File f = new File(_location + dir); 
    
        if(!f.isDirectory()) { 
          f.mkdirs(); 
        } 
      } 
    }
    

    USAGE

    just pass your file location of zip file and your destination Location to this class
    example

      String zipFile = Environment.getExternalStorageDirectory() + "/the_raven.zip"; //your zip file location
      String unzipLocation = Environment.getExternalStorageDirectory() + "/unzippedtestNew/"; // unzip location
      DecompressFast df= new DecompressFast(zipFile, unzipLocation);
        df.unzip();
    

    Dont Forget to add following permissions in manifest(also Run time permission if version higher than marshmellow)

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    

    hope this helps

    0 讨论(0)
  • 2020-12-02 09:23

    In case of using BufferedOutputStream be sure to flush it. If you do not do it, size smaller than buffer will not be unzipped properly

    if (ze.isDirectory()) {
                    _dirChecker(ze.getName());
                } else {
                    FileOutputStream fout = new FileOutputStream(_location
                            + ze.getName());
                        BufferedOutputStream out = new BufferedOutputStream(fout);
                        byte buffer[] = new byte[1024];
                    for (int c = in.read(buffer,0,1024); c != -1; c = in.read()) {
                        out.write(buffer,0,c);
                    }
                    out.flush();//flush it......
                    zin.closeEntry();
                    fout.close();
                }
    
    0 讨论(0)
  • 2020-12-02 09:29

    I don't know if unzipping on Android is slow, but copying byte for byte in a loop is surely slowing it down even more. Try using BufferedInputStream and BufferedOutputStream - it might be a bit more complicated, but in my experience it is worth it in the end.

    BufferedInputStream in = new BufferedInputStream(zin);
    BufferedOutputStream out = new BufferedOutputStream(fout);
    

    And then you can write with something like that:

    byte b[] = new byte[1024];
    int n;
    while ((n = in.read(b,0,1024)) >= 0) {
      out.write(b,0,n);
    }
    
    0 讨论(0)
  • 2020-12-02 09:33

    Thanks for the solution Robert. I modified my unzip method and now it takes only a few seconds instead of 2 minutes. Maybe someone's interested in my solution. So here you go:

    public void unzip() {
    
        try {
            FileInputStream inputStream = new FileInputStream(filePath);
            ZipInputStream zipStream = new ZipInputStream(inputStream);
            ZipEntry zEntry = null;
            while ((zEntry = zipStream.getNextEntry()) != null) {
                Log.d("Unzip", "Unzipping " + zEntry.getName() + " at "
                        + destination);
    
                if (zEntry.isDirectory()) {
                    hanldeDirectory(zEntry.getName());
                } else {
                    FileOutputStream fout = new FileOutputStream(
                            this.destination + "/" + zEntry.getName());
                    BufferedOutputStream bufout = new BufferedOutputStream(fout);
                    byte[] buffer = new byte[1024];
                    int read = 0;
                    while ((read = zipStream.read(buffer)) != -1) {
                        bufout.write(buffer, 0, read);
                    }
    
                    zipStream.closeEntry();
                    bufout.close();
                    fout.close();
                }
            }
            zipStream.close();
            Log.d("Unzip", "Unzipping complete. path :  " + destination);
        } catch (Exception e) {
            Log.d("Unzip", "Unzipping failed");
            e.printStackTrace();
        }
    
    }
    
    public void hanldeDirectory(String dir) {
            File f = new File(this.destination + dir);
            if (!f.isDirectory()) {
                f.mkdirs();
            }
    }
    
    0 讨论(0)
  • 2020-12-02 09:34

    Just call this method and it will give you much better performance..

        public boolean unzip(Context context) {
        try {
            FileInputStream fin = new FileInputStream(_zipFile);
            ZipInputStream zin = new ZipInputStream(fin);
            BufferedInputStream in = new BufferedInputStream(zin);
            ZipEntry ze = null;
            while ((ze = zin.getNextEntry()) != null) {
                Log.v("Decompress", "Unzipping " + ze.getName());
    
                if (ze.isDirectory()) {
                    _dirChecker(ze.getName());
                } else {
                    FileOutputStream fout = new FileOutputStream(_location
                            + ze.getName());
                        BufferedOutputStream out = new BufferedOutputStream(fout);
                        byte b[] = new byte[1024];
                    for (int c = in.read(b,0,1024); c != -1; c = in.read()) {
                        out.write(b,0,c);
                    }
                    zin.closeEntry();
                    fout.close();
                }
            }
            zin.close();
            return true;
        } catch (Exception e) {
            Log.e("Decompress", "unzip", e);
            return false;
        }
    }
    
        private void _dirChecker(String dir) {
        File f = new File(_location + dir);
        if (!f.isDirectory()) {
            f.mkdirs();
        }
    }
    
    0 讨论(0)
提交回复
热议问题