B4J Library Zip4J - Library update - Version 2.10.0

Zip4J library, by Srikanth Reddy Lingala

Version 2.10.0 - 2022-03-28

Improvements:
  • Use utf-8 by default when reading zip file names
  • Add NoCompression deflate compression level

Bug Fixes:
  • Validate AES extra data record size
  • Include pos in array copy length calculation
  • Change IllegalArgumentException to ZipException
  • Handle unexpected EOF when reading raw stream
  • Handle unexpected EOF when reading compressed stream
  • Fill NPE when aesKeyStrength is null
  • Validate AES extra data record before calculating header size
  • Throw exception when file name length is 0
  • Replace RunTimeException with ZipException
  • Fix NPE in ZipParameters when file name is either null or empty
  • Minor improvement to canonical path check
  • Set entry size in ZipParameters to 0 by default

Jar file available for download HERE.
 

giannimaione

Well-Known Member
Licensed User
Longtime User
how to use this lib ?
 

max123

Well-Known Member
Licensed User
Longtime User
Hi @Claudio Oliveira I read now this post.

I already ported Zip4j library and I will release next on this forum.

As @giannimaione said, that is not clear to me is because you just posted the link to the original Zip4j jar library, maybe I miss something?
You import it in B4J and manage with JavaObject ?

My jZip4J library is developed in pure Java language using Eclipse and I've .jar and .xml library files.
Already build on top of Zip4j 2.10.0.

Please let me know how you use it.
 
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
Not yet released but already is working, I had problems because it process zip files and the main program will continue without wait the work finished.
This after I changed it because originally do the inverse, block a main thread (so even a GUI) while process zip files.

I cannnot find a middle way, so process files in background, one by one waiting it finished (so awaiting is good) but without blocking the GUI.

It is wild, has a lot of commands, with this library you can do something you can imagine with zip files, I've managed it to:

- Zip files from a List of files, with or without password protection. Created files can even be read with other programs like WinZip,, WinRar etc... if protected, then the password prompt will exit.
- Unzip a zip file, with or without password protection. To unzip a password protected file you need to put the password in the code
Can even unzip protected files created with WinZip, WinRar, 7Zip etc... by putting the password
- Put files inside an existing zip file
- Extract just some files from a zip file
- Create a splited zip file, so eg. instead to have a 10MB zip file you have 10 x 1MB files plus a main file that if you click open all ten files (full archive), you can set by code the splited files dimensions
- Because java are regular zip files, the library can put files inside an existing jar file, with or without password protection, eg. you can put a protected file inside a jar file, if an user try to open the jar file with archiver, it can see all jar files content, if click on this file, the password prompt will exit. But by putting the password (that only you know) in the code, your code can extract it in a temporary place and the application can use this file. Even you can open it with other programs by putting the password at prompt
- Not tried but probably can even extract files from a jar file (not sure)
- Creating zip files you can decide the compression level to apply
- And more ......

Note that I developed this library for both B4J and B4A.

As I said the libraries are pretty finished, only had problems with sync/asyns operations, please help to solve, so I can release it.
Need a java expert.
I can post some piece of java code.
 
Last edited:

Claudio Oliveira

Active Member
Licensed User
Longtime User
Hi @Claudio Oliveira I read now this post.

I already ported Zip4j library and I will release next on this forum.

As @giannimaione said, that is not clear to me is because you just posted the link to the original Zip4j jar library, maybe I miss something?
You import it in B4J and manage with JavaObject ?

My jZip4J library is developed in pure Java language using Eclipse and I've .jar and .xml library files.

Please let me know how you use it.
You import it in B4J and manage with JavaObject ?
Yes. That's exactly how I use it.
- Reference the lib via #AdditionalJar:
B4X:
#AdditionalJar: zip4j-2.11.2.jar
- Create an instance of a zip4j object:
B4X:
Dim zipFile As JavaObject 
zipFile.InitializeNewInstance("net.lingala.zip4j.ZipFile", Array("AnyZipFile.zip"))
- Call library methods:
B4X:
zipFile.RunMethod("extractAll", Array("OutputDir"))

Hope this helps.
 

max123

Well-Known Member
Licensed User
Longtime User
Yes thanks, I do the some things but directly on Java side.

You see that these methods block the UI but the program will continue even if the zip file is not yet fully processed ?
To see it you need to Zip or Unzip a relatively big file, eg. 30-40 MB.

The good thing on do it directly on B4J, is that you can use WaitFor, I do not have this option on Java side.... maybe I can call the B4X API and use it ?
 

Claudio Oliveira

Active Member
Licensed User
Longtime User
As I said the libraries are pretty finished, only had problems with sync/asyns operations, please help to solve, so I can release it.
Need a java expert.
I can post some piece of java code.
These are greast news indeeed!
I've been studying zip4j for quite some time now, and have been working myself on a port of this lib to B4J.
It's all written in B4J using JavaObject.
Why in B4J?
Well, I know this is not the best way to port a Java library to B4X, but my knowledge of Java is extremely restrict. I would wrap it if I was able to code Java. I can read a Java code and understand most of it, but I'm completely unable to write a single line in Java, so I decided to give it a try with B4J.
It's a work in progress and it's working "almost" fine. In fact, I'm quite about to quit this task.
What's the problem?
It's what they call "ProgressMonitor". It is intended to give the caller a feedback of the work being carried out by zip4j.
The problem is that ProgressMonitor is not event driven, but It's dependent on "wait" statements instead. Even the lib developer recognises that this approach is not good.
Sometimes my code can sync with it, sometimes not.
You should take a look at this. Maybe it's the reason you are facing problems with sync/async operations.

I Wish you good luck and I'm looking forward to see your library available! :)
 

Claudio Oliveira

Active Member
Licensed User
Longtime User
Yes thanks, I do the some things but directly on Java side.

You see that these methods block the UI but the program will continue even if the zip file is not yet fully processed ?
To see it you need to Zip or Unzip a relatively big file, eg. 30-40 MB.

The good thing on do it directly on B4J, is that you can use WaitFor, I do not have this option on Java side.... maybe I can call the B4X API and use it ?

Yes thanks, I do the some things but directly on Java side.

You see that these methods block the UI but the program will continue even if the zip file is not yet fully processed ?
To see it you need to Zip or Unzip a relatively big file, eg. 30-40 MB.

The good thing on do it directly on B4J, is that you can use WaitFor, I do not have this option on Java side.... maybe I can call the B4X API and use it ?
Sorry mate... When it comes to Java I am absolutely unable to help you... :confused:
Let's hope a good soul can show up and give the answers you're looking for. 🤞
 

max123

Well-Known Member
Licensed User
Longtime User
Ah ok, thanks, you are not a Java Guru.

Attached a simplified Javadoc of my library.
Because I cannot post html files I renamed it as .txt, to see it just rename as .html.
Here you can see all methods I've implemented.
 

Attachments

  • Zip4j.txt
    59.2 KB · Views: 88

giannimaione

Well-Known Member
Licensed User
Longtime User
zipFile.RunMethod("extractAll", Array("OutputDir"))
your example is ok; i am able to unzip file.zip, but
which method to use to zip a single file?

B4X:
zipFile.RunMethod("addFile" ......
java.lang.RuntimeException: Method: addFile not matched.
 

max123

Well-Known Member
Licensed User
Longtime User
@giannimaione, this is a relevant part of code in my library.... see addFile on line 48

Java:
    /**
     * Add a single file to a Zip file.
     *
     * Zip file may not necessary exist.
     * If Zip file exist, then this file will be added to it.
     * If Zip file does not exist, then a new Zip file is created with the file mentioned inside it.
     *
     * ZipPath:  Specify the Zip file Path  (eg. "C:\DestFolder\MyZipFile.zip")
     * FileToAddPath:  Specify the file Path of file to add in the Zip file (eg. "C:\MyFile.avi")
     * CompressionMethod: Specify compression method constant (eg. COMP_DEFLATE, COMP_STORE, COMP_AES_ENC)
     * CompressionLevel:  Specify compression level constant for Deflate compression
     * (eg. DEFLATE_LEVEL_NORMAL, DEFLATE_LEVEL_FAST, DEFLATE_LEVEL_FASTEST, DEFLATE_LEVEL_MAXIMUM, DEFLATE_LEVEL_ULTRA)
     *
     * Note: If the Zip file already exists and if this Zip file is a split file
     * then this method throws an exception as Zip Format Specification does not
     * allow updating split zip files.
     *
     * Return:  True if file was successfully added to the Zip File, else False
     *
     * Raise Events
     * _Progress
     * _Error
     */
    public boolean AddFile(String ZipPath, String FileToAddPath, int CompressionMethod, int CompressionLevel) {   
   
        // Initiate ZipFile object with the path/name of the zip file.
        ZipFile zipFile = new ZipFile(ZipPath);
   
        final String evt = eventName + "_progress";
        final String errEvt = eventName + "_error";
       
        try {   
            Percent = 0; oldPercent = 0;
                         
            // Set true to monitor progress state
            zipFile.setRunInThread(true);
     
            // Initiate Zip Parameters which define various properties such as compression method, etc.
            ZipParameters parameters = new ZipParameters();
     
            // Deflate compression or store(no compression) can be set below
            parameters.setCompressionMethod(CompressionMethodFromInt(CompressionMethod));    
            // Set the compression level. This value has to be in between 0 to 9
            parameters.setCompressionLevel(CompressionLevelFromInt(CompressionLevel));
     
            // Now add file to the zip file
            File file = new File(FileToAddPath);    
            zipFile.addFile(file, parameters);
     
            // Get progress
            if (ba.subExists(evt)) {
                ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
                while (progressMonitor.getState() == ProgressMonitor.State.BUSY) {
                  //BA.Log("Processing. Percent done: " + progressMonitor.getPercentDone());
                    Percent = (int)progressMonitor.getPercentDone();
                    if (oldPercent != Percent) {
                        ba.raiseEvent(this, evt, "AddFile", Percent, false);            
                        oldPercent = Percent;
                    }
                }
     
               // HERE OPERATION IS DONE
                BA.Log("Zip4j: AddFile -> File added to " + ZipPath +
                        "  Result: " + getResultString(progressMonitor.getResult()));
                ba.raiseEvent(this, evt, "AddFile", 100, true);
            } else {
                BA.Log("Zip4j: AddFile -> Sub " + OriginalEventName +
                        "_Progress does not exists. Use Async Mode to add file " + FileToAddPath + " to " + ZipPath);        
            }
     
            return true;
    
        } catch (ZipException e) {
            String err = e.getMessage().replace("net.lingala.zip4j.exception.ZipException: net.lingala.zip4j.exception.ZipException: ", "");
            err = err.replaceAll(":", "");
            //BA.Log("Zip4j: AddFile -> " + err);
            if (ba.subExists(errEvt)) {
                ba.raiseEvent(this, errEvt, "AddFile", err); 
            }
            return false;
        } finally {
            try {
                zipFile.close();
            } catch (IOException e) {
                e.printStackTrace();
                if (ba.subExists(errEvt)) {
                    ba.raiseEvent(this, errEvt, "AddFile", e.getMessage()); 
                }
                return false;
            };
       }               
    }
 
Last edited:

Claudio Oliveira

Active Member
Licensed User
Longtime User
your example is ok; i am able to unzip file.zip, but
which method to use to zip a single file?

B4X:
zipFile.RunMethod("addFile" ......
java.lang.RuntimeException: Method: addFile not matched.
B4X:
zipFIle.RunMethod("addFile", Array("file-to-add"))
This way, the file is added to the zipFile using default parameters.
"Parameters" is a structure with 21 settings that determines how files are handled by zip4j. There are default values for all these settings. Using the syntax above, zip4j will use these default values in your zip task.

If you're curious about what these settings are:
B4X:
    Private mCompressionMethod As String = "DEFLATE"
    Private mCompressionLevel As String = "NORMAL"
    Private mEncryptFiles As Boolean = False
    Private mEncryptionMethod As String = "NONE"
    Private mReadHiddenFiles As Boolean = True
    Private mReadHiddenFolders As Boolean = True
    Private mAesKeyStrength As String = "KEY_STRENGTH_256"
    Private mAesVersion As String = "TWO"
    Private mIncludeRootFolder As Boolean = True
    Private mEntryCRC As Long
    Private mDefaultFolderPath As String
    Private mFileNameInZip As String
    Private mLastModifiedFileTime As Long = 0
    Private mEntrySize As Long = -1
    Private mWriteExtendedLocalFileHeader As Boolean = True
    Private mOverrideExistingFilesInZip As Boolean = True
    Private mRootFolderNameInZip As String
    Private mFileComment As String
    Private msymbolicLinkAction As String = "INCLUDE_LINKED_FILE_ONLY"
    Private mExcludeFileFilter As String
    Private mUnixMode As Boolean
 

max123

Well-Known Member
Licensed User
Longtime User
B4X:
zipFIle.RunMethod("addFile", Array("file-to-add"))
This way, the file is added to the zipFile using default parameters.
"Parameters" is a structure with 21 settings that determines how files are handled by zip4j. There are default values for all these settings. Using the syntax above, zip4j will use these default values in your zip task.

If you're curious about what these settings are:
B4X:
    Private mCompressionMethod As String = "DEFLATE"
    Private mCompressionLevel As String = "NORMAL"
    Private mEncryptFiles As Boolean = False
    Private mEncryptionMethod As String = "NONE"
    Private mReadHiddenFiles As Boolean = True
    Private mReadHiddenFolders As Boolean = True
    Private mAesKeyStrength As String = "KEY_STRENGTH_256"
    Private mAesVersion As String = "TWO"
    Private mIncludeRootFolder As Boolean = True
    Private mEntryCRC As Long
    Private mDefaultFolderPath As String
    Private mFileNameInZip As String
    Private mLastModifiedFileTime As Long = 0
    Private mEntrySize As Long = -1
    Private mWriteExtendedLocalFileHeader As Boolean = True
    Private mOverrideExistingFilesInZip As Boolean = True
    Private mRootFolderNameInZip As String
    Private mFileComment As String
    Private msymbolicLinkAction As String = "INCLUDE_LINKED_FILE_ONLY"
    Private mExcludeFileFilter As String
    Private mUnixMode As Boolean
The online Zip4J javadoc explain these.
You should refer not as String, but instead reference a class with JavaObject as static, then access members like myStatic.DEFLATE_NORMAL
 

Claudio Oliveira

Active Member
Licensed User
Longtime User
Ah ok, thanks, you are not a Java Guru.
Oh, no! Far away from this! 😬
Attached a simplified Javadoc of my library.
Because I cannot post html files I renamed it as .txt, to see it just rename as .html.
Here you can see all methods I've implemented.
Nice! Thank you!
 

Claudio Oliveira

Active Member
Licensed User
Longtime User
The online Zip4J javadoc explain these.
Yeah That's where I got this info...
You should refer not as String, but instead reference a class with JavaObject as static, then access members like myStatic.DEFLATE_NORMAL
Actually I used a different approach. I defined "Parameters" as JavaObject variable, and coded getters and setters for each setting. Actually just some of them, so far...
My code is not fully documented. I've been away from this task for a while now... I'll try to doc it and maybe post it here...
 

max123

Well-Known Member
Licensed User
Longtime User
Maybe some Java Guru can help so finally I release this useful library for both B4J and B4A ?

I even tried a runnable method but it do not handle any zip operation at time.

My old library version without runnables have a _Progress event that show the progress percent, it works well but blocks the GUI.

The version with runnable do no blocks the GUI, but all zip operation are mixed, it manage a single operation on every thread and events on the main app are mixed.

Thanks to everyone can help.
 
Last edited:

max123

Well-Known Member
Licensed User
Longtime User
Claudio, if I remember well, I started it using JavaObject then encountered problems and switched to java.

This is common for all libraries I've ported, so now I will start directly from Java code, that is the right way to develop B4X libraries. IMHO JavaObject is only suited for small libraries.

I even not a Java nerd, but because I use C++ on Arduino IDE this help, the syntax is similar.

If you know it then open the world to new scenarious, eg. now I still port some interesting and powerfull Processing libraries to B4J and B4A, like Firmata library to control Arduino GPIO (and more) from B4J app with Arduino connected via PC or Raspberry USB port.

If you do not know Java, my advice is to start with Processing with simple sketch familiarize a bit, then download BlueJ as I did, or just use Notepad++ or very good PSPad (so you have syntax hilight) and search on the web the Java HelloWorld example. I even started from here. If you know B4X is not difficult.

This even introduce you to create libraries for B4J and B4A, to do it I just started from B4X github repositoties by reading the code of other integrated libraries....

Try it, so when I need something I will ask you 😂
 
Last edited:

Claudio Oliveira

Active Member
Licensed User
Longtime User
Claudio, if I remember well, I started it using JavaObject then encountered problems and switched to java.

This is common for all libraries I've ported, so now I will start directly from Java code, that is the right way to develop B4X libraries. IMHO JavaObject is only suited for small libraries.

I even not a Java nerd, but because I use C++ on Arduino IDE this help, the syntax is similar.

If you know it then open the world to new scenarious, eg. now I still port some interesting and powerfull Processing libraries to B4J and B4A, like Firmata library to control Arduino GPIO (and more) from B4J app with Arduino connected via PC or Raspberry USB port.

If you do not know Java, my advice is to start with Processing with simple sketch familiarize a bit, then download BlueJ as I did, or just use Notepad++ or very good PSPad (so you have syntax hilight) and search on the web the Java HelloWorld example. I even started from here. If you know B4X is not difficult.

This even introduce you to create libraries for B4J and B4A, to do it I just started from B4X github repositoties by reading the code of other integrated libraries....

Try it, so when I need something I will ask you 😂
Thank you so much for your advice, Max! ☺️
You are absolutely right. JavaObject is not suitable for such a demanding task. This is one of the reasons why I´ve decided not to spend too much time in my project, even though it's working 95% ok so far.
Zip4j is quite a complex library and the work involved in designing and coding an "interface" between zip4j and B4J is pretty huge.

I'll try to get deeper into Java and write some stuff, sort of... "Hello World!", just to start... 🤣
When a I get really good at it, you can count on me to help!
 
Top