Probleme avec UnPackMemory() ! Aidez moi

Programmation d'applications complexes
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Probleme avec UnPackMemory() ! Aidez moi

Message par Thyphoon »

A force de tourné sur un problème depuis 2 jours je n'y comprends plus rien.

Voici un code qui permet de trandformer un fichier en chaine de caractère puis de nouveau en fichier. Cela en codant en Base64, et en utilisant le PackMemory.
Avec le code si dessous, vous selectionnez un fichier et il doit vous faire une copie du fichier juste a côté en rajoutant "New_" au debut du nom. ça marche très bien dans la plus part des cas. Vous pouvez essayé des fichiers texts, des images jpeg etc... mais parfois sur certain fichier j'ai une mechante erreur avec UnPackMemory
voici une image avec laquel j'ai le problème...
Image

Pouvez vous tester et me dire si vous avez la même problème et si jammais vous avez une idée... une solution n'hesitez pas... 2 jours ou je tourne le problème dans tout les sens. j'ai reprogrammé au moins 10 fois depuis zero, j'ai repris des codes du forum etc... et là je ne sais plus quoi faire.
Merci d'avance

Thy

Code : Tout sélectionner

Global FileSize.l
Procedure.s GetBase64StringFromFile(file.s)
  ; This uses code posted by netmaestro
  ; http://www.purebasic.fr/english/viewtopic.php?t=32638&highlight=blob
  
  If ReadFile(0, file)
    FileSize.l=Lof(0)
    *inputbuffer = AllocateMemory(FileSize)
    If *inputbuffer
      ReadData(0, *inputbuffer, FileSize)
      ;Pack File
      *PackMemory = AllocateMemory(FileSize + 8)
      NewFileSize.l=PackMemory(*InputBuffer, *PackMemory, FileSize, 9)
      If NewFileSize=0
        CopyMemory(*InputBuffer, *PackMemory, FileSize)
        NewFileSize=FileSize
      EndIf
      
      ; The output buffer (*encodedbuffer) needs to be approximately 35% larger than the input buffer
      *encodedbuffer = AllocateMemory(MemorySize(*PackMemory)*1.35)
      If *encodedbuffer
        encodedlength = Base64Encoder(*PackMemory, NewFileSize, *encodedbuffer, MemorySize(*encodedbuffer))
      EndIf
      CloseFile(0)
      FreeMemory(*inputbuffer)
      FreeMemory(*PackMemory)
    EndIf
  EndIf
  
  base64string.s = PeekS(*encodedbuffer)
  FreeMemory(*encodedbuffer)
  
  ProcedureReturn base64string
EndProcedure

Procedure DecodeBase64StringAndSaveAsBinary(base64string.s, file.s)
  ; This uses code posted by netmaestro
  ; http://www.purebasic.fr/english/viewtopic.php?t=32638&highlight=blob
  ;modified by Thyphoon replace len to StringByteLength (Unicode compatibility)
  *decodedbuffer = AllocateMemory(StringByteLength(base64string))
  Base64Decoder(@base64string, StringByteLength(base64string), *decodedbuffer, StringByteLength(base64string)*0.75)
  
      *UnPackBuffer = AllocateMemory(FileSize)
      If UnpackMemory(*DecodedBuffer, *UnPackBuffer)<>FileSize
        CopyMemory(*DecodedBuffer, *UnPackBuffer, FileSize)
      EndIf
  
  
  OpenFile(0, file)
  WriteData(0, *UnPackBuffer, FileSize)
  CloseFile(0)
   FreeMemory(*UnPackBuffer)
  FreeMemory(*decodedbuffer)
EndProcedure

; Select file to add to database
filePath.s = OpenFileRequester("Choose a file", "", "*.*", 0)
base64string.s = GetBase64StringFromFile(filePath)
newfilePath.s = GetPathPart(filePath) + "new_" + GetFilePart(filePath)
DecodeBase64StringAndSaveAsBinary(base64string.s, newfilePath)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

je n'ai pas regardé le code ...

mais ne s'agirait'il pas de la couleur transparente qui pose probleme ?? 8O
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Dobro a écrit :je n'ai pas regardé le code ...

mais ne s'agirait'il pas de la couleur transparente qui pose probleme ?? 8O
Merci Dobro de t'être penché sur mon problème. Il est vrai que si les images, Jpeg,BMP passe tres bien aucun PNG ne passe ou presque... qu'il y ai une couche alpha ou non.
Mais de toute façon mon code lit les données brut. C'est sensé fonctionné avec n'importe quel fichier.. et je ne vois pas pourquoi les png poserait problème :?
Mon code est relativement simple. Je charge un fichier directement en mémoire avec ReadData() ensuite je le compresse avec PackMemory je l'encode en Base64 et le stock dans une variable. Ensuite je fait tout en chemin inverse. Surtout qu'a la limite la function UnpackMemory devrait retourner 0 en cas de problème et pas planté...
la j'ai vraiment plus d'idée ... Je n'ose pas dire qu'il y a Bug dans purebasic, vu qu'a chaque fois que j'ai eu cette idée, ça venait au final de moi :P
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

J'ai pensé tout suite à une cause probable qui doit être le problème

Lorsque tu pack et que NewFileSize retourne 0, là tu stockes le fichier le fichier en entier. Lorsque tu décodes et qu'ensuite tu tentes un UnpackMemory, si c'est pas packé, alors là ça plante.

Lorsque ça plante, on est bien avec la variable NewFileSize à 0 de la procedure GetBase64StringFromFile()

Soit tu ajoutes avant les données compressées ou non, un octet qui t'indique que les données qui arrivent sont compressées ou non.
Si elles ne sont pas compressées, il ne faut pas unpacker mais extraire le tout en fonction de la longueur que tu auras aussi mémorisé dans ton archive car sinon ...

Tu peux peut-être t'inspirer d'un de mes vieux code ici
http://www.purebasic.fr/french/viewtopic.php?t=520

A+
Denis
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Denis a écrit :J'ai pensé tout suite à une cause probable qui doit être le problème

Lorsque tu pack et que NewFileSize retourne 0, là tu stockes le fichier le fichier en entier. Lorsque tu décodes et qu'ensuite tu tentes un UnpackMemory, si c'est pas packé, alors là ça plante.

Lorsque ça plante, on est bien avec la variable NewFileSize à 0 de la procedure GetBase64StringFromFile()

Soit tu ajoutes avant les données compressées ou non, un octet qui t'indique que les données qui arrivent sont compressées ou non.
Si elles ne sont pas compressées, il ne faut pas unpacker mais extraire le tout en fonction de la longueur que tu auras aussi mémorisé dans ton archive car sinon ...

Tu peux peut-être t'inspirer d'un de mes vieux code ici
http://www.purebasic.fr/french/viewtopic.php?t=520

A+
Denis
Merci denis, mais le problème ne vient pas de là.
Si tu regarde mon code...ici pour l'exemple j'ai mis un

Code : Tout sélectionner

Global FileSize.l
et ensuite

Code : Tout sélectionner

NewFileSize.l = PackMemory(*InputBuffer, *PackMemory, FileSize, 9)
      If NewFileSize = 0
        CopyMemory(*InputBuffer, *PackMemory, FileSize)
        NewFileSize = FileSize
      EndIf
Mais je vais aller etudier ton code ...merci
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Oui, j'ai vu mais le problème viens bien de là

Le code qui suit, tu ne peux pas faire car je me répète, tu ne peux pas utiliser la commande UnpackMemory sur des donnés non packées, sinon ça plante

Code : Tout sélectionner

     If UnpackMemory(*DecodedBuffer, *UnPackBuffer)<>FileSize
selon la doc PB, UnpackMemory
Décompresse une zone mémoire préalablement compressée (avec PackMemory()) vers la zone MemoireDestination
La doc dit aussi que la fonction retourne 0, mais il ne semble pas que cela soit le cas ...

alors teste ce code qui marche, j'ai ajouté une variable globale et deux tests



Code : Tout sélectionner

Global FileSize.l, Data_Coder.l

Procedure.s GetBase64StringFromFile(file.s)
     ; This uses code posted by netmaestro
     ; http://www.purebasic.fr/english/viewtopic.php?t=32638&highlight=blob
     
     If ReadFile(0, file)
          FileSize.l=Lof(0)
          *inputbuffer = AllocateMemory(FileSize)
          If *inputbuffer
               ReadData(0, *inputbuffer, FileSize)
               ;Pack File
               *PackMemory = AllocateMemory(FileSize + 8)
               NewFileSize.l=PackMemory(*InputBuffer, *PackMemory, FileSize, 9)
               If NewFileSize=0
                    Data_Coder = #False
                    CopyMemory(*InputBuffer, *PackMemory, FileSize)
                    NewFileSize=FileSize
               Else
                    Data_Coder = #True
               EndIf
               
               ; The output buffer (*encodedbuffer) needs to be approximately 35% larger than the input buffer
               *encodedbuffer = AllocateMemory(MemorySize(*PackMemory)*1.35)
               If *encodedbuffer
                    encodedlength = Base64Encoder(*PackMemory, NewFileSize, *encodedbuffer, MemorySize(*encodedbuffer))
               EndIf
               CloseFile(0)
               FreeMemory(*inputbuffer)
               FreeMemory(*PackMemory)
          EndIf
     EndIf
     
     base64string.s = PeekS(*encodedbuffer)
     FreeMemory(*encodedbuffer)
     
     ProcedureReturn base64string
EndProcedure

Procedure DecodeBase64StringAndSaveAsBinary(base64string.s, file.s)
     ; This uses code posted by netmaestro
     ; http://www.purebasic.fr/english/viewtopic.php?t=32638&highlight=blob
     ;modified by Thyphoon replace len to StringByteLength (Unicode compatibility)
     *decodedbuffer = AllocateMemory(StringByteLength(base64string))
     Base64Decoder(@base64string, StringByteLength(base64string), *decodedbuffer, StringByteLength(base64string)*0.75)
     
     *UnPackBuffer = AllocateMemory(FileSize)
     
     
     Debug Data_Coder
     If Data_Coder = #False
          CopyMemory(*DecodedBuffer, *UnPackBuffer, FileSize)
     Else
          UnpackMemory(*DecodedBuffer, *UnPackBuffer)
     EndIf
     
     
     OpenFile(0, file)
     WriteData(0, *UnPackBuffer, FileSize)
     CloseFile(0)
     FreeMemory(*UnPackBuffer)
     FreeMemory(*decodedbuffer)
EndProcedure

; Select file to add to database
filePath.s = OpenFileRequester("Choose a file", "", "*.*", 0)
base64string.s = GetBase64StringFromFile(filePath)
newfilePath.s = GetPathPart(filePath) + "new_" + GetFilePart(filePath)
DecodeBase64StringAndSaveAsBinary(base64string.s, newfilePath)
A+
Denis
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci beaucoup Denis ! ça fonctionne maintenant parfaitement...
Mais il y a bien un bug dans la function unpackMemory !
Crois tu qu'il faut le signaler sur le forum anglais ou pas ?
En tout cas merci !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

De mémoire, la fonction packmemory échoue si le résultat de la compression est d'une taille plus grande que l'original, ce qui arrive parfois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

djes a écrit :De mémoire, la fonction packmemory échoue si le résultat de la compression est d'une taille plus grande que l'original, ce qui arrive parfois.
la commande échoue Oui, mais plante non ! et c'est bien la le problème
c'est un peu comme si lorsque tu fait un openfile si tu as le fichier ça marche et si tu n'as pas le fichier ça plante... c'est assez ch.... comme bug non ?
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Je vais jeter un oeil...
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

djes a écrit :Je vais jeter un oeil...
merci c'est sympa ! :D
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Tu as raison, le unpackmemory() essaye de dépacker une zone qui ne contient pas de données packées, et au lieu de s'arrêter tout de suite et de renvoyer 0, continue jusqu'à faire un accès mémoire interdit. Pour l'instant dans ton programme, tu n'as qu'à faire un flag pour signaler que ton pack a échoué. Tu devrais aussi faire un rapport d'erreur (avec un exemple simplifié avec juste le pack et le unpack) pour Fred sur le forum anglais.

Il y a quelques autres erreurs dans ton code, mais je suppose que c'était pour le test.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

djes a écrit :Tu as raison, le unpackmemory() essaye de dépacker une zone qui ne contient pas de données packées, et au lieu de s'arrêter tout de suite et de renvoyer 0, continue jusqu'à faire un accès mémoire interdit. Pour l'instant dans ton programme, tu n'as qu'à faire un flag pour signaler que ton pack a échoué. Tu devrais aussi faire un rapport d'erreur (avec un exemple simplifié avec juste le pack et le unpack) pour Fred sur le forum anglais.

Il y a quelques autres erreurs dans ton code, mais je suppose que c'était pour le test.
Oui c'est ce que j'ai fait. En vité j'ai simplifié le code ici et j'ai modifier pour faire des tests... Des que j'ai un peu de temps je vais poster pour le UnPackmemory() sur le forum anglais ! mais je sais pas trop comment leur faire un truc simple et evident
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Tiens, un truc curieux, en essayant de faire l'exemple, ça a l'air de fonctionner!
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Edit:Petite correction du code Dans la boucle for c'est 1023 et non 1024 comme je l'avais mis au depart ! merci Denis
que penses tu de ça :

Code : Tout sélectionner

*source=AllocateMemory(1024)
For z=0 To 1023
  PokeB(*source+z,Random(255))
Next
*destination=AllocateMemory(1024)

If UnpackMemory(*source,*destination) =0
  MessageRequester("Error", "Error ", 0)
EndIf
j'ai posté ça là : http://www.purebasic.fr/english/viewtopic.php?t=33742
J'ai toujours peur que l'erreur vienne de moi et de les embêter plus qu'autre chose...
PS: ça renvoie bien un zero parcontre si dans les données tout est a Zero ...
Dernière modification par Thyphoon le mer. 13/août/2008 13:50, modifié 1 fois.
Répondre