kostenloser Webspace werbefrei: lima-city


VB6: Dateien packen

lima-cityForumProgrammiersprachenBasic

  1. Autor dieses Themas

    nerdinator

    Kostenloser Webspace von nerdinator, auf Homepage erstellen warten

    nerdinator hat kostenlosen Webspace.

    Servus,

    ich denke momentan darüber nach, wie es wohl zu realisieren wäre, dateien zu "paclen", also praktisch wie zip. Ansatz ist, dass die Daten komprimiert und dann in eine Datei geschrieben werden. (Oder erst in eine Datei, dann komprimiert - keine Ahnung was Sinnvoller ist.)

    Vorraussetzung ist natürlich eine verlustfreie Komprimierung.

    Nun habe ich mir mangels besserer Möglichkeiten eine einfache RLE-Komprimierung gebastelt und habe mir gedacht, dass ich einfach die einzelnen Dateien in eine Datei schreibe, á la
    <länge><dateiname><daten><länge><dateiname><daten>
    usw, wobei natürlich eine maximale Länge der Datei vorliegen müsste (Ich dachte an 24Bit länge des wertes, also maximal 16MB große Dateien) und eine feste, maximaleLänge des Dateinamens.

    Nun birgt das einige Probleme - beispielsweise, dass ich eventuell auch ordner hinzufügen will, dass ich mit RLE noch höchstens 14,7% effizienz erreicht habe usw...

    Das Problem mit dem Ordner ließe sich noch relativ leicht lösen. Aber mir erscheint das alles sehr Unelegant.

    Vorschläge wie man sowas besser macht? Und nein, ich will keine Fremd-DLL's oder so sehen. Ich will das Rad neu erfinden ^^
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. e********l

    Wenn du keine Fremdlibs nutzen willst, dann wirst du wohl oder übel deren frei verfügbare Kompressionsverfahren in VB nachschreiben, falls diese nicht schon in der VB Lib mit dabei sind. Zip Dateien wird VB doch auch ohne extra Libs erstellen können, oder nicht?
  4. Autor dieses Themas

    nerdinator

    Kostenloser Webspace von nerdinator, auf Homepage erstellen warten

    nerdinator hat kostenlosen Webspace.

    evil-devil schrieb:
    Wenn du keine Fremdlibs nutzen willst, dann wirst du wohl oder übel deren frei verfügbare Kompressionsverfahren in VB nachschreiben, falls diese nicht schon in der VB Lib mit dabei sind. Zip Dateien wird VB doch auch ohne extra Libs erstellen können, oder nicht?
    Nicht dass ich wüsste. Also wenn es geht, weiss ich nicht wie. (über aufklärung würde ich mich freuen ;) ) Aber tendenziell geht es mir viel mehr um den Spaß am Programmieren, am "selbermachen". Wäre doch langweilig einfach etwas zu benutzen was es schon gibt. ;) Nur bin ich da halt momentan etwas am Überlegen, wie ich das möglichst elegant mache.

    Aktuell bin ich dabei, das kompressionsverfahren zu optimieren. Nehme man beispielsweise eine Textdatei, wo also praktisch nur die Zeichen a-z, A-Z, 0-9 und Interpunktion verwendet wird, werden nur die Bytes 91 - 126 (aus der Luft gegriffen, stimmt natürlich nicht, soll nur veranschaulichen was ich vor habe) verwendet. Also nehme ich all diese Bytes, und rechne sie erstmal um 91 runter. Dann schaue ich nach, wie viele Bit das größte Byte hat, also 126 - 91 = 35 hat 6 Bits. Das ganze sieht dann so aus: 00100011. Allerdings brauche ich die null-bits am anfang ja nicht.also reduziere ich alle bytes auf 6 bit und stelle ein marker vorne dran, der mir sagt wie hoch der Höchste Byte ist und wie hoch der niedrigste Byte ist, da ich die Werte für das Zurückrechnen brauche. Meine Aktuellen Funktionen:

    Zum "reduzieren", also packen:
    Public Function Reduce(ByteText As Variant, HighByte As Byte, LowByte As Byte) As Variant
        Dim i As Integer
        Dim binary As String
        Dim ByteLength As Integer
        Dim Result() As Byte
        
        ByteLength = Len(dectobin(HighByte - LowByte))
        
        For i = 0 To UBound(ByteText) - 1
            Dim dec As Integer
            Dim binarystream As String
            dec = ByteText(i)
            dec = dec - LowByte
            binarystream = dectobin(dec)
            While Not Len(binarystream) Mod ByteLength = 0
                binarystream = "0" & binarystream
            Wend
            binary = binary & binarystream
        Next i
        
        While Not Len(binary) Mod 8 = 0
            binary = "0" & binary
        Wend
        
        ReDim Result(Len(binary) / 8)
        For i = 1 To Len(binary) Step 8
            Result(i / 8) = bintodec(Mid(binary, i, 8))
        Next i
        Reduce = Result
    End Function

    Zum "expandieren", also entpacken:
    Public Function Expand(ByteText As Variant, HighByte As Byte, LowByte As Byte) As Variant
        Dim i As Integer
        Dim binary As String
        Dim Result() As Byte
        Dim ByteLength As Integer
        
        For i = 0 To UBound(ByteText) - 1
            Dim binarystream As String
            Dim dec As Integer
            dec = ByteText(i)
            binarystream = dectobin(dec)
            While Not Len(binarystream) Mod 8 = 0
                binarystream = "0" & binarystream
            Wend
            binary = binary & binarystream
        Next i
        
        ByteLength = Len(dectobin(HighByte - LowByte))
        
        While Not Len(binary) Mod ByteLength = 0
            binary = Right(binary, Len(binary) - 1)
        Wend
        
        ReDim Result(Len(binary) / ByteLength)
        
        For i = 1 To Len(binary) Step ByteLength
            Result(i / ByteLength) = bintodec(Mid(binary, i, ByteLength)) + LowByte
        Next i
        Expand = Result
    End Function


    und die ganzen "Mathematischen" funktionen wie "bintodec", etc.(wo hexadezimal nur zur "veranschaulichung" später drin ist):
    Public Function dectobin(dec As Integer) As String
        Dim binary As String
        
        Do
            binary = LTrim(Str(dec Mod 2)) & binary
            dec = Int(dec / 2)
        Loop Until dec = 0
        dectobin = binary
    End Function
    
    Public Function bintodec(bin As String) As Integer
        Dim i As Integer
        Dim dec As Integer
        
        For i = 0 To Len(bin) - 1
            dec = dec + (2 ^ i * Int(Mid(bin, Len(bin) - i, 1)))
        Next i
        bintodec = dec
    End Function
    
    Public Function dectohex(dec As Integer) As String
        Dim hexarray()
        Dim hex As String
        
        hexarray = Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
        Do
            hex = hex & hexarray(dec Mod 16)
            dec = Int(dec / 16)
        Loop Until dec = 0
        dectohex = hex
    End Function
    
    Public Function stringtochar(Text As String) As Variant
        Dim Result() As Byte
        Dim i As Long
        
        ReDim Result(Len(Text))
        For i = 1 To Len(Text)
            Result(i - 1) = Asc(Mid(Text, i, 1))
        Next i
        stringtochar = Result
    End Function
    
    Public Function chartostring(char As Variant) As String
        Dim i As Long
        Dim Text As String
        
        If IsArray(char) Then
            For i = LBound(char) To UBound(char) - 1
                If VarType(char(i)) = vbByte Then
                    Text = Text & Chr(char(i))
                End If
                DoEvents
            Next i
        End If
        Beep
        chartostring = Text
    End Function

    Nun möchte ich dass der das ganze als Blocks verarbeitet. Was ich meine: Er soll die Datei beispielsweise erst nach möglichst ähnlichen Blöcken durchsuchen. Diese könnten beispielsweise Bis zu 255 oder 65.535 Bytes groß sein. Er nimmt solche als "Blöcke", in denen die Bytes eine Möglichst hohe Kompression ermöglichen, also wo die Bytes möglichst geringe differenzen zwischen dem höchsten und niedrigsten Byte verzeichnen. Da ich dann aber ein 3 - 4 Byte großes Präfix brauche, muss die Kompression natürlich dementsprechend effektiv sein.

    Wenn ich damit dann fertig bin, kann ich mir nochmal anschauen, ob es sich beispielsweise lohnt, mehrere Durchgänge zu machen, bzw. danach nochmal mit RLE drüber zu gehen... Aber das wird sich dann zeigen.

    Nun zur Datenstruktur, wenn ich mehrere Dateien zusammenpacken möchte: Hier stehe ich noch relativ am Anfang. Wie schon gesagt wäre eine Maximale Dateigröße zur Markierung am einfachsten. 3 - 4 Bytes um die größe einer Datei zu makieren, gefolgt von einem Byte für die Länge des Dateinamens, gefolgt vom Dateinamen, gefolgt vom Dateiinhalt. Aber damit lässt sich noch keine "Struktur" packen, also keine Ordner, unterordner und ähnliches. Hier wäre ich auf konstruktive Ideen angewiesen.

    Also: Hat noch jemand Ideen, wie man die Komprimierung noch "optimieren" könnte? Oder wie man sowas mit einer Datenstruktur realisieren könnte?
  5. e********l

    Naja, weit kommst da nur leider nicht. Schau dir mal den LZMA Algo an.
    http://de.wikipedia.org/wiki/Lempel-Ziv-Markow-Algorithmus

    Du wirst in deinem Fall denke ich auch ein internes Wörterbuch benötigen.
  6. Autor dieses Themas

    nerdinator

    Kostenloser Webspace von nerdinator, auf Homepage erstellen warten

    nerdinator hat kostenlosen Webspace.

    Also meine variante ist zwar alles andere als schnell, aber bisher funktioniert sie mehr als gut. Es geht mir auch nicht um Geschwindigkeit. Meinetwegen kann der tagelang rechnen, solange das Ergebnis überzeugt. und bisher tut es das ;)

    Und ich möchte ja keinen Algorithmus reproduzieren, sondern schlicht einen eigenen schreiben. Einfach abschreiben wäre langweilig.

    Das Wörterbuchverfahren wird ja bei RLE praktisch angewendet. Zwar nicht so ausgereift, aber prinzipiell ist es nichts anderes. Nur ist es halt fraglich, in wiefern das nach meiner Komprimierung noch Sinn macht. Aber das wird sich dann halt zeigen, wenn ich fertig bin.

    In meiner Aktuellen "Version" bekomme ich teilweise bessere Ergebnisse als Zip liefert, also kann der Ansatz ja schonmal nicht schlecht sein ;) Wenn ich das nun noch durch die "Block-Methode" optimiere, muss ich es mir am ende mal an anschauen. Und dann kann ich noch immer einmal mit RLE drüber gehen. Ich glaube Zip arbeitet ja auch mit verschiedenen Methoden, welche hintereinander angewendet werden.
  7. e********l

    Wie groß ist denn deine Eingangsdatei? Und WinZip ist ....keine Worte ^^

    @RLE: Da wird gar kein Wörterbuch genutzt. Mit dem Wörterbuch kannst du halt vieles zusammenfassen und dann einfach die Referenz auf den Eintrag speichern.

    Und das soll kein Angriff sein, aber mal eben etwas besseres zu schreiben als hochbegabte Mathematiker ist nicht einfach ;)
  8. Autor dieses Themas

    nerdinator

    Kostenloser Webspace von nerdinator, auf Homepage erstellen warten

    nerdinator hat kostenlosen Webspace.

    Die Eingangsdatei: 443 Byte. Ausgabe bei Zip: 329 Byte. Ausgabe bei meinem Verfahren: 288 Byte. Ist zwar nur ein Sonderfall, aber naja.

    RLE funktioniert ja folgendermaßen: Zeichenfolge AAABBBBCCCCCC wird zu 3A4B6C. Also vereinfacht. Wenn man das ganze nun etwas komplexer macht, wird halt aus ABABABAB = 4AB. Im Grunde ist das eine Art Wörterbuch, wobei das - wie schon gesagt - noch nicht so ausgereift ist, wie moderne "Wörterbücher", vor allem da die "Indexes" halt für sich die Entschlüsselung darstellen... Aber tendenziell ist es nichts anderes.

    Und nein, ich will nicht zwingend was "besseres" schaffen. Zumal sich die hochbegabten Mathematiker vor allem auch um Dinge sorgen machen, die mich überhaupt nicht interessieren - wie beispielsweise die Geschwindigkeit. Ich konzentriere mich da voll und ganz auf die Kompression - im bewusstsein, dass es sicher irgendwo was besseres gibt. Aber es geht ja auch nicht darum mein Produkt zu verkaufen, sondern einfach um den Spaß dabei, sowas zu entwickeln.
  9. e********l

    Naja, wenn es dir nur um Kompression geht, dann schau dir trotzdem bestehende Verfahren an und leite dir daraus deine eigene Kompression ab. Viele Spiele nutzen Beispielsweise Kombinationen aus diversen Kompressionsverfahren um ihre Daten zu crunchen.

    Und RLE hat kein Wörterbuch. Ein Wörterbuch ist ein seperater Bereich der gepackten Datei das effektiv als Lookup Table dient. Und probiere deinen Code mal an einer größeren Datei (~50MB) oder an einer bereits komprimierten Datei.
  10. Autor dieses Themas

    nerdinator

    Kostenloser Webspace von nerdinator, auf Homepage erstellen warten

    nerdinator hat kostenlosen Webspace.

    evil-devil schrieb:
    Naja, wenn es dir nur um Kompression geht, dann schau dir trotzdem bestehende Verfahren an und leite dir daraus deine eigene Kompression ab. Viele Spiele nutzen Beispielsweise Kombinationen aus diversen Kompressionsverfahren um ihre Daten zu crunchen.
    Und warum sollte ich das tun? Wie du schon richtig sagtest: Bestehendes werde ich nicht übertreffen, vor allem nicht, wenn ich bestehendes verwende. Es geht mir halt darum, mir etwas eigenes auszudenken. Wobei mir jetzt erklärt wurde, dass meine Variante offenbar einiges mit der Huffmann-Methode gemeinsam hat.

    Und RLE hat kein Wörterbuch. Ein Wörterbuch ist ein seperater Bereich der gepackten Datei das effektiv als Lookup Table dient. Und probiere deinen Code mal an einer größeren Datei (~50MB) oder an einer bereits komprimierten Datei.
    Du kannst die Daten bei RLE auch seperat hin packen, was aber tendenziell keinen Sinn hat. Im Grunde werden aber sich wiederholende Zeichenfolgen geindext und durch ein kürzeres Zeichen ersetzt.

    Für größere Dateien plane ich ja bei meinem Verfahren halt wie oben schon erwähnt, die Datei in Blöcke aufzuteilen. Dann funktioniert das auch recht effizient mit größeren Dateien. Aktuell wäre bei einer großen Byte-Datei, also wo nicht nur text drin steht das höchste byte natürlich fast immer hex(FF) und das niedrigste immer hex(0) und somit würde keine kompression zustande kommen. Das ist mir allerdings auch klar. Wenn ich nun aber aus der 50MB-Datei - wie bereits lang und breit erwähnt - immer Blöcke suche, deren Differenz zwischen dem niedrigsten und höchsten byte immer in einem bestimmten Rahmen liegt, hat sich das Problem erledigt.
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!