Technical Support
🟒 Online now
Hello πŸ‘‹

How can we help you today?
Contact on WhatsApp
B4X Store
jdashboardUI / Files & Compression / ZipFile + ZipFileHeader
Files & Compression

ZipFile + ZipFileHeader

Advanced ZIP with SmartCompression, AES, streams, async progress and entry inspection

Source
jdashboardUI.b4xlib Β· Public API only
Store language: en

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 STORE for formats that are already compressed.
  • Compression levels from NO_COMPRESSION through ULTRA.
  • 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, AddFolder2 and AddStream2 when you need explicit options and error handling.
  • Check LastError / HasError after void operations.
  • Use GetInputStream instead of ReadBytes for very large entries.
  • For new encrypted archives, prefer the explicit password + AES options flow.
  • Use ZipFileHeader for inspection; changing Header.FileName does not rename the stored archive entry.
  • Use smart folder compression synchronously when you need per-entry STORE/DEFLATE selection.
  • Call Close when finished.