Zip/Unzip Library

JonPM

Well-Known Member
Licensed User
Longtime User
There is a known bug with this library. On zip'ing, the first letter of each filename gets deleted (i.e. Picture.jpg > icture.jpg). Is there any status on the repair of this? This bug virtually makes this library useless.
 

jdiperla

Member
Licensed User
Longtime User
While you wait for a fix, try a workaround. Add one letter to the beginning of the files you are creating and it should solve the problem for now.
 

AscySoft

Active Member
Licensed User
Longtime User
While you wait for a fix, try a workaround. Add one letter to the beginning of the files you are creating and it should solve the problem for now.

Indeed, this is the way I do things about this 'imperfect' but useful library. The only problem is that you must rename (large) number of files, is not so beautiful...but there is no other way, at least for now.
 

alwaysbusy

Expert
Licensed User
Longtime User
I've discontinued working on this library because I do not have the time to work on it any more. Here is the java source code if someone wants to fix it. However this was one of the first libraries I wrote for B4A and was still learning java at the time so the quality is not going to be good. But feel free to use it as a base to maybe create a complete new Zip library.

Alwaysbusy

B4X:
package com.AB.ABZipUnzip;

import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * Object that does zip en unzip files on the device 
 */
@ShortName("ABZipUnzip")
@Permissions(values={"android.permission.WRITE_EXTERNAL_STORAGE"})
@Version(1.0f)
@Author("Alain Bailleul")
public class ABZipUnzip {
   private static CopyOnWriteArrayList<ABZipContent> _theZip=null;
   private static String SOURCE_FOLDER = "";
   /**
    *  zip a folder with all its files and subdirectories
    *  
    *  Example:<code>
    *  myzip.ABZipDirectory(sdRoot & "start", sdRoot & "myZip.zip")
    *  </code>
    */
   public boolean ABZipDirectory(String sourceDir, String zipFile) {
      
      //String sourceDir = "C:/examples";
      //String zipFile = "C:/FileIO/zipdemo.zip";
         SOURCE_FOLDER = sourceDir;
         try {
            boolean wasOK=false;
            FileOutputStream fout = new FileOutputStream(zipFile);
            ZipOutputStream zout = new ZipOutputStream(fout);
            File fileSource = new File(sourceDir);
            wasOK = addDirectory(zout, fileSource, true);
            zout.close();
            System.out.println("Zip file has been created!");
            return wasOK;
         }
         catch(IOException ioe) {
            System.out.println("IOException :" + ioe);
            return false;
         }
   }
   
   /**
    *  Zip a single file
    *  
    *  sourcePath must end with "/"
    *  
    *  Example:<code>
    *  myzip.ABZipFile(sdRoot & "start/" , "test4.txt", sdRoot & "myZipOneFile.zip")
    *  </code>
    */
   public boolean ABZipfile(String sourcePath, String sourceFile, String zipFile) {
      
      //String zipFile = "C:/FileIO/zipdemo.zip";
      //String sourceFile = "C:/FileIO/sourcefile.doc
      
         try
            {
            byte[] buffer = new byte[1024];
            FileOutputStream fout = new FileOutputStream(zipFile);
            ZipOutputStream zout = new ZipOutputStream(fout);
            FileInputStream fin = new FileInputStream(sourcePath + sourceFile);
            zout.putNextEntry(new ZipEntry(sourceFile));
            int length;
            while((length = fin.read(buffer)) > 0)
            {
               zout.write(buffer, 0, length);
            }
            zout.closeEntry();
            fin.close();
            zout.close();
            System.out.println("Zip file has been created!");
            return true;
            
         }
         catch(IOException ioe) {
            System.out.println("IOException :" + ioe);
            return false;
         }
      
   }
   /**
    *  Unzip a zip file 
    *  
    *  Example:<code>
    *  myZip.ABUnzip(sdRoot & "myZip.zip", sdRoot & "target")
    *  </code>
    */
   public boolean ABUnzip(String zipFile, String targetPath) {
      
      //String strZipFile = args[0];
      
      if(zipFile == null || zipFile.equals("")) {
         System.out.println("Invalid source file");
         return false;
      }
      System.out.println("Zip file extracted!");
      return unzip(zipFile, targetPath);
      
   }
   
   
   private static boolean unzip(String zipFile, String targetPath) {
      try {
         File fSourceZip = new File(zipFile);
         //String zipPath = zipFile.substring(0, zipFile.length()-4);
         //File temp = new File(zipPath);
         //temp.mkdir();
         File temp = new File(targetPath);
         temp.mkdir();
         System.out.println(targetPath + " created");
         ZipFile zFile = new ZipFile(fSourceZip);
         Enumeration e = zFile.entries();
         while(e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry)e.nextElement();
            File destinationFilePath = new File(targetPath,entry.getName());
            destinationFilePath.getParentFile().mkdirs();
            if(entry.isDirectory()) {
               continue;
            } 
            else {
               System.out.println("Extracting " + destinationFilePath);
               BufferedInputStream bis = new BufferedInputStream(zFile.getInputStream(entry));
               int b;
               byte buffer[] = new byte[1024];
               FileOutputStream fos = new FileOutputStream(destinationFilePath);
               BufferedOutputStream bos = new BufferedOutputStream(fos,1024);
               while ((b = bis.read(buffer, 0, 1024)) != -1) {
                  bos.write(buffer, 0, b);
               }
               bos.flush();
               bos.close();
               bis.close();
            }
         }
      }
      catch(IOException ioe) {
         System.out.println("IOError :" + ioe);
         return false;
      }
      return true;
   }
   /**
    *  List the contents of a zip file
    *  
    *  Example:<code>
    *  Dim myZipFile as ABZipContent 
    *  
    *  listview1.Clear
    *  counter = myzip.ABListZip(sdRoot & "myZipOneFile.zip")
    *  For a = 0 To counter - 1
    *      myZipFile = myZip.ABGetListItem(a)
    *      listview1.AddTwoLines(myZipfile.Name, "Size: " & MyZipfile.Size & " bytes   Compressed Size: " & myzipFile.CompressedSize & " bytes")
    *  Next
    *  </code>
    */
   public int ABListZip(String zipFile) {
      _theZip = new CopyOnWriteArrayList<ABZipContent>();
      ABZipContent _tmpABC=null;
      int counter=0;
      try {
         File fSourceZip = new File(zipFile);
         ZipFile zFile = new ZipFile(fSourceZip);
         Enumeration e = zFile.entries();
         while(e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry)e.nextElement();
            _tmpABC = new ABZipContent();
            _tmpABC._Name = entry.getName();
            _tmpABC._CompressedSize = entry.getCompressedSize();
            _tmpABC._Size = entry.getSize();
            _tmpABC._IsDirectory = entry.isDirectory();
            _tmpABC._Type = 1; //new
            _theZip.add(_tmpABC);
            counter++;
         }
      }
      catch(IOException ioe) {
         System.out.println("IOError :" + ioe);
         return -1;
      }
      return counter;
   }
   
   /**
    *  Get one if the items in the zipfile to get more information. Fill this list first by calling ABListZip() 
    */
   public ABZipContent ABGetListItem(int index) {
      return _theZip.get(index);
   }
   
   private static String generateZipEntry(String file){
       return file.substring(SOURCE_FOLDER.length()+1, file.length());
    }

   
   private static boolean addDirectory(ZipOutputStream zout, File fileSource, boolean isRoot) {
      boolean wasOK=false;
      File[] files = fileSource.listFiles();
      System.out.println("Adding directory " + fileSource.getName());
      for(int i=0; i < files.length; i++) {
         if(files[i].isDirectory()) {
            wasOK = addDirectory(zout, files[i], false);
            if (wasOK==false) {
               return false;
            }
            continue;
         }
         try {
            System.out.println("Adding file " + files[i].getAbsolutePath());
            byte[] buffer = new byte[1024];
            FileInputStream fin = new FileInputStream(files[i].getAbsoluteFile());
            if (isRoot==true) {
               zout.putNextEntry(new ZipEntry(generateZipEntry(files[i].getAbsoluteFile().toString())));
            } else {
               zout.putNextEntry(new ZipEntry(generateZipEntry(files[i].getAbsoluteFile().toString())));
            }
            int length;
            while((length = fin.read(buffer)) > 0) {
               zout.write(buffer, 0, length);
            }
            zout.closeEntry();
            fin.close();
         }
         catch(IOException ioe) {
            System.out.println("IOException :" + ioe);
            return false;
         }
   
      }
      return true;
   }
   
   /**
    * An object that the contains information about an entry in the zip file 
    */
   @ShortName("ABZipContent")
   public static class ABZipContent {
       String _Name = "";
        Long _CompressedSize = (long) 0;
        Long _Size = (long) 0;
        boolean _IsDirectory = false;
        int _Type = 0;        
        
        /**
         * Returns the full path and name of the entry 
         */
        public String getName() {
           return _Name;
        }
        
        /**
         * Returns the compressed size of the entry 
         */
        public Long getCompressedSize() {
           return _CompressedSize;
        }
        
        /**
         * Returns the uncompressed size of the entry 
         */
        public Long getSize() {
           return _Size;
        }
        
    }
}
 

Smee

Well-Known Member
Licensed User
Longtime User
I am extracting a single file from a zip folder. However the code I am using also creates a folder with the same name as the file inside the archive

B4X:
Dim ZipFile As ABZipUnzip
Dim ZipName As ABZipContent
Dim i As Int
Dim ZipList As List
Dim CatFolder,FileName As String      

CatFolder=File.DirDefaultExternal & "/Catalogues/"

ZipList.Initialize
ZipList = File.ListFiles(CatFolder)

For x = 0 To ZipList.Size-1
   FileName=ZipList.Get(x)
   If s.Right(FileName,4)=".zip" Then
      ZipFile.ABListZip(CatFolder & FileName)
         ZipName=ZipFile.ABGetListItem(0)
         Log(ZipName.Name)
         If File.Exists(CatFolder,ZipName.Name)=False Then
            ZipFile.ABUnzip(CatFolder & FileName, CatFolder & ZipName.Name)
         End If
   End If
Next

Can someone see what i am doing wrong. I do not want to recreate a folder


UPDATE:

Its Ok i see what i was doing wrong.

The unzip command should be

ZipFile.ABUnzip(CatFolder & FileName, CatFolder)

dohhhh:
 
Last edited:

M.LAZ

Active Member
Licensed User
Longtime User
B4X:
Path = File.DirRootExternal & "/pics/" & "/mypics/"
                    For n = 0 To filelist.Size-1
                        file1 = filelist.Get(n)
                        If file1.EndsWith (".jpg") OR file1.EndsWith (".jpeg")  Then
                           myZip.ABZipFile(Path & "/" , Path & file1 , Path & "test.zip")
                        End If
                        DoEvents
                        Next


i try this code but the size of test.zip is 0 byte why? any help please!
and i changed this line :
myZip.ABZipFile(Path & "/" , Path & file1 , Path & "test.zip")
to: without slash
myZip.ABZipFile(Path, Path & file1 , Path & "test.zip")
and still the same problem?
 
Last edited:

CyclopDroid

Well-Known Member
Licensed User
Longtime User
mmmh please help me.
In my App I've Zipped a DB with WinZip and Unzipped with this command but, or I insert a Zipped DB into DirAssets, or I Insert a not zipped DB in DirAssets, the APK have the same MB.
Example:
My File.DB whitout compress have 15MB and my Apk file return 16MB RAM on HD.
When I insert File.ZIP, they have 5MB and, when I insert into my Dirassets (removed File.DB), the APK file is same 16MB! :eek:
Why? My normal APP have 10MB APK... but if I use a 5MB zipped DB, I've 16MB APK...if I use a 15MB DB, I've 16MB :confused:
Where am I doing wrong?
I Use the command
B4X:
myZip.ABUnzip(File.DirAssets & "File.zip", File.DirInternal & "File.db")

PS:The db is extracted only after a recall into a controll and not at the start of the APP
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Of course, it should not be so.

If you have tried several times, without making any error, I have some doubts, for which we will have to wait Erel; this doubt is also related to another your problem: the fact that sometimes the installation of your app does not complete successfully and you receive a memory error, which is more than enough.

I want to report the error happens to you when you use the Rapid Debug:

java.lang.RuntimeException: java.io.IOException: write failed: ENOSPC (No space left on device)
at anywheresoftware.b4a.shell.Shell.virtualAssets(Shell.java:159)


even though your device has a lot of free memory.
 
Top