Seite 1 von 1

PackMemory() auf Linux, UnpackMemory() auf Windows -> FAIL

Verfasst: 10.12.2010 17:54
von Kukulkan
Hallo,

Ich muss unter einem Linux Server ein paar Daten mit PackMemory packen, welche dann unter Windows wieder entpackt werden müssen. Leider geht das in fast allen Fällen schief.

Unter Linux packen und Linux entpacken -> ok
Unter Linux packen und Windows entpacken -> geht nicht

Um das genauer zu untersuchen, habe ich diese beiden Test-Codes erstellt.

Pack-Code (Linux):

Code: Alles auswählen

SourceFile.s      = "INSTALL.txt"
DestinationFile.s = "INSTALL.pak"

FilesizeUnpacked.l = FileSize(SourceFile.s)

; speicher reservieren
MemoryPointerUnpacked.l = AllocateMemory(FilesizeUnpacked.l)
MemoryPointerPacked.l   = AllocateMemory(FilesizeUnpacked.l + 8)

; datei in speicher lesen
ReadFile(1, SourceFile.s)
  ReadData(1, MemoryPointerUnpacked.l, FilesizeUnpacked.l)
CloseFile(1)

; datei packen
FileSizePacked.l = PackMemory(MemoryPointerUnpacked.l, MemoryPointerPacked.l, FilesizeUnpacked.l, 9)
If FileSizePacked.l < 1
  Debug "Packing " + SourceFile.s + " failed!"
Else
  ; speichern
  If FileSize(DestinationFile.s) > -1: DeleteFile(DestinationFile.s): EndIf
  
  If OpenFile(1, DestinationFile.s)
    WriteData(1, MemoryPointerPacked.l, FileSizePacked.l)
    CloseFile(1)
    Debug "Filesize before: " + Str(FilesizeUnpacked.l) + " bytes"
    Debug "Filesize after : " + Str(FilesizePacked.l) + " bytes"
    Debug "File saved. Finished."
  Else
    Debug "Error writing " + DestinationFile.s
  EndIf
EndIf
Entpack-Code (Windows):

Code: Alles auswählen

SourceFile.s = "INSTALL.pak"

FilesizePacked.l = FileSize(SourceFile.s)

If FilesizePacked.l < 1: Debug "Can not open file " + SourceFile.s: End: EndIf

; speicher reservieren
MemoryPointerPacked.l   = AllocateMemory(FilesizePacked.l)
MemoryPointerUnpacked.l = AllocateMemory(FilesizePacked.l * 4) ; 4 faches reservieren

; datei in speicher lesen
ReadFile(1, SourceFile.s)
  ReadData(1, MemoryPointerPacked.l, FilesizePacked.l)
CloseFile(1)

; datei entpacken
FilesizeUnpacked.l = UnpackMemory(MemoryPointerPacked.l, MemoryPointerUnpacked.l)
If FileSizeUnpacked.l < 1
  Debug "Unpacking " + SourceFile.s + " failed!"
Else
  Debug "Successfully extracted file to " + Str(FilesizeUnpacked.l) + " bytes"
EndIf
Ich hab zum Testen mal die Datei INSTALL aus dem Purebasic Linux-Install genommen, mit .txt umbenannt und damit getestet. geht aber auch mit anderen Daten. Immer das gleiche Resultat.

Kann mir da jemand helfen bzw. das Problem nachvollziehen? In beiden Fällen arbeite ich auf 32 Bit Systemen (Ubuntu 10.04 LTS und Windows XP SP3).

Kukulkan

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 10.12.2010 18:12
von Thorium
Liegt daran das unter Windows eine andere Packlib verwand wird als unter Linux. Obwohl schon oft drauf hingewiesen wurde, wurde das in der Hilfe nicht korrigiert.
Lösung: Nutze zlib
zlib liegt PureBasic bei und ist schneller und komprimiert besser als JCalG1.

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 10.12.2010 18:18
von ts-soft
Scheint so, als wenn unterschiedliche Packroutinen genutzt werden. Dachte eigentlich immer es
gäbe zur Zeit nur den Unterschied von x86 zu x64.

Ist mir bisher nicht aufgefallen, da ich unter jedem OS zlib verwende, was ja auch mitgeliefert wird.
Da klappts dann auch unter versch. OS, sowie x86_x64.

Hier der code:

Code: Alles auswählen

; Autor: Thomas (ts-soft) Schulz
; PB-Version: 4.xx
; OS: windows/linux/MacOS

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    ImportC #PB_Compiler_Home + "purelibraries/linux/libraries/zlib.a"
CompilerCase #PB_OS_MacOS
  ImportC "/usr/lib/libz.dylib"
  CompilerCase #PB_OS_Windows
    ImportC "zlib.lib"
CompilerEndSelect
  compress2(*dest, *destLen, *source, sourceLen, level)
  uncompress(*dest, *destLen, *source, sourceLen)
EndImport

Procedure zipPackMemory(*source, sourceLen = #PB_Default, level = #PB_Default)
  Protected *dest, destLen
  
  If level < #PB_Default Or level > 9 : level = #PB_Default : EndIf
  If *source
    If sourceLen = #PB_Default : sourceLen = MemorySize(*source) : EndIf
    destLen = sourceLen + 13 + (Int(sourceLen / 100))
    *dest = AllocateMemory(destLen)
    If *dest
      If Not compress2(*dest, @destLen, *source, sourceLen, level)
        *dest = ReAllocateMemory(*dest, destLen)
        ProcedureReturn *dest
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure zipUnpackMemory(*source, *dest)
  Protected sourceLen = MemorySize(*source)
  Protected destLen = MemorySize(*dest)

  If Not uncompress(*dest, @destLen, *source, sourceLen)
    ProcedureReturn destLen
  EndIf
EndProcedure
PS: die entpackte grösse schreibt man immer als Header zum Pack hinzu! Ausserdem noch eine
Prüfsumme (CRC, MD5 oder ähnlich).

Gruß
Thomas

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 10.12.2010 18:26
von Kukulkan
Mist, das bringt mich jetzt echt in Schwierigkeiten :| . Was um alles in der Welt ist der Grund für diese Abweichung????

Danke für die Info zur zlib,

Kukulkan

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 10.12.2010 19:07
von NicTheQuick
Also ich wusste das vorher auch noch nicht, aber ehrlich gesagt ist es doch sau dumm. Wozu hat der Pack-Algorithmus dann überhaupt einen Namen?

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 10.12.2010 19:18
von Thorium
Wie gesagt, das will scheinbar keiner in der Hilfe korrigieren: http://www.purebasic.fr/german/viewtopi ... 05#p262405

Ich hatte deswegen mal extra die Entpackroutine von JCalG1 portiert, so das man wenigstens auf anderen Plattformen entpacken kann, sollte auch unter Linux funktionieren: http://www.purebasic.fr/english/viewtop ... 12&t=38606

Re: PackMemory() auf Linux, UnpackMemory() auf Windows -> FA

Verfasst: 13.12.2010 09:08
von Kukulkan
Hi Thorium,

Danke für die Info. Das mit den unterschiedlichen Algorithmen ist ja wirklich blanker Unsinn. Dein Code entpackt das von Windows gepackte oder das von Linux gepackte Format?

Danke,

Kukulkan