Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Making the content list of files inside a Zip ?
#11
Here my version of the program making list of files into a ZIP(with name, sizes, date, hour)
(compatible QB64 & QB64pe, Win)

Code: (Select All)
'See useful informations about ZIP header --> 'https://medium.com/@felixstridsberg/the-zip-file-format-6c8a160d1c34
'This version by Euklides
'Objet: create a list of files placed into a zip file (name, compressed and normal sizes, date , time)
'Works with  .ZIP files, .EPUB files & .CBZ files

'---put your ZIP file here---
fi$ = "D:\temp\essai.zip"
'-------------------------

Close #1: Open fi$ For Binary As #1: txe$ = Space$(LOF(1)): Get #1, , txe$: Close #1
Amorce$ = "PK" + Chr$(3) + Chr$(4): jj = 1: jj = InStr(jj, txe$, Amorce$) + 2: NBFILE = 0
Refait: jk = InStr(jj, txe$, Amorce$): jj = jk + 1
If jk = 0 Then GoTo Fino
'---------sizes (compress, normal) name of the included files
Bloc$ = Mid$(txe$, jk + 18, 4): GoSub Converti: XVolCompress = AV#
Bloc$ = Mid$(txe$, jk + 22, 4): GoSub Converti: XVolNormal = AV#
Bloc$ = Mid$(txe$, jk + 25, 2): largeur = Asc(Mid$(Bloc$, 1, 1)) * 256 + Asc(Mid$(Bloc$, 2, 1))
XName$ = Mid$(txe$, jk + 30, largeur): NBFILE = NBFILE + 1
'---------Date of file
Zonedate$ = Mid$(txe$, jk + 12, 2): OCTETDATE$ = "":
QQ = Asc(Mid$(Zonedate$, 2, 1)): GoSub OCTETBIT: OCTETDATE$ = oc$
QQ = Asc(Mid$(Zonedate$, 1, 1)): GoSub OCTETBIT: OCTETDATE$ = OCTETDATE$ + oc$
oc$ = Right$(OCTETDATE$, 5): GoSub BITOCTET: XDAY = QQ:
oc$ = Mid$(OCTETDATE$, 8, 4): GoSub BITOCTET: XMONTH = QQ
oc$ = Left$(OCTETDATE$, 7): GoSub BITOCTET: XYEAR = QQ + 1980
'---------time of the file
Zoneheure$ = Mid$(txe$, jk + 10, 2): OCTETDATE$ = ""
QQ = Asc(Mid$(Zoneheure$, 2, 1)): GoSub OCTETBIT: OCTETDATE$ = oc$
QQ = Asc(Mid$(Zoneheure$, 1, 1)): GoSub OCTETBIT: OCTETDATE$ = OCTETDATE$ + oc$
oc$ = Right$(OCTETDATE$, 5): GoSub BITOCTET: XHOUR = QQ
oc$ = Mid$(OCTETDATE$, 6, 6): GoSub BITOCTET: XMINU = QQ
oc$ = Left$(OCTETDATE$, 5): GoSub BITOCTET: XSEC = QQ * 2
'---------using informations here (example)
' File Name |chr$(124) Size compressed chr$(124) Normal size
T$ = XName$ + "|" + _Trim$(Str$(XVolCompress)) + "|" + _Trim$(Str$(XVolNormal))
'date  YYYY~MM~DD
XDATE$ = Right$(Str$(XYEAR + 10000), 4) + "~" + Right$(Str$(100 + XMONTH), 2) + "~" + Right$(Str$(100 + XDAY), 2)
T$ = T$ + "|" + XDATE$
'TIME: hh:mm:ss  Not very significant because it depends on the place of creation of the ZI ¨P
XTIME$ = Right$(Str$(XHOUR + 100), 2) + ":" + Right$(Str$(XMINU + 100), 2) + ":" + Right$(Str$(XSEC + 100), 2)
T$ = T$ + "|" + XTIME$
Print T$: 'input kk$
'---next file
GoTo Refait
'---end
Fino:
Print fi$
Print "Number of files: "; NBFILE
End

Converti: '-------------in bloc$ with 1,2,3 or 4 bytes to convert to numerical value
If Len(Bloc$) < 3 Then Bloc$ = Left$(Bloc$ + Chr$(0) + Chr$(0) + Chr$(0), 4)
A1 = Asc(Mid$(Bloc$, 1, 1)): A2 = Asc(Mid$(Bloc$, 2, 1)): A3 = Asc(Mid$(Bloc$, 3, 1)): A4 = Asc(Mid$(Bloc$, 4, 1))
AV# = A0 + (A2 * 256) + (A3 * 256 * 256) + (A4 * 256 * 256 * 256)
Return
OCTETBIT: '------------- in QQ out  oc$
oc$ = ""
Bito: QQ = QQ / 2: If QQ <> Int(QQ) Then oc$ = "1" + oc$ Else oc$ = "0" + oc$
If Int(QQ) > 0 Then QQ = Int(QQ): GoTo Bito
oc$ = Right$("000000000" + oc$, 8): Return
BITOCTET: '------------- bin  oc$ out  QQ
DECAoc: If Left$(oc$ + "x", 1) = "0" Then oc$ = Right$(oc$, Len(oc$) - 1): GoTo DECAoc
If oc$ = "" Then QQ = 0: Return
QQ = Val(Left$(oc$, 1))
For xo = 2 To Len(oc$): If Mid$(oc$, xo, 1) = "0" Then QQ = QQ * 2 Else QQ = (QQ * 2) + 1
Next xo: Return
Why not yes ?
Reply
#12
Be aware that all versions above read filedata from the file entries itself. Which might be deleted/removed from the zipfile.
The correct central directory is at the end of the zip and gets rewritten everytime the zipfile is updated.
The central directory signature is Chr$(&H50) + Chr$(&H4B) + Chr$(&H01) + Chr$(&H02)

Also above code stops working with zipfiles larger then 2GB or ZIP64 extension

See below my version also retrieving date/time/size:
Code: (Select All)
Type fdType
Date As String * 10
Time As String * 8
Size As _Unsigned _Integer64
fName As String
End Type
ReDim Shared As fdType f(1000), d(1000)

Function processZip& (zipFile$)
  Const MAXCDIR = 2000000000
  Dim c As String
  Open zipFile$ For Binary Access Read As #1
  If LOF(1) < MAXCDIR Then
    c = String$(LOF(1), 0)
  Else
    c = String$(MAXCDIR, 0)
    Seek #1, LOF(1) - MAXCDIR + 1
  End If
  Get #1, , c
  Close #1
  Dim s As _Unsigned Long, fd As fdType, sig As String
  sig = Chr$(&H50) + Chr$(&H4B) + Chr$(&H01) + Chr$(&H02)
  fileCount& = 0: dirCount& = 0
  s = InStr(c, sig)
  Do
    If Mid$(c, s, 4) <> sig Then Exit Do
    tim~% = CVI(Mid$(c, s + 12, 2))
    th% = _ShR(tim~%, 11): tm% = _ShR(tim~%, 5) Mod (2 ^ 6): ts% = _ShL(tim~%, 1) Mod (2 ^ 6)
    dat~% = CVI(Mid$(c, s + 14, 2))
    dy% = 1980 + _ShR(dat~%, 9): dm% = _ShR(dat~%, 5) Mod (2 ^ 4): dd% = dat~% Mod (2 ^ 5)
    siz~&& = CVL(Mid$(c, s + 24, 4))
    flen~% = CVI(Mid$(c, s + 28, 2))
    xlen~% = CVI(Mid$(c, s + 30, 2))
    clen~% = CVI(Mid$(c, s + 32, 2))
    'iatt~% = CVI(Mid$(c, s + 36, 2))
    'xatt~% = CVL(Mid$(c, s + 38, 4))
    xfld$ = Mid$(c, s + 46 + flen~%, xlen~%)
    'cfld$ = Mid$(c, s + 46 + flen~% + xlen~%, clen~%)
    If xfld$ <> "" Then
      xtype~% = CVI(Left$(xfld$, 2))
      If xtype~% = 1 Then 'ZIP64
        'Print "xfld=";: For i% = 1 To xlen~%: Print Right$("0" + Hex$(Asc(xfld$, i%)), 2); " ";: Next i%: Print
        siz~&& = _CV(_Unsigned _Integer64, Mid$(xfld$, 5, 8))
        'Print siz~&&
      End If
    End If
    If th% < 24 And tm% < 60 And ts% < 60 And dy% < Val(Right$(Date$, 4)) And dm% > 0 And dm% < 13 And dd% > 0 And dd% < 32 And flen~% < 1024 And xlen~% <= 64 And clen~% < 1024 Then
      fd.fName = Mid$(c, s + 46, flen~%)
      fd.Date = LTrim$(Str$(dy%)) + "-" + Right$("0" + LTrim$(Str$(dm%)), 2) + "-" + Right$("0" + LTrim$(Str$(dd%)), 2)
      fd.Time = Right$("0" + LTrim$(Str$(th%)), 2) + ":" + Right$("0" + LTrim$(Str$(tm%)), 2) + ":" + Right$("0" + LTrim$(Str$(ts%)), 2)
      fd.Size = siz~&&
      'Print "Name="; fd.fName; "|"
      'Print "Date="; fd.Date;
      'Print " Time="; fd.Time;
      'Print " Size="; fd.Size
      'Print "iatt="; iatt~%, "xatt="; xatt~%
      'Print "flen="; flen~%; "xlen="; xlen~%; "clen="; clen~%
      'Print "Comment="; cfld$; "|"

      If Right$(fd.fName, 1) = "/" Then
        If dirCount& = UBound(d) Then ReDim _Preserve As fdType d(dirCount& + 1000)
        dirCount& = dirCount& + 1
        fd.Attrib = "D????"
        d(dirCount&) = fd
      Else
        If fileCount& = UBound(f) Then ReDim _Preserve As fdType f(fileCount& + 1000)
        fileCount& = fileCount& + 1
        fd.Attrib = ".????"
        f(fileCount&) = fd
      End If
      s = s + 46 + flen~% + xlen~% + clen~%
    Else
      s = InStr(s + 1, c, sig)
    End If
  Loop
  ReDim _Preserve As fdType d(dirCount&), f(fileCount&)
  processZip& = fileCount& + dirCount&
End Function
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#13
Interesting stuff. You could probably handle much larger zip files if you weren't getting it all into the string at once.
Tread on those who tread on you

Reply
#14
Yes, of course,SpriggsySpriggsNot to use for very big zip files ...

For my little use, quick listing the content of  .epub (generally they have a size <10000ko), it works.
Why not yes ?
Reply




Users browsing this thread: 6 Guest(s)