IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB 6 et antérieur Discussion :

Problème avec les données binaire


Sujet :

VB 6 et antérieur

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Problème avec les données binaire
    Je cherche à écrire une classe VB pour encoder et décoder des données en Base64. Mon code marche très bien pour les chaîne de caractères conventionnel mais plante lamentablement lorsqu'il s'agit de données binaire.

    L'encodage consiste à convertir les données binaires en une chaîne de caractère ASCII puis d'encoder la chaine en base64. Le decodage quand à lui se limite à décoder une chaîne en base64 et l'écrire dans un fichier vierge ou dans une variable (suivant qu'il s'agisse de données binaires ou de texte).

    J'ai trouvé un article (particulièrement indigeste) sur MSDN parlant de ce problème, mais l'anglais n'est pas mon fort et les notions abordées commence à me dépasser légèrement. :p

    http://msdn.microsoft.com/library/de...og6_topic1.asp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    ' Récupération de données binaires dans un fichier
        Private Function getBinaryFile(strFilePath As String)
        ' Déclaration des variables
            Dim oStream
            Dim i, strValue
       ' Création de l'objet
            Set oStream = New ADODB.Stream
        ' Ouverture de l'objet
            oStream.Open
        ' On récupère les données binaires du fichier
            oStream.Type = 1
            oStream.LoadFromFile strFilePath
        ' On convertit les données binaires en ASCII
            strValue = StrConv(oStream.Read, vbUnicode)
            For i = 1 To LenB(binValue) Step 2
                strValue = strValue & Chr(AscB(MidB(binValue, i, 1)))
            Next
        ' On renvoie les données binaires
            getBinaryFile = strValue
        ' On détruit l'objet
            Set oStream = Nothing
        End Function
    Mais le résultat est éroné même s'il est similaire à l'original comme le rajout de " 'd" en debut de chaine ou les changements des "Ž" en "}" ou encore des "‰" en "0".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Original (extrait):
    GIF89aËè³     ï  ïïïÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,    Ëè 
    (...)
    FgT!ÃҎُi‰	©ɐ
    9‰   ;
     
    Copie (extrait): 
     'dGIF89aËè³     ï  ïïïÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,    Ëè 
    (...)
    FgT!ÃÒ}ُi0	©ɐ
    90
    Je ne pense pas que l'encodage/decodage en base64 soit fautif puisque c'est un code que j'ai recyclé à partir de l'ASP et qu'il fonctionnait parfaitement avec des mail contenant du text en base64 (chaîne de caractères) et des images jointes (données binaires).

    Donc voilà, si quelqu'un a des conseils sur comment éffectuer proprement la conversion de données binaire en chaines de caractère sous VB6, ou l'adresse d'un tutorial simple et explicite sur ce sujet, je suis preneur.
    Merci d'avance pour toutes propositions permettant de faire avancer mon schmilblick. ^^



    A noter que sous ASP, la conversion du binaire en ASCII était plus simple (le code ci dessous ne reprend que la convertion binaire vers ASCI):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        Private Function BinaryToString(binValue)
            Dim i, strValue
            For i = 1 To LenB(binValue)
                strValue = strValue & Chr(AscB(MidB(binValue, i, 1)))
            Next
            BinaryToString = strValue
        End Function

  2. #2
    Futur Membre du Club
    Inscrit en
    Août 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    J'ai fait quelques essais de copie de fichier en binaire en recopiant le flux binaire du fichier source vers le fichier cible sans encodage/decodage en base64.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
        Private Sub BinaryCopy(strFilePathSource As String, strFilePathTarget As String)
            Dim oStream
            Dim iFile As Integer
            Set oStream = New ADODB.Stream
            oStream.Open
            oStream.Type = 1
            oStream.LoadFromFile strFilePath
            iFile = FreeFile
            Open "D:\essais1.bmp" For Binary As #iFile
     
    ' Cas 1: En renvoyant directement le flux binaire on se retrouve avec une concatenation
    ' en debut de fichier d'une chaine de 12 caractères "  (d      ".
    '        Put #iFile, , oStream.Read
     
    ' Cas 2: Si on tente de tronquer les 12 premier caractères on se retrouve avec un
    ' fichier complètement éroné, aussi bien avec Mid qu'avec MidB on perd la moitié des
    ' données...  X(
    '        Put #iFile, , Mid(oStream.Read, 13)
    '        Put #iFile, , MidB(oStream.Read, 13)
     
    ' Cas 3: En convertissant d'abord le flux en unicode avant de le renvoyer dans le
    ' fichier, on se retrouve avec une concaténation en debut de fichier d'une chaine de 4
    ' caractères ""
    '        Put #iFile, , StrConv(oStream.Read, vbUnicode)
     
    ' Cas 4: En convertissant d'abord le flux en unicode puis en tronquant les 4 premier
    ' caractères avant de le renvoyer dans le fichier, on se retrouve avec un fichier dont
    ' les 4 premier caractères ont été corrompue.
    '        Put #iFile, , Mid(StrConv(oStream.Read, vbUnicode), 5)
     
    ' Cas 5: En convertissant d'abord le flux en unicode puis en tronquant les 4 premier
    ' caractères avant de le renvoyer dans le fichier, on se retrouve avec un fichier dont
    ' les 4 premier caractères ont été corrompue.
            Put #iFile, , StrConv(Mid(oStream.Read, 5), vbUnicode)
     
            Close #iFile
     
    ' Si on écrase les quatre premier octet avec une chaine contenant les 4 premiers
    ' caractères du fichier original, après avoir appliquer le cas 4 ou le cas 5, on se
    ' retrouve avec un fichier sain... (O_O)
            iFile = FreeFile
            Open "D:\essais1.bmp" For Binary As #iFile
            Put #iFile, , "GIF89"
            Close #iFile
     
            Set oStream = Nothing
        End Sub

  3. #3
    Modérateur
    Avatar de AlainTech
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mai 2005
    Messages
    4 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2005
    Messages : 4 235
    Points : 24 327
    Points
    24 327
    Par défaut
    Je ne comprends pas le but de transformer des données binaires en caractères.
    Il y aura forcément perte d'information...
    N'oubliez pas de cliquer sur quand vous avez obtenu ou trouvé vous-même la réponse à votre question.
    Si vous trouvez seul, pensez à poster votre solution. Elle peut servir à d'autres!
    Pensez aussi à voter pour les réponses qui vous ont aidés.
    ------------
    Je dois beaucoup de mes connaissances à mes erreurs!

  4. #4
    Futur Membre du Club
    Inscrit en
    Août 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Il y a perte d'information si tu interpretes les caractères spéciaux.
    La convertion est nécessaire si on ne veut pas que VB interpréte les dit caractères quand on passe les données à la fonction d'encodage.
    Si j'envoie directement du binaire à la fonction d'encodage en base64, les données seront tronquées au premier caractère nul (dans un gif yen a un parmis les 10 premiers caractères). Sinon, comme je l'ai dit plus haut, je recycle un code qui marchait très bien en ASP, cad qu'en suivant le cursus :

    binaire --convertion--> ASCII --encodage--> base64 --decodage--> ASCII --convertion--> binaire

    ...j'avais bien des données identique en entrée et en sortie.

  5. #5
    Futur Membre du Club
    Inscrit en
    Août 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    Private Sub BinaryCopy(strFilePathSource As String, strFilePathTarget As String) 
            Dim oStream 
            Dim iFile As Integer 
        ' On ouvre le fichier source
            Set oStream = New ADODB.Stream 
            oStream.Open 
            oStream.Type = 1 
            oStream.LoadFromFile strFilePath 
        ' On récupère les données en tronquant les 4 premier caractères.
            strValue = StrConv(MidB(oStream.Read, 5), vbUnicode)
        ' On ferme le fichier source
            Set oStream = Nothing 
        ' On encode les données
            strValue = Base64Encode(strValue)
        ' On affiche le résultat de l'encodage
            MsgBox "strValue: " & strValue
        ' On decode les données
            strValue = Base64Decode(strValue)
        ' On écrit les données dans un nouveau fichiers
            iFile = FreeFile 
            Open "D:\essais1.bmp" For Binary As #iFile 
            Put #iFile, , strValue
            Close #iFile 
        ' On écrase manuellement les quatre premiers caractères
            iFile = FreeFile 
            Open "D:\essais1.bmp" For Binary As #iFile 
            Put #iFile, , "GIF8" 
            Close #iFile 
        End Sub
    Avec cette procédure j'arrive bien à encoder puis décoder une image gif de 26ko sans qu'elle soit corrompue... Donc la logique est bonne, il y a juste un bug lors de l'écriture des données dans le fichier cible.

    A prioris, le problème vient du fait que la ligne...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
            Put #iFile, , strValue
    ...écrit la chaîne de caractères précédé de sa taille. Ce qui est encore plus étrange à mon gout, c'est que cette erreur ne se produit pas tant qu'on ne passe pas la chaine de caractère par le biais d'une variable (qui aurait pu être utile pour stocker les 4 premiers caractères qu'on tronque).

    Donc en fait, il faudrait juste trouver le moyen d'écrire la chaine de caractère sans la précéder de sa taille.

  6. #6
    Futur Membre du Club
    Inscrit en
    Août 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Si j'ai bien compris mon probkème viens du fait que la mèthode put interprète les chaines de caractères BSTR comme de simple chaine LPWSTR. Il me faut donc convertir ma chaine strValue en Byte Array ou en chaîne LPWSTR.

    J'ai trouvé quatre solutions pour effectuer celà (les temps sont pris sur un sur un P4 2800):

    La première consiste à convertir la chaîne BSTR en Byte Array puis d'écrire le Byte Array dans le fichier cible. Mais ce code semble particulièrement lent...
    26 ko ---> 405 ms
    400 ko ----> 284'000 ms
    680 ko ----> 1'161'000 ms
    15'850 ko ----> quelques jours ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            Dim b() As Byte
            ReDim b(1 To Len(strValue)) As Byte
            For i = 1 To Len(strValue)
               b(i) = Asc(MidB(strValue, i + i - 1))
            Next
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            Put #iFile, , b
            Close #iFile

    La deuxième solution consiste à convertir la chaîne BSTR en une chaîne LPWSTR puis d'écrire la chaîne LPWSTR dans le fichier cible. Cette méthode semble beaucoup plus rapide que la précédante mais la chaîne obtenue ne serras pas exploitable en dehors de la function où elle a été créée.
    26 ko ----> 31 ms
    400 ko ----> 330 ms
    680 ko ----> 547 ms
    15'850 ko ----> 13'258 ms

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            Dim tmp As String
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            tmp = Space(Len(strValue))
            For i = 1 To Len(strValue)
                Mid(tmp, i, 1) = Chr(Asc(MidB(strValue, i + i - 1, 2)))
            Next
            Put #iFile, , tmp
            Close #iFile

    La troisième solution (et la plus barbare) consiste à écrire la chaîne BSTR dans le fichier cible, puis récupérer les données (en tronquant les 4 premiers caractères) qui viennent d'être écrite dans un Byte Array, éffacer le fichier cible qui viens d'être créer, et enfin, écrire le Byte Array dans le fichier cible final. Ce code est l'un des plus éfficace...
    26 ko ----> 15 ms
    400 ko ----> 15 ms
    680 ko ----> 63 ms
    15'850 ko ----> 1'250 ms

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            Put #iFile, , strValue
            Close #iFile
     
            Dim bytValue() As Byte
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            ReDim bytValue(1 To Len(strValue)) As Byte
            Get #iFile, 5, bytValue
            Close #iFile
     
            If Dir(strFilePathTarget) <> "" Then Kill strFilePathTarget
     
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            Put #iFile, , bytValue
            Close #iFile

    La dernière reprend la solution évoquer plus haut dans le thread et est tout aussi barbare... Mais elle est la plus éfficace.
    26 ko ----> 15 ms
    400 ko ----> 15 ms
    680 ko ----> 47 ms
    15'850 ko ----> 1'171 ms

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
            Dim b() As Byte
            ReDim b(1 To 4) As Byte
            For i = 1 To 4
               b(i) = Asc(MidB(strValue, i + i - 1))
            Next
     
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            Put #iFile, , Mid(strValue, 5)
            Close #iFile
     
            iFile = FreeFile
            Open strFilePathTarget For Binary As #iFile
            Put #iFile, , b
            Close #iFile

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. problème avec les données issues d'une kinect
    Par takfa2008 dans le forum Traitement d'images
    Réponses: 0
    Dernier message: 05/03/2013, 09h20
  2. [Pentaho BI-server 2]Problème avec les sources de données
    Par jonathansauret dans le forum Pentaho
    Réponses: 1
    Dernier message: 11/03/2009, 08h59
  3. [VB]Problème avec les bases de données
    Par boudincweole10 dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 22/04/2006, 20h24
  4. Problème avec les indexes sur une base de données.
    Par osoudee dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 09/02/2006, 09h24
  5. Réponses: 3
    Dernier message: 08/12/2005, 10h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo