Déserialisation d'un fichier binaire (VB2005)

Résolu
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 - 22 janv. 2008 à 18:05
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 - 28 janv. 2008 à 15:48
Bonjour et bonne année 2008, qu'elle vous soit (oui, à vous P.L., petit lecteur, lol) douce, agréable, et fructueuse (il est encore temps de faire ses veux) ,

    J'adapte un code VB6 en VB.NET (et ce n'est pas si simple contrairement à ce que je pensais au départ, ce malgré la simplicité du code VB6 à adapté) le problème étant que je veut lire un fichier de stockage de données ou des structures de donnée on été écrite en binaire bout à bout (non je ne peut pas le modifier, d'autre 'truc' y accède dont des dll C). Problème (comme je m'y attendais) le code si dessous me renvoie l'erreur :
"Binary stream '255' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization."

Forcément puisque mon fichier ne contiens pas d'entête...

Par contre je ne veut pas récupérer un tableau de byte (char) et me cogné oct par oct la conversion vers ma structure (qui est en faite un tableau de structure et mon fichier contient env 2 500 enregistrement à charger, je sent que sa risquerais de prendre un temps infini à l'exécution. Pourtant ce n'est pas très compliqué à faire en théorie ... Je sent
venir la dll ... Décidément plus j'en apprend sur le Dot.Net et moins ça
me plais ...)

Heee svp comment je fait un truc équivalent à ça (c'est du VB6) en Dot.Net
-----------------------------------------------------------------------------------------------------
Private Function LireFichier(ByVal ChemainNomFichier As String) As Boolean
Dim Compteur As Long
Dim NumFichier As Integer
Dim Tampon As MaStructure
    'On Error GoTo ErreurLecture
    Compteur = 0
    NumFichier = FreeFile()
    Open ChemainNomFichier For Binary Access Read As NumFichier Len = 128
    Get NumFichier, (Compteur * Len(Tampon)) + 1, Tampon
        While Not EOF(NumFichier)
            ReDim Preserve Fichier(0 To Compteur)
            Fichier(Compteur) = Tampon
            Compteur = Compteur + 1
            Get NumFichier, (Compteur * Len(Tampon)) + 1, Tampon
        Wend
    Close NumFichier
    LireFichierTABCRI = True
    Exit Function
ErreurLecture:
    Close NumFichier
    LireFichierTABCRI = False
End Function
-----------------------------------------------------------------------------------------------------

Mon code qui plante (VB2005) :
-----------------------------------------------------------------------------------------------------
Private Function LireFichier(ByVal ChemainNomFichier As String) As Boolean
        Dim Compteur As Long
        Dim StreamFichier As System.IO.FileStream
        Dim Tampon As MaStructure
        Dim Serializer As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
        Compteur = 0
        StreamFichier = New System.IO.FileStream(ChemainNomFichier, System.IO.FileMode.Open, IO.FileAccess.Read)
        While True
            Try
                Tampon = Serializer.Deserialize(StreamFichier) '<--- C'est la que l'erreur se produit
                ReDim Preserve Fichier(0 To Compteur)
                Fichier(Compteur) = Tampon
                Compteur = Compteur + 1
            Catch ex As Exception
                Exit While
            End Try
        End While
        StreamFichier.Close()
        If Compteur = 0 Then
            Return False
        Else
            Return True
        End If
    End Function
-----------------------------------------------------------------------------------------------------

Merci d'avance
Amicalement
Pensez "Réponse acceptée"

20 réponses

NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 10:30
Bonjour

Alors je t'explique le principe de la sérialisation comparé à la méthode utilisée par les autres programmes que tu cites :

1) En .NET, il y a un entête qui permet de déterminer le nom (complet) du type de la déssérialisation (de là il en détermine la taille des données à extraire), la version (pour éviter les surprises du chef), ...
Alors que dans les autres, il n'y a pas cet entête, les données sont mises tel quel et c'est au développeur de se débrouiller pour que ça marche.

2) Les données sont stockée de manière différentes :
En .NET : Les données sont précédé du nom du champ auquel elles sont liées
Autre : Les données sont mises tel quel et si une inversion des champs intervient, tant pis.

Donc si tu veux faire pareil, il existe une méthode, à base de CopyMemory (l'API), et pour définir la structure (là c'est la joie), il faut définir la taille et la position ainsi que le type .NET des champs (pour la syntaxe exacte, convertit un projet VB6 avec une structure d'exemple).

Attention quand même, il peut t'arriver quelques surprises, .NET n'est pas compilé, il est comme Java (sur ce point), il est pseudo compilé et tourne avec un interpréteur, donc il se peut que parfois tu ais quelques pb (si tu te trompe sur la taille de la structure par exemple.

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
3
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 14:01
Bonjour

En .NET, le Any n'existe plus, mais c'est possible de déclarer le CopyMemory :
A la place de Any, tu met un type (déclaré par toi mme ou du FramWork)
Tu peux déclarer plusieurs fois la fonction exemple :

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Single, ByRef Source As Byte, ByVal Length As Long)
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Byte, ByRef Source As Single, ByVal Length As Long)

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
3
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 14:02
Bonjour

Quoi que le "As Long" j'ai un doute (j'avais copier la déclaration brut de VB6 :-/ ), "As Integer" devrai fonction aussi.

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
3
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 16:04
La ligne que j'ai posté fonctionne mais (je pense) qu'elle m'affecte de la mémoire (du fait de la présence du "new"), mémoire qui ne me servira jamais à rien. De toute façon il me semble qu'en Dot.Net une tache de font tourne et désaffecte la mémoire qui n'est plus référencé (soit qui n'a plus de nom de variable). Mais il est possible que je me trompe. Merci pour tes idées.

Toujours la même fonction mais avec le calcul de la taille de la structure en plus :
8<-----------------------------------------------------------------------------------------------------------------------------------------------------------
Private
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef
Destination As MaStructure, ByRef Source As Byte, ByVal Length As
Int16) 'La déclaration de l'API (ATTENTION : l'Alias est important ! )

    Private Function LireFichier(ByVal ChemainNomFichier As String) As Boolean
        Dim Compteur As Long 'Compteur utilisé pour remplire le tableau de structure
        Dim NombreDeStructure As Long 'Varable utilisé pour stocké le nombre de structure à extraire
        Dim StreamFichier As System.IO.FileStream 'Streameur fichier (ce qui permet de lire le fichier)
        Dim TailleDeLaStructure As UInt16 'Variable utilisé pour stocké la taille de la structure
        TailleDeLaStructure = System.Runtime.InteropServices.Marshal.SizeOf(New MaStructure) 'Sauvegarde de la taille de la structure
        Dim Tampon(0 To TailleDeLaStructure - 1) As Byte 'Le tampon ou les données vont être placé à la lecture (-1 car le tableau commence à 0 et non pas à 1)
        Compteur = 0 'Init du compteur si non le complo renvoie un Warning
        StreamFichier = New System.IO.FileStream(ChemainNomFichier, System.IO.FileMode.Open, IO.FileAccess.Read) 'L'ouverture du fichier
        If StreamFichier.Length Mod TailleDeLaStructure <> 0 Then 'Si le fichier ne contiens pas exactement n fois la structure alors erreur
            StreamFichier.Close() 'Ferme le fichier
            Return False 'La fonction retourne faux (sous entendu ne fonctionne pas avec ce fichier)
            Exit Function 'Quite la fonction
        End If
        NombreDeStructure = StreamFichier.Length / TailleDeLaStructure 'Sauvegarde du nombre de structure à priorie présente dans le fichier
        ReDim Fichier(0 To NombreDeStructure - 1) 'Création du tableau de structure servant à recevoir les données
        While Compteur < NombreDeStructure 'Temps que toute les structure n'ont pas été lut
            Try 'Gestion d'erreur
                StreamFichier.Read(Tampon, 0, TailleDeLaStructure) 'Lit les données et les met dans le tampon
                CopyMemory(Fichier(Compteur), Tampon(0), TailleDeLaStructure) 'Copie des données du tampon dans la structure
                Compteur = Compteur + 1 'Incrémentation du compteur de boucle
            Catch ex As Exception 'Si une erreur se déclenche dans le block Try Catch
                StreamFichier.Close() 'Ferme le fichier
                Return False 'Retourne faux
                Exit Function 'Quite la fonction
            End Try 'Fin de la gestion d'erreur
        End While 'Fin de la boucle
        StreamFichier.Close() 'Ferme le fichier
        Return True 'Retourne Vrais (sous entendu tout c'est passé correctement)
    End Function 'Fin de la fonction

----------------------------------------------------------------------------------------------------------------------------------------------------------->8
Remarque : Cette fonction à pour objectif d'être insérer dans un module de classe si vous souaitez la mettre dans un module je conseil d'ajouté dans les variable passé à la fonction le tableau de structure (nomé ici Fichier) à fin d'éviter les variables globales. Comme ça : "Private Function LireFichier(ByVal ChemainNomFichier As String, ByRef Fichier() As MaStructure) As Boolean" et pouf, tout fonctionneras bien (Attention néanmoins, le contenu de la variable Fichier sera perdu à l'exécution de cette fonction)



 

Amicalement
Pensez "Réponse acceptée"
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
28 janv. 2008 à 15:48
J'ai hue à lire un fichier binaire mais cette fois contenant d'autre structure. Bà, ce fut difficile. Pour info je poste ma résolution (ça serviras sans doute à quelqu'un un jours) :

J'ai fini par trouvé une solution
(Je ne l'es trouvé nul part donc je diffuse le même post un peut
partout, ou le sujet semble être lié au problème que j'ai rencontré
quand même)



Attention ça ne fonctionneras pas dans tout les cas, à moins de l'adapter à mort...



La déclaration de chaine de longueur fixe (qui ne fonctionne que dans le cas ci-dessous, tout du moins dans mes test) :


Il faut cette déclaration dans une structure simple (soit dans une structure ne contenant pas d'autre structure)


8<----------------------------------------------------------------------------------------------------
<VBFixedString(LG_DU_TEXT),
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst:=LG_DU_TEXT)> _

Dim Chaine() as Char



---------------------------------------------------------------------------------------------------->8



Mon objectif été de lire dans un fichier binaire des données écrite
avec la méthode put de VB6 et de les chargé dans une structure complexe
(j'entends par là contenant d'autre structures)


Méthode :


1) Déclaration de mes structures et variables comme d'habitude


2) Déclaration de nouvelle structure simple basé sur le même schéma que les structure complexe mais sans les sous structures


3) Lecture du fichier en placent les données dans un tableau de byte (mentionnés pour contenir le bon nombre de données)


4) Copie des données grâce à CopyMemory (ou sans doute marchal.copy
mais je n'es pas fait de test avec, donc à valider) dans les structures
simples.


5) Copie des structure simple dans les structure complexe.



Bon je suis conscient que ça peut paraitre obscure je mes donc un exemple.


8<----------------------------------------------------------------------------------------------------
    Private Declare Sub CopyMemory Lib "kernel32" Alias
"RtlMoveMemory" (ByRef Destination As S_Simple, ByRef Source As Byte,
ByVal Length As Int16)

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(ByRef Destination As S_Creation, ByRef Source As Byte, ByVal Length As
Int16)


    Private Const C_NbSousStrucutre = 10

    Private Const C_TailleChaine = 10


    'Déclaration des structures

    Private Structure S_Simple

        <VBFixedString(C_TailleChaine),
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst:=C_TailleChaine)> _

        Public SousChaine() As Char

        Public SousValeur As Int16

    End Structure


    Private Structure S_Objectif

        <VBFixedString(C_TailleChaine),
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst:=C_TailleChaine)> _

        Public Chaine() As Char

        Public Valeur As Int16

        Public SousDonnees() As S_Simple

        Public Sub Initialise()

            ReDim SousDonnees(0 To C_NbSousStrucutre - 1)

        End Sub

    End Structure


    'Structure basé sur le même schema que S_Objectif mais sans le tableau de sous structure

    Private Structure S_Creation

        <VBFixedString(C_TailleChaine),
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst:=C_TailleChaine)> _

        Public Chaine() As Char

        Public Valeur As Int16

        'Public SousDonnees() As S_Simple

        'Public Sub Initialise()

        '    ReDim SousDonnees(0 To C_NbSousStrucutre - 1)

        'End Sub

    End Structure


    'Fonction de lecture

    Public Function LitFichier(ByVal ChemainNomFichier As String, ByRef DonneesFichier() As S_Objectif) As Boolean

        Dim Compteur As UInt16 'Compteur utilisé pour remplire le tableau de structure

        Dim NombreDeStructure As UInt16 'Varable utilisé pour stocké le nombre de structure à extraire

        Dim StreamFichier As System.IO.FileStream 'Streameur fichier (ce qui permet de lire le fichier)

        Dim TailleRacine As UInt16

        Dim TailleNiveau1 As UInt16

        Dim TailleTotalDeLaStructure As UInt16 'Variable utilisé pour stocké la taille de la structure

        Dim ConstruitRacine As S_Creation

        Dim ConstruitNiveau1() As S_Simple

        ReDim ConstruitNiveau1(0 To C_NbSousStrucutre - 1)

        TailleRacine = System.Runtime.InteropServices.Marshal.SizeOf(ConstruitRacine)

        TailleNiveau1 = System.Runtime.InteropServices.Marshal.SizeOf(ConstruitNiveau1(0))

        TailleTotalDeLaStructure = TailleRacine + (TailleNiveau1 * C_NbSousStrucutre) 'Sauvegarde de la taille de la structure

        Dim Tampon(0 To TailleTotalDeLaStructure - 1) As Byte 'Le
tampon ou les données vont être placé à la lecture (-1 car le tableau
commence à 0 et non pas à 1)

        Compteur = 0 'Init du compteur si non le complo renvoie un Warning

        StreamFichier = New System.IO.FileStream(ChemainNomFichier,
System.IO.FileMode.Open, IO.FileAccess.Read) 'L'ouverture du fichier

        NombreDeStructure = StreamFichier.Length /
TailleTotalDeLaStructure 'Sauvegarde du nombre de structure à priorie
présente dans le fichier

        ReDim DonneesFichier(0 To NombreDeStructure - 1) 'Création du tableau de structure servant à recevoir les données

        While Compteur < NombreDeStructure 'Temps que toute les structure n'ont pas été lut

            Try 'Gestion d'erreur

                Dim Position As UInt16

                StreamFichier.Read(Tampon, 0, TailleTotalDeLaStructure) 'Lit les données et les met dans le tampon

                CopyMemory(ConstruitRacine, Tampon(0), TailleRacine) 'Copie des données du tampon dans la structure

                For CompteurMaj As UInt16 = 0 To C_NbSousStrucutre - 1

                    CopyMemory(ConstruitNiveau1(CompteurMaj),
Tampon(TailleRacine + TailleNiveau1 * CompteurMaj), TailleNiveau1)
'Copie des données du tampon dans la structure

                Next

                DonneesFichier(Compteur).Initialise()

                DonneesFichier(Compteur).Chaine = ConstruitRacine.Chaine

                DonneesFichier(Compteur).Valeur = ConstruitRacine.Valeur

                DonneesFichier(Compteur).SousDonnees = ConstruitNiveau1


                Compteur = Compteur + 1 'Incrémentation du compteur de boucle

            Catch ex As Exception 'Si une erreur se déclenche dans le block Try Catch

                StreamFichier.Close() 'Ferme le fichier

                Return False 'Retourne faux

                Exit Function 'Quite la fonction

            End Try 'Fin de la gestion d'erreur

        End While 'Fin de la boucle

        StreamFichier.Close() 'Ferme le fichier

        Return True 'Retourne Vrais (sous entendu tout c'est passé correctement)

    End Function



---------------------------------------------------------------------------------------------------->8



Si la sous structure avais par exemple été entre "Chaine" et "Valeur" il aurais fallut ajouté encore une étape à la lecture.


1) CopyMemory de "Chaine"


2) CopyMemory des sous structure


3) CopyMemory de "Valeur"


(et sans doute une variable qui sauvegarde la position courante dans le tampon)



Voila j'espère avoir été claire. Mais franchement sur ce coup Microbof ne cherche vraiment pas à nous arrangé.



ATTENTION : Je parle ici de lecture d'un fichier binaire qui aurais été
crée et/ou encore utilisé par d'autre programme si non il existe des
méthode "BinaryFormatter.Serialize" et "BinaryFormatter.Deserialize"
simple à utilisé mais qui insère une entête de fichier contenant le
type et la version de ce qui à été sauvegarder. Il n'est donc pas
possible de lire avec ces méthode si l'entête est absent. De plus le
développeur n'a plus complètement les main libre sur la façon dont ses
données seront sauvegarder.

Amicalement
Pensez "Réponse acceptée"
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
22 janv. 2008 à 22:40
Tu parles de temps d'exécution et je vois 'Redil Preserve' dans une boucle...
Regarde la taille du fichier avant de boucler et dimensionne ton tableau 1 seule fois avant la boucle.
Désolé pour .NET, je n'y connais rien.

ciao...
BruNews, MVP VC++
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 09:20
Bonjour

Tu as créé ton fichier (de données) comment ?

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 10:20
Coucou et merci de vous occupé de mon problème,

Effectivement BruNews tu à totalement réson par rapport au "redim preserve" dans la boucle , merci je vais faire la pitite modif .

NHenry : Mon fichier de données est un 'vieux truc' qu'utilise le programme que je fait évoluer (il à été crée, et est toujours utilisé par du code C et Fortran). Mon objectif est de charger ces données, effectuer des traitement dessus, modifié les données en fonction de mes résultats, et réécrit ce dit fichier (je n'en suis qu'au chargement de données pour le moment)

Amicalement
Pensez "Réponse acceptée"
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
23 janv. 2008 à 10:24
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 10:52
Renfied :

En faite ça ne m'aide pas vraiment pour mon problème ici présent, mais je suis sure que ça pourra me servir un de ces jours, je me met le lient sous le coude (il commence à en y avoir beaucoup sous mon coude et c'est temps mieux ).

Merci quand même

NHenry :
Oki merci bien
Si je comprend bien je lit le fichier en mettant mes données dans un tableau d'octet (char) puis j'utilise CopyMemory pour mettre ces données dans ma structure (pour la déclaration de la structure j'ai déjà fait le nécessaire, enfin je crois ). Je le fait, puis je test, et répond (en collant mon code si ça fonctionne ).

MERCI de ta réactivité

Amicalement
Pensez "Réponse acceptée"
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 janv. 2008 à 12:09
Dans tous les cas si vraiment il faut des perfs, faut exclure .NET à tout coup.
Comme expliqué plus haut, impossible de lire direct dans des structures sans faire des CopyMemory (tu auras le temps de boire un café tranquille).

ciao...
BruNews, MVP VC++
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 13:51
BruNews :

Merci de l'info mais je sait que le VB.NET n'est pas l'idéale au niveau perf (loooiiinnn de là, pire que le VB6 à ce que j'ai entendu. VB6 qui été déjà nul niveau perf comparer au C ou C++) mais j'essaie de ne pas en rajouté avec un développement qui ferais des truc à la co_ (du style de mon 'redim preserve' dans la boucle au début ).
Heeee par contre tu laisse entendre que CopyMemory n'es pas top niveau perf ??? Je pensais le contraire (moi je voilais cette fonction comme un bout ce code C/C++ qui récup une adrs et la copie à l'ards de destination, et ça en C/C++ c'est plus que rapide, enfin il me semble)

NHenry :
Haaaa (en fait je commence à vouloir la mort de Dot.Net, je m'explique). Je n'arrive pas à déclarer l'API "CopyMemory" dans VB.NET (le type Any n'existe plus, mais ça ce n'est pas nouveau) du coup je tente pour la première fois de faire un "Marshal.Copy" (ou "Marshal.PtrToStructure") et c'est fout comme l'utilisation de cette saleté est simple et est bien expliqué (ironie)... Quoi que je tente j'ai l'erreur "Overload resolution failed [...]" avec "Copy" et je n'arrive pas à récupérer l'adrs de mon Tampon (mon tableau de byte) vue que "IntPtr.ToPointer" ne fonctionne pas en VB2005 (il me semblais que VB2005 été parfaitement équivalents au C#... Encore un bon point pour le VB2005)...

Amicalement
Pensez "Réponse acceptée"
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 janv. 2008 à 14:05
C'est l'APPEL CopyMemory qui est une calamité (et en boucle on n'en parle même pas).
C/C++ n'est bien entendu pas concerné par cela, le compilo met memcpy inline direct dans le code sans aucun appel externe.
do {*pdst++ = *psrc++;} while(--len);

ciao...
BruNews, MVP VC++
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 14:26
BruNews :

Merci pour l'info

NHenry :
Heee voila autre chose... Ma déclaration :
Private Declare Sub CopyMemory Lib "kernel32" (ByRef Destination As Object, ByRef Source As Byte, ByVal Length As Integer)

Quand je cherche à l'utilisé (comme ça : "CopyMemory(Fichier(Compteur), Tampon(0), 128)") je récupérè l'erreur "System.EntryPointNotFoundException" ??? Ça veut dire que VB2005 ne trouve pas la procédure CopyMemory dans kernel32 ou autre chose parce que là je commence à sérieusement en avoir ras le bol (plus d'une demis journée pour lire une structure dans un fichier... Sois je suis complètement nul en développement, alors que je me croyais juste pas doué, lol, et dans ce cas il faut que je change d'emploi très rapidement soit ça viens de VB2005 et je vais alerter ma hiérarchie qu'on fout dehors cette saleté et qu'on repasse sous VB6)

Aller je m'acharne encore un peut avant les solution radicale évoquer plus haut...
Amicalement
Pensez "Réponse acceptée"
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 14:34
Bonjour

As Object, pourquoi ? Tu ferais mieux de mettre le type de ta structure à la place.

Pour ton erreur, j'ai utilisé ces 2 déclaration plurieurs fois et aucun pb (IDE VB 2005 sous XP Pro SP2).

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 14:40
Heee oui effectivement "as object" pourquois ??? Je commence sans doute à fatigué (qui à dit "la bonne excuse" ? lol). Avec ma structure dans la déclaration j'ai toujours la même erreur ??? Par contre tu dit 'IDE VB 2005' pourquois IDE ??? (Si non je suis aussi sous XP Pro SP2)

Amicalement
Pensez "Réponse acceptée"
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 14:57
Bonjour

J'ai refait le test, aucun pb.

Pour t'en convaincre, voici l'exemple que j'ai fait :
http://nhen0039.chez-alice.fr/ddl/programs/sources/vbnet2
Fichier : ClsModbus.7z

Tu regarde le Sub main et tu verra (il y a un exit sub dans le main), fais un pas à pas.

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 15:21
CA MARCHE !!! C'est fout mais c'est vrais !!!




J'ai simplement ajouté {Alias "RtlMoveMemory"} à ma déclaration... Je n'est pas du bien comprendre la déclaration des API. Le nom de la fonction dans la dll c'est quoi exactement "CopyMemory" ou "RtlMoveMemory" ?
Ma fonction qui fonctionne (pour du vrais en plus, j'ai vérif les données récupérés. Avec un max de commentaire comme ça j'espère que d'autre n'auront pas à se faire chi__ comme moi aujourd'hui) :

8<----------------------------------------------------------------------------------------------
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As MaStructure, ByRef Source As Byte, ByVal Length As Int16) 'La déclaration de l'API (ATTENTION : l'Alias est important)

    Private Function LireFichier(ByVal ChemainNomFichier As String) As Boolean
        Dim Compteur As Long 'Compteur utilisé pour remplire le tableau de structure
        Dim NombreDeStructure As Long 'Varable utilisé pour stocké le nombre de structure à extraire
        Dim StreamFichier As System.IO.FileStream 'Streameur fichier (ce qui permet de lire le fichier)
        Dim Tampon(0 To 127) As Byte 'Le tampon ou les données vont être placé app la lecture
        Compteur = 0 'Init du compteur si non le complo renvoie un Warning
        StreamFichier = New System.IO.FileStream(ChemainNomFichier, System.IO.FileMode.Open, IO.FileAccess.Read) 'L'ouverture du fichier
        If StreamFichier.Length Mod 128 <> 0 Then 'Si le fichier ne contiens pas exactement n fois la structure alors erreur
            StreamFichier.Close() 'Ferme le fichier
            Return False 'La fonction retourne faux (sous entendu ne fonctionne pas avec ce fichier)
            Exit Function 'Quite la fonction
        End If
        NombreDeStructure = StreamFichier.Length / 128 'Sauvegarde du nombre de structure à priorie présente dans le fichier
        ReDim Fichier(0 To NombreDeStructure - 1) 'Création du tableau de structure servant à recevoir les données
        While Compteur < NombreDeStructure 'Temps que toute les structure n'ont pas été lut
            Try 'Gestion d'erreur
                StreamFichier.Read(Tampon, 0, 128) 'Lit les données et les met dans le tampon
                CopyMemory(Fichier(Compteur), Tampon(0), 128) 'Copie des données du tampon dans la structure
                Compteur = Compteur + 1 'Incrémentation du compteur de boucle
            Catch ex As Exception 'Si une erreur se déclenche dans le block Try Catch
                StreamFichier.Close() 'Ferme le fichier
                Return False 'Retourne faux
                Exit Function 'Quite la fonction
            End Try 'Fin de la gestion d'erreur
        End While 'Fin de la boucle
        StreamFichier.Close() 'Ferme le fichier
        Return True 'Retourne Vrais (sous entendu tout c'est passé correctement)
    End Function 'Fin de la fonction
---------------------------------------------------------------------------------------------->8

Une derniers toute petite question et je vous laisse tranquille (déjà MERCI mille fois)
Comment récupérer la taille en oct de ma structure parceque j'ai peur que la ligne ci dessous ne m'affecte de la mémoire pour rien :
System.Runtime.InteropServices.Marshal.SizeOf(New MaStructure)
Amicalement
Pensez "Réponse acceptée"
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
23 janv. 2008 à 15:34
Bonjour

Je n'ai jamais eu besoin de ce genre de chose en .NET.
Je te propose :
- Tu utilises la taille fournie à partir des autres prog
- Tu calcul la taille par toi même
Mais normalement la ligne que tu utilises devrais fonctionner.

dsl.

Dans Word, j'Excel. (juste pour la citation)
VB (6, .NET1&2), C++, C#.Net1
Mon site
0
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
23 janv. 2008 à 17:27
Hooo
Je viens de faire un test supplémentaire (avec un fichier volontairement plus gros que celui qui sera réellement utilisé) et ce code extrais 35 000 structure de données en 406 mili-seconde en débug !!! Loin d'être lente cette pitite fonction dit donc !!!

Amicalement
Pensez "Réponse acceptée"
0
Rejoignez-nous