Files & Compression Β· jdashboardUI Β· B4J Β· Zip4j 2.11.6
ZipFile is jdashboardUI's ZIP service. It wraps Zip4j 2.11.6 and exposes a B4J API for creating, modifying, reading, encrypting, extracting and inspecting ZIP archives.
ZipFileHeader is its companion class. It represents one entry inside the archive and exposes its name, sizes, CRC, compression method, encryption state, timestamp and other metadata.
They are documented together because they form one workflow:
ZipFile
βββ FileNames / getFileName(...)
βββ ZipFileHeader
Highlights
- Create ZIP archives and add one or many files.
- Add complete folders while preserving relative paths.
- SmartCompression: uses
STOREfor formats that are already compressed. - Compression levels from
NO_COMPRESSIONthroughULTRA. - AES and ZIP_STANDARD encryption.
- Built-in source example for AES 256-bit.
- Extract the whole archive or a single entry.
- Read text or bytes directly from the ZIP without extracting.
- Open an entry as an
InputStream. - Add data from an
InputStream. - Rename and remove entries inside an archive.
- Global ZIP comments.
- Configurable charset for names and comments.
- Detect encrypted archives.
- Validate ZIP structure.
- Detect split archives and merge them.
- Background operations through
RunInThread. - Progress, current file/task, completed bytes, pause, resume and cancel.
- Archive statistics.
- Native Zip4j access through
Obj. - Entry inspection through
ZipFileHeader.
Dependency
The jdashboardUI.b4xlib manifest declares:
zip4j-2.11.6.jar
The wrapper is therefore built specifically around Zip4j 2.11.6.
If B4J reports the dependency as missing, make sure zip4j-2.11.6.jar is available in your Additional Libraries folder.
Basic initialization
Private Zip As ZipFile
Private Sub CreateArchive
Dim ZipPath As String = File.Combine(File.DirApp, "backup.zip")
Zip.Initialize(ZipPath)
End Sub
Zip4j creates the archive when the first entry is added.
Password-protected archive
Private Zip As ZipFile
Private Sub OpenEncryptedArchive
Dim ZipPath As String = File.Combine(File.DirApp, "secure.zip")
Zip.InitializeWithPassword(ZipPath, "Secret123")
End Sub
You can also set the password later:
Zip.SetPassword("Secret123")
ZipFile B4X properties
Property-compatible lowercase getX/setX accessors are documented as normal B4X properties.
| Property | Access | Type | Purpose |
|---|---|---|---|
| Obj | read | Object | Native net.lingala.zip4j.ZipFile |
| Obj2 | read | Object | Native-object alias |
| RunInThread | read / write | Boolean | Native background execution |
| SmartCompression | read / write | Boolean | Enables STORE/DEFLATE selection |
| LastError | read | String | Last wrapper error |
| HasError | read | Boolean | True when LastError is not empty |
| Comment | read / write | String | Global ZIP comment |
| FileNames | read | List | List of ZipFileHeader, not Strings |
| FileHeaders | read | List | Native Zip4j FileHeader list |
| ProgressMonitor | read | Object | Native progress monitor |
| IsBusy | read | Boolean | Background operation is active |
| ProgressPercent | read | Int | 0β100 |
| ProgressFile | read | String | Current file |
| ProgressTask | read | String | Current task |
| ProgressState | read | String | Progress state |
| ProgressResult | read | String | Operation result |
| ProgressTotalWork | read | Long | Total work in bytes |
| ProgressCompletedWork | read | Long | Completed work in bytes |
| ProgressError | read | String | Async error message |
| IsPaused | read | Boolean | Operation is paused |
| FileCount | read | Int | Regular-file entry count |
| DirectoryCount | read | Int | Directory-entry count |
| TotalUncompressedSize | read | Long | Total original bytes |
| TotalCompressedSize | read | Long | Total compressed bytes |
| CompressionRatio | read | Double | compressed / original Γ 100 |
Zip.SmartCompression = True
Zip.RunInThread = False
Log(Zip.FileCount)
Log(Zip.TotalCompressedSize)
Log(Zip.HasError)
Clear the wrapper error state with:
Zip.ClearError
Add a file
Simple form:
Zip.addFile(File.Combine(File.DirApp, "report.pdf"))
Configurable form:
Dim Opt As Map = Zip.CreateOptions
Opt.Put("CompressionLevel", Zip.LEVEL_HIGHER)
Dim Ok As Boolean = Zip.AddFile2( _
File.Combine(File.DirApp, "report.pdf"), _
Opt)
If Ok = False Then
Log(Zip.LastError)
End If
Add multiple files
Dim Files As List
Files.Initialize
Files.Add(File.Combine(File.DirApp, "a.txt"))
Files.Add(File.Combine(File.DirApp, "b.txt"))
Files.Add(File.Combine(File.DirApp, "photo.jpg"))
Zip.addFiles(Files)
With options:
Dim Opt As Map = Zip.CreateOptions
Opt.Put("CompressionLevel", Zip.LEVEL_ULTRA)
If Zip.AddFiles2(Files, Opt) = False Then
Log(Zip.LastError)
End If
SmartCompression note for AddFiles2
The current implementation creates one ZipParameters object for the complete list. It does not call ShouldStore for every file.
For mixed file types and true per-file SmartCompression, call AddFile2 for each file or use smart folder compression.
Add folders
Zip.AddFolder(File.DirApp, "data")
With options:
Dim Opt As Map = Zip.CreateOptions
Opt.Put("IncludeRootFolder", True)
Dim Ok As Boolean = Zip.AddFolder2( _
File.Combine(File.DirApp, "data"), _
Opt)
Smart folder compression
Zip.SmartCompression = True
If Zip.AddFolderSmart(File.Combine(File.DirApp, "assets")) = False Then
Log(Zip.LastError)
End If
Smart folder mode scans the directory, preserves relative paths, adds truly empty folders, and chooses the compression method per file.
SmartCompression
Zip.SmartCompression = True
or:
Dim Opt As Map = Zip.CreateOptions
Opt.Put("Smart", True)
ShouldStore treats these formats as already compressed:
.zip .7z .rar .gz .jar
.png .jpg .jpeg .webp .gif
.mp3 .aac .ogg
.mp4 .mkv .webm
.woff .woff2
Those use STORE; other files use DEFLATE.
If Zip.ShouldStore("photo.jpg") Then
Log("STORE is preferred")
End If
Smart folders and async mode
Smart folder compression adds entries one by one. For predictable behavior, use it synchronously. If you need one native background folder operation, disable SmartCompression for that operation.
Compression levels
Public constants:
LEVEL_NO_COMPRESSION, LEVEL_FASTEST, LEVEL_FASTER, LEVEL_FAST, LEVEL_MEDIUM_FAST, LEVEL_NORMAL, LEVEL_HIGHER, LEVEL_MAXIMUM, LEVEL_PRE_ULTRA, LEVEL_ULTRA.
Dim Opt As Map = Zip.CreateOptions
Opt.Put("CompressionLevel", Zip.LEVEL_NORMAL)
Zip.AddFile2(File.Combine(File.DirApp, "database.db"), Opt)
CreateOptions defaults to LEVEL_ULTRA.
CreateOptions
Dim Opt As Map = Zip.CreateOptions
Default values:
| Key | Default |
|---|---|
| IncludeRootFolder | False |
| CompressionLevel | LEVEL_ULTRA |
| CompressionMethod | DEFLATE |
| Smart | current SmartCompression value |
| OverrideExistingFilesInZip | True |
| ReadHiddenFiles | True |
| ReadHiddenFolders | True |
Advanced option keys
CreateZipParameters recognizes:
| Key | Purpose |
|---|---|
| CompressionMethod | STORE or DEFLATE |
| CompressionLevel | LEVEL_* value |
| IncludeRootFolder | Include root directory |
| RootFolderNameInZip | Root path/name inside ZIP |
| OverrideExistingFilesInZip | Replace existing entries |
| EncryptFiles | Enable encryption |
| EncryptionMethod | AES or ZIP_STANDARD |
| AesKeyStrength | AES key-strength enum name |
| ReadHiddenFiles | Include hidden files |
| ReadHiddenFolders | Include hidden directories |
| SymbolicLinkAction | Symbolic-link action enum |
| UnixMode | Unix mode |
| LastModifiedFileTime | Entry timestamp |
| WriteExtendedLocalFileHeader | Extended local header |
| FileNameInZip | Exact entry path/name |
| FileComment | Entry comment |
For low-level use:
Dim NativeParams As JavaObject = Zip.CreateZipParameters(Opt)
Place content in a folder inside the ZIP
Zip.AddFileToFolder( _
File.Combine(File.DirApp, "logo.png"), _
"assets/images")
Zip.AddFilesToFolder(Files, "documents")
Zip.AddFolderToFolder( _
File.Combine(File.DirApp, "web"), _
"backups/v1")
Add an InputStream
AddStream2 is the safest stream helper because it explicitly receives the ZIP entry name:
Dim In As InputStream = File.OpenInput(File.DirApp, "settings.json")
Dim Opt As Map = Zip.CreateOptions
If Zip.AddStream2(In, "config/settings.json", Opt) = False Then
Log(Zip.LastError)
End If
In.Close
With AddStream, put FileNameInZip in the options Map.
AES encryption
Dim Zip As ZipFile
Dim ZipPath As String = File.Combine(File.DirApp, "secure.zip")
Zip.InitializeWithPassword(ZipPath, "Secret123")
Dim Opt As Map = Zip.CreateOptions
Opt.Put("EncryptFiles", True)
Opt.Put("EncryptionMethod", "AES")
Opt.Put("AesKeyStrength", "KEY_STRENGTH_256")
If Zip.AddFile2(File.Combine(File.DirApp, "private.pdf"), Opt) = False Then
Log(Zip.LastError)
End If
KEY_STRENGTH_256 is used by the wrapper's own saveZipCPassword implementation.
ZIP Standard
Dim Opt As Map = Zip.CreateOptions
Opt.Put("EncryptFiles", True)
Opt.Put("EncryptionMethod", "ZIP_STANDARD")
Zip.AddFile2(File.Combine(File.DirApp, "private.txt"), Opt)
Legacy saveZipCPassword helper
Zip.saveZipCPassword(ZipPath, Files, "Secret123")
Internally it creates another ZipFile instance, enables AES and uses KEY_STRENGTH_256.
For new code, the explicit InitializeWithPassword + CreateOptions + AddFile2/AddFiles2 flow is preferable because it exposes return values and errors directly.
Extract all files
Zip.ExtractAll(File.Combine(File.DirApp, "extracted"))
Encrypted archive:
Dim Zip As ZipFile
Zip.InitializeWithPassword( _
File.Combine(File.DirApp, "secure.zip"), _
"Secret123")
Zip.ExtractAll(File.Combine(File.DirApp, "output"))
Convenience helper:
Zip.ExtractZipWithPassword( _
File.Combine(File.DirApp, "secure.zip"), _
File.Combine(File.DirApp, "output"), _
"Secret123")
Extract one entry
Zip.ExtractFile( _
"docs/manual.pdf", _
File.Combine(File.DirApp, "output"))
Read without extracting
Text
Dim JsonText As String = Zip.ReadText( _
"config/settings.json", _
"UTF-8")
An empty charset defaults to UTF-8.
Bytes
Dim Data() As Byte = Zip.ReadBytes("images/logo.png")
ReadBytes loads the complete entry into memory. Use GetInputStream for large entries.
Read through InputStream
Dim Header As ZipFileHeader = Zip.getFileName("video/data.bin")
If Header <> Null Then
Dim In As InputStream = Zip.GetInputStream(Header)
' Process stream...
In.Close
End If
getFileName(filename) remains a method because it takes an argument.
List archive contents
Despite its historical name, FileNames returns ZipFileHeader objects, not Strings:
For Each Header As ZipFileHeader In Zip.FileNames
Log(Header.FileName)
Next
Detailed inspection:
For Each Header As ZipFileHeader In Zip.FileNames
Log("Name: " & Header.FileName)
Log("Directory: " & Header.IsDirectory)
Log("Encrypted: " & Header.IsEncrypted)
Log("Method: " & Header.CompressionMethod)
Log("Original: " & Header.UncompressedSize)
Log("Compressed: " & Header.CompressedSize)
Next
The raw native list is available as:
Dim NativeHeaders As List = Zip.FileHeaders
ZipFileHeader wraps net.lingala.zip4j.model.FileHeader.
You normally receive it from Zip.FileNames or Zip.getFileName(...).
ZipFileHeader properties
| Property | Access | Type | Description |
|---|---|---|---|
| Obj | read / write | Object | Native FileHeader |
| FileName | read / write | String | Internal entry path |
| LastModifiedTime | read | Long | Epoch milliseconds |
| UncompressedSize | read | Long | Original bytes |
| CompressedSize | read | Long | Compressed bytes |
| Crc | read | Long | CRC-32 |
| IsDirectory | read | Boolean | Directory entry |
| CompressionMethod | read | String | DEFLATE, STORE, etc. |
| IsEncrypted | read | Boolean | Entry encryption state |
| FileComment | read | String | Entry comment |
| OffsetLocalHeader | read | Long | Local-header offset |
FileName does not rename the stored entry
Header.FileName = "new-name.txt"
only changes the in-memory header object.
Rename the actual ZIP entry with:
Zip.RenameFile("old-name.txt", "new-name.txt")
Rename entries
Zip.RenameFile("docs/old.txt", "docs/new.txt")
Batch rename:
Dim RenameMap As Map
RenameMap.Initialize
RenameMap.Put("a.txt", "archive/a.txt")
RenameMap.Put("b.txt", "archive/b.txt")
Zip.RenameFiles(RenameMap)
Remove entries
Zip.RemoveFile("old.log")
Batch removal:
Dim RemoveList As List
RemoveList.Initialize2(Array As String( _
"temp/a.tmp", _
"temp/b.tmp"))
Zip.RemoveFiles(RemoveList)
ZIP comment
Because lowercase getComment/setComment are a valid B4X accessor pair, use normal property syntax:
Zip.Comment = "Backup generated by my B4J app"
Log(Zip.Comment)
Charset
Zip.SetCharset("UTF-8")
Log(Zip.GetCharset)
SetCharset and GetCharset start with uppercase letters, so they remain normal methods rather than a B4X property pair.
Validate an archive
If Zip.ValidateArchive Then
Log("Valid ZIP")
Else
Log(Zip.LastError)
End If
Compatibility alias:
If Zip.IsValidZipFile Then
Log("Valid ZIP")
End If
Encrypted archive detection
If Zip.IsEncrypted Then
Log("Password protected")
End If
Split archives
If Zip.IsSplitArchive Then
Zip.MergeSplitFiles(File.Combine(File.DirApp, "merged.zip"))
End If
The current public wrapper exposes split-archive detection and merging. It does not expose a dedicated public API for creating split archives.
GetCapabilities reports SplitZip = True; in this wrapper that should be interpreted as support for handling existing split archives.
Background execution
Zip.RunInThread = True
Dim Opt As Map = Zip.CreateOptions
Zip.AddFolder2(File.Combine(File.DirApp, "large-folder"), Opt)
Monitor progress with a Timer:
Sub Class_Globals
Private Zip As ZipFile
Private ProgressTimer As Timer
End Sub
Private Sub StartBackup
Zip.Initialize(File.Combine(File.DirApp, "backup.zip"))
Zip.RunInThread = True
Zip.SmartCompression = False
ProgressTimer.Initialize("ProgressTimer", 200)
ProgressTimer.Enabled = True
Dim Opt As Map = Zip.CreateOptions
Zip.AddFolder2(File.Combine(File.DirApp, "data"), Opt)
End Sub
Private Sub ProgressTimer_Tick
Log("Task: " & Zip.ProgressTask)
Log("File: " & Zip.ProgressFile)
Log("Progress: " & Zip.ProgressPercent & "%")
If Zip.IsBusy = False Then
ProgressTimer.Enabled = False
Log("Result: " & Zip.ProgressResult)
If Zip.ProgressError <> "" Then
Log("Error: " & Zip.ProgressError)
End If
End If
End Sub
For background operations, the final result belongs to ProgressResult / ProgressError.
Pause, resume and cancel
Zip.Pause
Log(Zip.IsPaused)
Zip.Resume
Zip.Cancel
Progress properties
Log(Zip.IsBusy)
Log(Zip.ProgressPercent)
Log(Zip.ProgressFile)
Log(Zip.ProgressTask)
Log(Zip.ProgressState)
Log(Zip.ProgressResult)
Log(Zip.ProgressTotalWork)
Log(Zip.ProgressCompletedWork)
Log(Zip.ProgressError)
Expected native state/result strings include:
ProgressState:
READY
BUSY
ProgressResult:
SUCCESS
WORK_IN_PROGRESS
ERROR
CANCELLED
Archive statistics
Log("Files: " & Zip.FileCount)
Log("Folders: " & Zip.DirectoryCount)
Log("Original bytes: " & Zip.TotalUncompressedSize)
Log("ZIP bytes: " & Zip.TotalCompressedSize)
Log("Ratio: " & Zip.CompressionRatio & "%")
CompressionRatio semantics
The wrapper calculates:
TotalCompressedSize * 100 / TotalUncompressedSize
So:
100%β no size reduction.50%= archive is about half the original size.25%= archive is about one quarter of the original size.
Savings percentage:
Dim SavedPercent As Double = 100 - Zip.CompressionRatio
Capabilities
Dim Caps As Map = Zip.GetCapabilities
The wrapper declares:
Streams, AsyncProgress, Pause, Cancel, AES, ZipStandard, SplitZip, RenameMultiple, RemoveMultiple, SymbolicLinks, Charset, Zip64, SmartCompression.
Native Zip4j access
Dim NativeZip As JavaObject = Zip.Obj
A read-only Obj2 alias is also present.
Use native access only for Zip4j features not wrapped by the B4J API.
Close
Zip.Close
This releases open Zip4j file handles.
Complete example: smart encrypted backup
Sub CreateSecureBackup
Dim Zip As ZipFile
Dim OutputZip As String = File.Combine(File.DirApp, "backup-secure.zip")
Dim SourceFolder As String = File.Combine(File.DirApp, "data")
Zip.InitializeWithPassword(OutputZip, "Secret123")
Zip.SmartCompression = True
Dim Opt As Map = Zip.CreateOptions
Opt.Put("IncludeRootFolder", True)
Opt.Put("CompressionLevel", Zip.LEVEL_ULTRA)
Opt.Put("EncryptFiles", True)
Opt.Put("EncryptionMethod", "AES")
Opt.Put("AesKeyStrength", "KEY_STRENGTH_256")
If Zip.AddFolder2(SourceFolder, Opt) = False Then
Log("ZIP error: " & Zip.LastError)
Return
End If
Zip.Comment = "Encrypted application backup"
Log("Files: " & Zip.FileCount)
Log("Compressed: " & Zip.TotalCompressedSize)
Log("Original: " & Zip.TotalUncompressedSize)
Log("Size ratio: " & NumberFormat(Zip.CompressionRatio, 1, 2) & "%")
Zip.Close
End Sub
ZipFile public API
Initialization/configuration: Initialize, InitializeWithPassword, SetPassword, SetCharset, GetCharset, Close, ClearError, ShouldStore, CreateOptions, CreateZipParameters.
Add content: addFile, AddFile2, addFiles, AddFiles2, AddFolder, AddFolderWithParameters, AddFolder2, AddFolderSmart, AddFileToFolder, AddFilesToFolder, AddFolderToFolder, AddStream, AddStream2.
Extract/read: ExtractAll, ExtractFile, ExtractZipWithPassword, GetInputStream, ReadText, ReadBytes.
Encryption: InitializeWithPassword, SetPassword, saveZipCPassword.
Modify archive: RemoveFile, RemoveFiles, RenameFile, RenameFiles.
Inspect: getFileName(filename), IsEncrypted, IsSplitArchive, ValidateArchive, IsValidZipFile, MergeSplitFiles, GetCapabilities.
Async control: Cancel, Pause, Resume.
Property-compatible getX/setX members are shown as B4X properties instead of literal accessor calls.
ZipFileHeader public API
Normal methods: Initialize, isDirectory.
B4X properties: Obj, FileName, LastModifiedTime, UncompressedSize, CompressedSize, Crc, IsDirectory, CompressionMethod, IsEncrypted, FileComment, OffsetLocalHeader.
Best practices
- Prefer
AddFile2,AddFolder2andAddStream2when you need explicit options and error handling. - Check
LastError/HasErrorafter void operations. - Use
GetInputStreaminstead ofReadBytesfor very large entries. - For new encrypted archives, prefer the explicit password + AES options flow.
- Use
ZipFileHeaderfor inspection; changingHeader.FileNamedoes not rename the stored archive entry. - Use smart folder compression synchronously when you need per-entry STORE/DEFLATE selection.
- Call
Closewhen finished.