B4J Question Packing Latyouts in b4xlib

stevel05

Expert
Licensed User
Longtime User
I am trying to write a manager utility to assist with packaging B4xlibs using files from the project folders and I have a problem packing layouts. It seems that all of the zip libraries pack the files at a byte level which corrupts layout files and renders them unusable in the library.

I have currently got around this for my own use by using 7zip from a shell and creating an archive that way, which just packs the original files as they are and works.

I have tried packing them as uncompressed files with the existing libraries, but it seems that the act of transferring them as bytes corrupts them.

My question is, has anybody been able to successfully pack a layout file in a .b4xlib zipped file using one of the available libraries i.e. Archiver, zt-lib or the java.util.zip classes (or any other) and how do you do it?

This would provide a better solution than making everybody that wants to try it use 7zip, or having to rewrite the shell code to use their preferred Zip tool. I've spent 2 days trying to crack this and thought I would ask the community for help at this stage, I realise that I am not overly familiar with the structure of zip files and may be missing something pretty basic.

As usual this tool will be available to all, so if you can help, it may be of benefit to the whole community.

Code I have tried with zt-lib:

B4X:
'    Attempt with zt-zip
'    ___________________

    Dim L As List
    L.Initialize
 
    For Each S As String In ExportedModules
        Dim FS As FileSource
        FS.Initialize
        FS.Create(S,lblProjectFolder.Text,S)
        L.Add(FS)
    Next
 
    For Each S As String In ExportedFiles
        Dim FS As FileSource
        FS.Initialize
        FS.Create("Files\" & S,File.Combine(lblProjectFolder.Text,"Files"),S)
        'Create the file uncomressed
        FS.GetEntry.SetMethod(ZipEntry_Static.STORED)
        L.Add(FS)
        Log(FS.GetEntry.GetMethod)
  
    Next
 
    Dim FS As FileSource
    FS.Initialize
    FS.Create("Manifest.txt",lblProjectFolder.Text,"Manifest.txt")
    L.Add(FS)
 
    Try
        ZipUtils.Pack3(Utils.ListToArray(L),lblB4xLibDeploy.Text,Name)
    Catch
        Dialog.Title = "File write Error"
        Wait For (Dialog.Show($"Failed to create Zip file ${CRLF}Is the file open in your zip tool?"$,"OK","","")) Complete (Resp As Int)
        Return
    End Try

and with java.util.zip

B4X:
'    Attempt with java zip
    _____________________

    Dim L As List
    L.Initialize
 
    For Each S As String In ExportedModules
        L.Add(S)
    Next
 
    L.Add("Manifest.txt")
 
    For Each S As String In ExportedFiles
        L.Add("Files\" & S)
    Next
 
    Try
        Dim FOS As OutputStream = File.OpenOutput(lblB4xLibDeploy.Text,tfLibName.Text & LibExtension,False)
        Dim ZipOut As JavaObject
    ZipOut.InitializeNewInstance("java.util.zip.ZipOutputStream",Array(FOS,ChrSet.RunMethod("forName",Array("NTFS"))))
        ZipOut.InitializeNewInstance("java.util.zip.ZipOutputStream",Array(FOS))
        'Write files in uncompressed format
        ZipOut.RunMethod("setLevel",Array(ZipOut.GetField("STORED")))
 
 
        For Each S As String In L
            Log(S)
            '            If S.StartsWith("Files") Then ZipOut.RunMethod("setLevel",Array(ZipOut.GetField("STORED")))
            Dim FIS As InputStream = File.OpenInput(lblProjectFolder.Text,S)
            Dim ZE As JavaObject
            ZE.InitializeNewInstance("java.util.zip.ZipEntry",Array(S))
            ZipOut.RunMethod("putNextEntry",Array(ZE))
  
            Dim Bytes(1024) As Byte
            Dim Length As Int = 1024
            Do While True
                Length = FIS.ReadBytes(Bytes,0,Length)
                If Length = -1 Then Exit
                ZipOut.RunMethod("write", Array(Bytes,0,Length))
            Loop
            FIS.Close
        Next
        ZipOut.RunMethod("close",Null)
        FOS.Close
    Catch
        Log(LastException)
        Dialog.Title = "File write Error"
        Wait For (Dialog.Show($"Failed to create Zip file ${CRLF}Is the file open in your zip tool?"$,"OK","","")) Complete (Resp As Int)
        Return
    End Try
 
    lblWriteInfo.Text = DateTime.Date(File.LastModified(lblB4xLibDeploy.Text,Name))
 
    Dialog.Title = "Deploy Success"
    Wait For (Dialog.Show("Library " & tfLibName.Text & LibExtension & " saved at " & lblWriteInfo.Text ,"OK","","")) Complete (Resp As Int)

In both examples ExportedModules and ExportedFiles just contain the filenames.

Screenshot for the current utility.

upload_2019-11-17_22-38-42.png
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Not 100% certain, but don't FIS and FOS need to be FileInputStream / FileOutputStream respectively, as opposed to plain InputStream/OutputStream streams.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Assuming that the JDK is installed, you can use this code to archive a folder:
B4X:
Sub ArchiveFolder (folder As String, target As String)
   Dim jar As String = File.Combine(GetSystemProperty("java.home", ""), "../bin/jar.exe")
   If File.Exists(jar, "") = False Then
       Log("jar.exe not found!")
       Return
   End If
   File.Delete(target, "")
   Dim shl As Shell
   shl.Initialize("shl", jar, Array("-cvfM", target, "*"))
   shl.WorkingDirectory = folder
   shl.Run(-1)
   Wait For shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
   If Success And ExitCode = 0 Then
       Log("Success")
   Else
       Log("Error: " & StdOut & CRLF & StdErr)
   End If
End Sub
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Not 100% certain, but don't FIS and FOS need to be FileInputStream / FileOutputStream respectively, as opposed to plain InputStream/OutputStream streams.
Thansk Daestrum, just tried that, same results unfortunately.
 
Upvote 0
Top