.z (zlip) Entpacken

  • VB.NET

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    Flush ist unnötig, passiert dann spätestens beim Close sowieso.
    und Streams muss man auch nicht schließen, wenn man sie in einem using verwendet.

    Ein using ist dafür da, um Resourcen innerhalb eines Scopes zu verwenden und beim verlassen dieses scopes automatisch aufzuräumen, d.h. auf Streams wird Close und Dispose aufgerufen.
    Bei IDisposables nur Dispose z.B.

    Dann sollte das Programm theoretisch stehen.
    Aber noch immer fehlt die Überprüfung des Magics, damit verhinderst du, dass du versuchst eine Datei mit dem falschen Format zu öffnen.

    Die Datei oben hab ich bereits gesehen, sonst hätte ich unmöglich so viel über das Format herausbekommen. Aber die hat eben nur 1en run, interessant sind dateien mit mehr als einem run
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Leider habe ich keine Datei mit mehr als einem runs.

    Habe jetzt eine If Abfrage als Validierung genutzt um falsche Dateien zu übergehen:

    VB.NET-Quellcode

    1. Dim zielfilename As String = Path.GetFileNameWithoutExtension(zfile.FullName)
    2. Dim h As New Header
    3. Dim fh As New Fileheader
    4. Dim _dLen As UInteger = 8192
    5. Dim _d As Byte() = New Byte(_dLen - 1) {}
    6. Dim count As Integer
    7. Dim outputbyte() As Byte
    8. Using src As FileStream = File.Open(zfile.FullName, FileMode.Open)
    9. Using reader As New BinaryReader(src)
    10. h.magic = reader.ReadUInt64()
    11. h.size1 = reader.ReadUInt64
    12. h.unknow = reader.ReadUInt64()
    13. h.size2 = reader.ReadUInt64
    14. If h.magic = 2653586369 Then
    15. Dim bytesout As Byte()
    16. Dim runs As ULong
    17. runs = (h.size1 + h.size2 - 1) / h.size1
    18. Dim array As New List(Of Fileheader)
    19. Dim uebergabe As New Fileheader
    20. For o As Integer = 0 To runs - 1 Step 1
    21. uebergabe.compressedSize = reader.ReadUInt64
    22. uebergabe.uncompressedSize = reader.ReadUInt64()
    23. array.Add(uebergabe)
    24. Next
    25. Using dest As FileStream = File.Open("c:\test.u", FileMode.Create, FileAccess.Write)
    26. For i As Integer = 0 To runs - 1 Step 1
    27. Dim to_read As ULong = array(i).compressedSize
    28. Dim compressed As Byte() = reader.ReadBytes(to_read)
    29. Using ms As New MemoryStream(compressed)
    30. Using ds As New Compression.DeflateStream(ms, Compression.CompressionMode.Decompress)
    31. ds.CopyTo(dest)
    32. End Using
    33. End Using
    34. Next
    35. Return True
    36. End Using
    37. Else
    38. Console.WriteLine("Die Datei " & zfile.Name & " hat ein falsches Format")
    39. End If
    40. End Using
    41. End Using


    Bekomme aber einen Fehler bei ds.copy:
    Zusätzliche Informationen: Die Blocklänge entspricht nicht dem Komplement.
    ähh? wasn das :)
    aha, es handelt sich um zlib spezifikation und nicht deflate. Aber ich denke wir können davon ausgehen, dass es sich immer um deflate handelt, d.h.

    Du musst in der Schleife von Zeile 30 einen ushort lesen

    Visual Basic-Quellcode

    1. Dim zlibHeader As UShort = reader.ReadUInt16()

    und in Zeile 31 zwei von der compressed Size abziehen, dann sollte es funktionieren
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Vielen Dank!

    Warum muss ich ein Ushort nehmen, und warum -2 ?

    Wie kann ich mich bei Dir für deine Hilfe bedanken?!

    Hier die Lösung für wie entpacke ich eine .z File:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Structure Header
    3. Dim magic, size1, unknow, size2 As ULong
    4. End Structure
    5. Private Structure daten
    6. Dim zahl As ULong
    7. End Structure
    8. Private Structure Fileheader
    9. Dim compressedSize As ULong
    10. Dim uncompressedSize As ULong
    11. End Structure
    12. Function decompress(ByVal zfile As FileInfo) As Boolean
    13. Dim zielfilename As String = Path.GetFileNameWithoutExtension(zfile.FullName)
    14. Dim h As New Header
    15. Dim fh As New Fileheader
    16. Dim _dLen As UInteger = 8192
    17. Dim _d As Byte() = New Byte(_dLen - 1) {}
    18. Using src As FileStream = File.Open(zfile.FullName, FileMode.Open)
    19. Using reader As New BinaryReader(src)
    20. h.magic = reader.ReadUInt64()
    21. h.size1 = reader.ReadUInt64
    22. h.unknow = reader.ReadUInt64()
    23. h.size2 = reader.ReadUInt64
    24. If h.magic = 2653586369 Then
    25. Dim runs As ULong
    26. runs = fix((h.size1 + h.size2 - 1) / h.size1)
    27. Dim array As New List(Of Fileheader)
    28. Dim uebergabe As New Fileheader
    29. For o As Integer = 0 To runs - 1 Step 1
    30. uebergabe.compressedSize = reader.ReadUInt64
    31. uebergabe.uncompressedSize = reader.ReadUInt64()
    32. array.Add(uebergabe)
    33. Next
    34. Using dest As FileStream = File.Open(Path.GetFileNameWithoutExtension(zfile.FullName), FileMode.Create, FileAccess.Write)
    35. For i As Integer = 0 To runs - 1 Step 1
    36. Dim zlibHeader As UShort = reader.ReadUInt16() '/ 40056
    37. Dim to_read As ULong = array(i).compressedSize
    38. Dim compressed As Byte() = reader.ReadBytes(to_read - 2)
    39. Using ms As New MemoryStream(compressed)
    40. Using ds As New Compression.DeflateStream(ms, Compression.CompressionMode.Decompress)
    41. ds.CopyTo(dest)
    42. End Using
    43. End Using
    44. Next
    45. Return True
    46. End Using
    47. Else
    48. Console.WriteLine("Die Datei " & zfile.Name & " hat ein falsches Format")
    49. End If
    50. End Using
    51. End Using
    52. End Function
    53. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    54. Dim directoryPath As String = "c:\"
    55. Dim directorySelected As New DirectoryInfo(directoryPath)
    56. Dim fileinfo As FileInfo = directorySelected.GetFiles("test.z")(0)
    57. decompress(fileinfo)
    58. End Sub

    ähh? wasn das :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „haufe“ ()

    zlib hat einen header von 2 bytes, der beinhaltet die Art der Komprimierung(meines Wissens unterstützt zlib im Moment sowieso nur deflate), also ignorieren wir die ersten zwei Bytes für die Dekomprimierung.
    D.h. wir lesen die aus dem stream und die restlichen daten die noch zu dekomprimieren sind, sind dann natürlich um diese zwei bytes auch gekürzt.
    UShort deshalb, weil negativ werte bei soetwas keinen Sinn ergeben und ein Short(in .Net) aus 2 bytes besteht
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Danke, danke, danke!
    Super Hilfe!


    Habe noch einen Fehler gefunden bei der Datei im Anhang, er sagt :
    Über das Ende des Datenstroms hinaus kann nicht gelesen werden.
    Dateien
    • test.7z

      (15,06 kB, 188 mal heruntergeladen, zuletzt: )
    ähh? wasn das :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „haufe“ ()

    Habe jetzt nochmals den Thread geöffnet da ich doch eine Datei habe die mehr als einen run hat, zumindest laut der Rechnung

    VB.NET-Quellcode

    1. runs = (h.size1 + h.size2 - 1) / h.size1

    Dort bekomme ich dann den Fehler der im Post "26" hier im Thread zu lesen ist, setzte ich runs = 1 kann ich die Datei Entpacken, wie entsteht der Fehler bei der Rechnung und wie kann ich ihn beheben?

    Habe die Lösung selbst gefunden!
    Das Problem liegt daran das bei der Summe 1,8 heraus kommt und die aufgerundet wird, mit dem Befehl Fix() konnte ich es lösen.

    ähh? wasn das :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „haufe“ ()

    strange, seit wann rundet VB da auf?

    anstelle von Fix sollte aber dann auch das hier funktionieren

    Visual Basic-Quellcode

    1. runs = (h.size1 + h.size2 - 1) \ h.size1

    Der Backslash ist eine ganzzahl division, und sollte dann eigt. auch zum gewünschten ergebnis führen
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---