Zerlegte, per DeflateStream komprimierte Datei wieder zusammenführen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    Zerlegte, per DeflateStream komprimierte Datei wieder zusammenführen

    Hallo miteinander :)

    Ich habe ein kleines Problem, bei dem ich vermute, dass das so nicht geht, wie ich mir das vorgestellt habe. Die Frage ist: Kann ich eine Datei, die ich per DeflateStream komprimiert habe, zerlegen und die Einzelteile erst dekomprimieren und dann wieder zusammenfügen?

    Ich gehe leider davon aus, dass so eine DeflateStream-Datei einen Header hat, und nicht so ohne weiteres in Einzelteilen dekomprimiert werden kann.

    Jedenfalls bekomme ich in Zeile 38 den Fehler: System.IO.InvalidDataException: "Ungültige Daten beim Decodieren gefunden.", jedenfalls wenn in Zeile 9 i = 2 ist, bei i = 1 oder i = 0 kommt noch kein Fehler.

    Oder es liegt an was Anderem, sieht jemand einen offensichtlichen Fehler?

    Hier mein Code:

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim KomprimierteDaten As Byte() = Komprimieren(System.IO.File.ReadAllBytes("C:\OriginalDatei.dat"))
    3. Using ZusammenGesetzteDaten As New MemoryStream
    4. Dim ZerlegteDaten As List(Of Byte()) = ByteArrayZuChunksZerlegen(KomprimierteDaten, 500000)
    5. For i = 0 To ZerlegteDaten.Count - 1
    6. ZusammenGesetzteDaten.WriteAsync(DeKomprimieren(ZerlegteDaten(i)), i * 500000, 500000)
    7. Next
    8. Using fStream As New FileStream("C:\DekomprimierteDatei.dat", FileMode.Create)
    9. ZusammenGesetzteDaten.CopyTo(fStream)
    10. End Using
    11. End Using
    12. Console.WriteLine("Done!")
    13. Console.ReadLine()
    14. End Sub
    15. Private Function ByteArrayZuChunksZerlegen(ByVal byteData As Byte(), ByVal BufferSize As Long) As List(Of Byte())
    16. Dim chunks As List(Of Byte()) = byteData.[Select](Function(value, index) New With {Key .PairNum = Math.Floor(index / CDbl(BufferSize)), value
    17. }).GroupBy(Function(pair) pair.PairNum).[Select](Function(grp) grp.[Select](Function(g) g.value).ToArray()).ToList
    18. Return chunks
    19. End Function
    20. Function DeKomprimieren(ByVal ZuKomprimieren As Byte()) As Byte()
    21. ' Byte Array in MemoryStream verwandeln
    22. Using inputStream As MemoryStream = New MemoryStream(ZuKomprimieren)
    23. ' Dekomprimierten Stream erzeugen
    24. Using outputStream As MemoryStream = New MemoryStream()
    25. Using decompressionStream As DeflateStream =
    26. New DeflateStream(inputStream, CompressionMode.Decompress)
    27. ' Dekomprimierten Stream in MemoryStream verwandeln
    28. decompressionStream.CopyTo(outputStream)
    29. End Using
    30. Return outputStream.ToArray
    31. End Using
    32. End Using
    33. End Function

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Okay ich hatte jetzt speziell den Deflate-Algorhythmus im Visier. Der scheint ja hier nicht enthalten zu sein (ich lasse mich aber gern auch eines Besseren belehren):

    VB.NET-Quellcode

    1. Public Enum COMPRESS_ALGORITHM As Integer
    2. MSZIP = COMPRESS_ALGORITHM_MSZIP
    3. XPRESS = COMPRESS_ALGORITHM_XPRESS
    4. XPRESS_HUFF = COMPRESS_ALGORITHM_XPRESS_HUFF
    5. LZMS = COMPRESS_ALGORITHM_LZMS
    6. End Enum
    Hi. Es ist kein Deflate mit bei, aber was @RodFromGermany eventuell damit sagen möchte ist, Du zerlegst ein eingelesenes ByteArray in Chunks und komprimierst diese und setzt einen Header, wie zB. Komprimierungsalgo und Größe der ursprünglichen Daten, vor den komprimierten Daten. Beim Dekomprimieren ließt Du den Header wieder ein, weist also welcher Dekompressionsalgo verwendet werden soll und die Größe der ursprünglichen Daten, dekomprimierts das ByteArray nach dem Header.
    Mfg -Franky-

    kafffee schrieb:

    Die Frage ist: Kann ich eine Datei, die ich per DeflateStream komprimiert habe, zerlegen und die Einzelteile erst dekomprimieren und dann wieder zusammenfügen?

    Ne, Deflate ist ein aufeinander aufbauende Komprimierung. Du kannst nicht einfach z.B. in der Mitte anfangen zu dekomprimieren. Da steht z.B. drin: Nimm die 5 Bytes, die von meiner Position aus 46 zurückliegen und füge diese 7-mal hintereinander ein. Du musst also vom Anfang aus beginnen.
    @-Franky-

    Ah okay also schon beim Komprimieren was machen, d.h. mein File Komprimieren, dann ein Header davor setzen, dann vor dem Dekomprimieren den Header einlesen mit der Grösse der Datenbytes drin und diese dann dekomprimieren?
    Hat ein DLF File nicht an sich schon nen Header? Wichtig wäre dass ich die Chunks einzeln dekomprimiere <b>bevor </b> ich sie dann zusammensetzen...

    @Bluespide

    Ah okay die Ahnung hatte ich nämlich auch. Dann muss ich mir was Anderes überlegen...

    Edit:

    Bluespide schrieb:

    Du musst also vom Anfang aus beginnen.

    Hab mal nachgedacht. In der Mitte irgendwo anfangen muss ich nicht. Es reicht wenn ich die Chunks nacheinander dekomprimiere...
    Heisst das ich könnte theoretisch Chunk 1 runterladen, das dann dekomprimieren, dann Chunk2 runterladen an das dekomprimierte Chunk1 anhängen und dann das Ergebnis davon wiederum dekomprimieren usw.... weisst du wie ich mein?

    Oder muss ich tatsächlich erst alle Chunks runterladen, die dann zusammensetzen und dann als Ganzes dekomprimieren?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()

    @kafffee Vielleicht fängst Du mit einem einfacheren in sich geschlossenen Komprimierungsalgorithmus an, ZIP z.B.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    kafffee schrieb:

    Chunk 1 runterladen, das dann dekomprimieren, dann Chunk2 runterladen an das dekomprimierte Chunk1 anhängen und dann das Ergebnis davon wiederum dekomprimieren usw.... weisst du wie ich mein?

    Ja klar, das geht. Du kannst anfangen zu dekomprimieren, so weit wie du mit dem ersten Teil (Chunk) kommst, und dann weiter machst, sobald weitere Daten (Chunks) da sind.
    Mein Hauptprojekt der Musikplayer ist ja jetzt fertig. Also hab ich da nen Installer für geschrieben der die Installationsdateien (bisher ZIP) runterlädt, dekomprimiert und in einen Ordner schreibt.

    Nur leider gefällt das dem Virenscanner überhaupt nicht, da hat @siycah mir empfohlen, das so zu machen...

    Wenn einer noch ne andere Idee hat, gerne hier posten:-)

    kafffee schrieb:

    Nur leider gefällt das dem Virenscanner überhaupt nicht
    Solch unwichtige Information gehört eigentlich in den Eröffnungspost.
    Solch Installationsautomaten sind ein eigen Ding.
    Ich packe alles in eine ZIP, entpacke die von Hand und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Jo so war's ursprünglich auch geplant, aber ich will auch Publikum erreichen das jetzt nicht so versiert ist, wobei sich da natürlich drüber streiten lässt, ob das nicht doch zum Allgemeinwissen gehört...

    Ich spiele mit dem Gedanken einfach zweigleisig zu fahren und nebenher auch einfach die ZIP zum Download bereitstell...

    @Bluespide

    Wie würdest du das realisieren? Würde der Dekompressor das erkennen welcher Teil der Daten schon dekomprimiert ist?

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

    @kafffee

    Du hast einen Input-Strom und einen DEFLATE-Strom.

    Wenn vom Input Daten kommen, schiebst du sie in den DEFLATE-Strom. Irgendwann ergeben sich daraus Dateien (oder Daten, je nachdem wie du es machst) und die schreibst du dann auf Platte.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    kafffee schrieb:

    Jo so war's ursprünglich auch geplant, aber ich will auch Publikum erreichen das jetzt nicht so versiert ist, wobei sich da natürlich drüber streiten lässt, ob das nicht doch zum Allgemeinwissen gehört...

    Ich spiele mit dem Gedanken einfach zweigleisig zu fahren und nebenher auch einfach die ZIP zum Download bereitstell...

    @Bluespide

    Wie würdest du das realisieren? Würde der Dekompressor das erkennen welcher Teil der Daten schon dekomprimiert ist?


    Mach doch einfach mit INNO Setup ein ganzes Setup ohne irgendwelche Hintergrund downloads?
    Das ist doch die einfachste Methode. Zumal hast du dann keinen unsicheren Download Code in deiner Anwendung.
    Wie sicherst du jetzt z.b. ab das die Datei die heruntergeladen wurde auch wirklich deine Datei ist ? Und nicht irgendeine kompromittierte Datei?
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    @xChRoNiKx

    Cool danke für den Tipp :)

    Prüft der von InnoSetup erstellte Installer denn sich selbst auf Kompromittierung?
    Wie ist das, der "kompiliert" dann mein komplettes Programm und sich selbst in eine einzige Datei?
    Ist das noch aktuell?: Setup mit automatischer .Net Framework Installation erstellen - mit Inno Setup
    Insbesondere: Muss das .NET-Framework aktuell noch mit installiert werden?

    Das klingt für mich erstmal gut nämlich...
    Nein der Installer prüft da nichts. Der User lädt sich von deiner Seite aus den Installer runter der ja schon alle Dateien beinhaltet.
    Da wird also nichts nachgeladen.

    Natürlich kann es sein das dein Webserver gehackt wird und jemand die Datei austauscht oder dem User sein Netzwerk kompromitiert wurde
    und die Datei nicht deine ist. Dafür könntest du eine Checksum bereitstellen um wenigstens etwas mehr in die Richtung zu gehen das ein
    User nach dem Download prüfen kann ob er auch wirklich DEINE Datei bekommen hat.

    Ja das ganze verpackt dein Programm und alles was dazu gehört in ein Setup - und installiert dann alles in ein Verzeichnis.
    Schau dir bitte bei Microsoft an welche NET Versionen vorinstalliert sind und was deine Zielgruppe ist.
    Je nachdem kannst du dann NET eben mit installieren oder nicht.

    Ich denke der Link sollte noch so oder so ähnlich funktionieren. Ich habe leider nur ein paar fertige Projekte die
    schon fertig sind und ich das Setup nur per Script erneure. Bei allen anderen funktioniert das einfach über ein ZIP Download.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    xChRoNiKx schrieb:

    Dafür könntest du eine Checksum bereitstellen um wenigstens etwas mehr in die Richtung zu gehen das ein
    User nach dem Download prüfen kann ob er auch wirklich DEINE Datei bekommen hat.

    Aber nur in die Richtung :P Die Checksumme könnte ja auch gehackt werden. Aber gut 100% sicher ist eh nichts...

    xChRoNiKx schrieb:

    Ich habe leider nur ein paar fertige Projekte die
    schon fertig sind und ich das Setup nur per Script erneure. Bei allen anderen funktioniert das einfach über ein ZIP Download.

    Wie meinst du? Ich hab irgendwo gelesen dass Updates so gemacht werden: Der User lädt sich das neue Installationsfile von InnoSetup runter, dieses erkennt dann automatisch ob eine Installation oder aber ein Update gemacht werden muss. Solange die AppID nicht geändert wird. Wobei ich noch nicht dahinter gekommen bin, was eine AppID denn nun sein soll? Einfach der Name, den man bei der Konfiguration eingibt?
    typischer Auszug aus *. iss-File

    Quellcode

    1. [Setup]
    2. ; NOTE: The value of AppId uniquely identifies this application.
    3. ; Do not use the same AppId value in installers for other applications.
    4. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
    5. AppId={{3363CF75-9A96-4D7A-9126-424R88E65F1D}


    ich denke das ist selbsterklärend


    und updatecheck ist dir überlassen - soweit ich weiß -

    Code-Tag eingefügt. ~Thunderbolt

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