Vb6 - lire/écrire fichier .dat

Résolu
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 - 14 nov. 2007 à 23:37
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 - 16 nov. 2007 à 17:18
Bonjour,

Je cherche la syntaxe complète pour écrire et lire un fichier .dat s'il vous plait.
Je connais la syntaxe pour les fichiers .txt, mais j'ai des problèmes avec les .dat, quelqu'un pourrait m'aider?
Ce que j'aimerais faire c'est sauvegarder par paire, dans le même fichier, un numéro et une chaine, et lire à l'intérieur du .dat pour voir si cette paire (nombre+chaine) est présente, et si elle ne l'est pas, la rajouter à la fin du fichier.

Merci beaucoup à tous !

11 réponses

cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
15 nov. 2007 à 00:45
En principe, un fichier .dat est binaire, mais tu peux aussi bien écrire un fichier .txt en lui donnant l'extension .dat ... donc difficile de te répondre...

Partant du principe que tu veux écrire un fichier binaire...

Open "c:\monfichier.dat" for Binary as #1
    'ici tu utilises Get ou Put selon que tu veux lire ou écrire
Close #1

LOF peut aussi être utile ... ainsi que FreeFile, bien sûr.

Voir les mots en gras dans ton aide et tu devrais trouver pas mal de réponses...

PS: je te vois aller depuis quelques semaines et tu sembles apprendre très rapidement...
Lâche pas !

MPi²
3
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
15 nov. 2007 à 02:06
Salut

Si j'ai bien compris, ton fichier sera une succession de :
   ValeurNumérique - Chaine - ValeurNumérique - Chaine - ValeurNumérique - Chaine - ...

J'ajouterai que :
- on peut se déplacer dans le fichier sur un octet précis avec l'instruction Seek
- les données que tu vas lire ou écrire avec Get ou Put doivent avoir la bonne taille.
Si tu veux lire un chiffre qui a été sauvé en Long, il faudra le relire en Long.
Pour les chaines, il faudra définir une taille fixe car la lecture se fait par zone tampon dimensionnée.
Pour lire une chaine de 10 caractères, il faudra avoir dimensionné une variable chaine comme suit :
   Dim sTemp As String
   sTemp = String(10, vbSpace)
pour pouvoir faire un
   Get #file, , sTemp
De même, à l'écriture, il faudra écrire les données avec ce même format, obligatoirement, c'est à dire que si ton texte ne fait pas 10 caractères, il faudra quand même les ajouter à la suite.

En général, on prépare un "Type" de variable dédiée à cette lecture :
   Public Type typeMesDonnées
      ValeurNumérique   As Long
      Texte                     As String * 10   ' Chaine de longueur fixe
   End Type
+   Dim maFiche As typeMesDonnées
De cette manière, tu pourras lire facilement les données d'une seule fiche d'un coup :
   Get #file, , maFiche
et retrouver tes données dans maFiche.ValeurNumérique et maFiche.Texte

Il ne sera pas possible de modifier la taille du texte après coup car les données qui suivent seraient décalées, c'est l'inconvénient des fichier binaires que l'on lit byte après byte.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
3
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
15 nov. 2007 à 06:16
Ok, merci à tous les deux, je vais essayer tout ça en espérant avoir assez de temps avant les cours pour mettre ça en place !  (je me suis levé un peu en avance pour voir s'il y avait des réponses, merci énormément à tous les deux :)
0
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
15 nov. 2007 à 07:19
Re-bonjour,

Je viens d'écrire, dans un module:

Public Pseudo As String
Dim DernierNiveau As Integer


Public Type DonneesPseudo
    Nick As String * 45
    Level  As Integer
End Type

'~~~~~~~~~~~~~~~~~~~~

Public Sub LoadDonneesPseudo(ByVal Filename As String)
   Dim sTemp As String * 45
   sTemp = Pseudo 
   Dim FichePseudoTemp As DonneesPseudo
   fic = FreeFile
   Open Filename For Binary As #fic
   Seek #fic, sTemp   'Ca ça ne marche pas, je ne trouve pas la syntaxe, j'ai cherché sur le net, ils disent que ça renvoie un long, mais si j'essaie de mettre "position=Seek #fic,stemp, il me renvoit une erreur dès la compilation.
'C'est censé regarder si le pseudo existe déjà ou non, et voir le dernier niveau associé dans le fichier
   Get #fic, , FichePseudoTemp   'J'aurais voulu mettre la position ici... (grâce au seek ci-dessus)
   Close #fic
   DernierNiveau = FichePseudoTemp.Level
   MsgBox Trim(Str(DernierNiveau))
End Sub


Public Sub SaveDonneesPseudo(ByVal Filename As String)
   Dim FichePseudoTemp As DonneesPseudo
   FichePseudoTemp.Nick = Pseudo
   FichePseudoTemp.Level = DernierNiveau
   fic = FreeFile
   Open Filename For Binary As #fic
   Put #fic, LOF(fic) + 1, FichePseudoTemp 'Pas sûr ici du LOF(fic)+1, je n'ai jamais utilisé cette fonction encore, le LOF indique la taille du fichier si j'ai bien compris, donc je pensais rajouter 1 pour écrire à la fin du fichier. Je ne peux pas vérifier que ça marche, ma fonction load ne fonctionne pas encore ;-)
   Close #fic
   DernierNiveau = FichePseudoTemp.Level
End Sub

Donc voilà, j'ai encore pas mal de problèmes avec ça, je vais essayer d'y réfléchir dans la journée, entre cours et réunions, merci encore MPi et jack (et désolé d'être aussi nul ^^").
Si quelqu'un connait la syntaxe, ou voit direct les (probablement énormes) erreurs, merci de me le dire, dans tous les cas, je vais y réfléchir de mon côté et continuer mes recherches après les cours :)
Ps: je sens qu'il va y avoir une distribution de "Réponse validée" à gogo ;-P
0

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

Posez votre question
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
15 nov. 2007 à 13:46
Rebonjour :)

Alors je viens de revoir ce que j'ai fait ce matin après avoir mangé, j'ai compris qu'en fait pour lire le fichier, il fallait dire à quel bit on débute (et donc demander la longueur de chaque élément de ma table, etc), donc la sauvegarde et la lecture marchent bien, j'ai fait tous les tests qu'il faut, sinon ce qui ne marche pas, c'est la fonction seek, je ne trouve pas la syntaxe, ni comment on l'utilise en fait.
Je pourrais utiliser une boucle et faire une lecture complète de mon fichier (je vois comment le faire maintenant que j'ai compris comment marchait la lecture du fichier en binaire), mais puisqu'apparament la fonction seek fait cela toute seule, je me dis que ça serait bête de me priver d'une telle fonction ;-)

Ce qu'il me faudrait, c'est trouver dans mes couples chaine/nombre, une chaine égale à la chaine que j'appelle "Pseudo" (grâce à la fonction seek), et connaitre sa position. De là, je saurais la position de mon couple et pourrais lire le nombre qui est couplé avec la chaine.

Il me manque la syntaxe pour le seek, donc encore une fois, si quelqu'un sait, qu'il me fasse signe, moi je continue de chercher, je peux rester ici encore un petit peu, je n'ai pas beaucoup de classes cet après midi :)
0
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
15 nov. 2007 à 13:55
Hmmm

Ici, j'ai trouvé quelque chose enfin en cherchant sur le net, disant que la fonction seek permet soit de retourner la position actuelle, soit de se placer à la position souhaitée.
Ca ne donne pas, selon la source, la position d'un texte, ou quelque chose écrit à l'intérieur, donc je vais faire mon système de boucle, je reviens distribuer une tonne de remerciements et des "réponses acceptées" quand j'ai fini de coder ça ;-)

ps: ce que j'ai trouvé sur le net, si ça peut aider d'autres personnes:

In the previous 4 sections, we have read a file from start to end. There has been no way to move backwards in a file, and no way to move forwards without first reading everything up to that position.
This is probably why Visual Basic has the <tt>Seek</tt> command. There are two ways to use <tt>Seek</tt>; as a function and as a command. If you use it as a function, it will return the current position within the file:

<tt>   Position = Seek(1) </tt>

Similarly, if you want to move to a specific location in the file, you use it this way:

<tt>   Seek #1, Position</tt>
0
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
15 nov. 2007 à 14:14
Hop, comme promis, je reviens, merci à tous les deux, MPi et jack encore une fois, j'ai appris encore plein de choses grâce à vous deux :)
(binary, get, put, LOF, seek, les types, les chaines à nombre de caractères controlé, et bien sûr la résolution de mon problème grâce à vous deux :D )


Des tonnes de merci, et puis à très bientôt j'espère :)


 


(ps: je mets mon code ici pour si il y a des personnes qui souhaiteraient s'en servir)


 


Public Pseudo As String
Public DernierNiveau As Integer


Public Type DonneesPseudo
    Nick As String * 45
    Level  As Integer
End Type
Dim FichePseudo As DonneesPseudo


Public Sub LoadDonneesPseudo(ByVal Filename As String) 'Regarde tout d'abord si il trouve la chaine Pseudo dans le fichier, si oui, elle affiche son niveau, et sinon, elle sauvegarde ce nouveau pseudo avec un niveau=1
Dim FichePseudoTemp As DonneesPseudo
Dim sTemp As String * 45
sTemp = Pseudo
Dim Longueur As Integer
Longueur = Len(FichePseudoTemp)
fic = FreeFile
Open Filename For Binary As #fic
For i = 1 To LOF(fic) Step Longueur
    Get #fic, i, FichePseudoTemp
    If FichePseudoTemp.Nick = sTemp Then
        Close #fic
        DernierNiveau = FichePseudoTemp.Level
        Exit Sub
    End If
Next
Close #fic
DernierNiveau = 1
SaveDonneesPseudo (App.Path & "\Test.dat")
End Sub


Public Sub SaveDonneesPseudo(ByVal Filename As String) 'Sauvegarde à la fin du fichier
Dim FichePseudoTemp As DonneesPseudo
FichePseudoTemp.Nick = Pseudo
FichePseudoTemp.Level = DernierNiveau
fic = FreeFile
Open Filename For Binary As #fic
Put #fic, LOF(fic) + 1, FichePseudoTemp
Close #fic
End Sub
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
16 nov. 2007 à 04:08
Re
Merci de ton anthousiasme, ça fait plasir.

Je t'ai embrouillé avec mes histoires de Seek, désolé.
Seek ne permet que de se balader parmi les Bytes du fichier. Cela n'a aucun lien avec la structure de tes données.

Juste un truc bizarre dans ton code :
Tu lis toutes les fiches à la recherche d'un Nom, tu mémorise DernierNiveau, puis tu sors de la boucle : Ok
Ensuite, tu refermes le fichier et ... tu réinitialise DernierNiveau à 1 : Tu vas perdre la donnée que tu viens de lire !

Encore deux :
- Méfie-toi quand tu compares deux chaines : la comparaison se fait avec les min et maj
  Pour comparer, passe les deux termes en minuscules, par exemple.
- Les chaines à longueur fixe comme FichePseudoTemp.Nick ne peuvent pas être comparées à une String standard.
  Les chaines à longueur fixe se terminent par des espaces, donc la comparaison risque de ne pas marcher :
Solution couplant ces deux remarques :
   If Left(LCase(FichePseudoTemp.Nick), Len(sTemp)) = LCase(sTemp) Then

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
16 nov. 2007 à 04:14
PS : Désolé, il est tard. Je n'avais pas vu que tu avais pris la précaution de dimensionner sTemp comme chaine à longueur fixe.
Il n'y aura donc aucun problème avec la comparaison (sauf pour les min/maj), autant pour moi.
0
mstarsup5 Messages postés 527 Date d'inscription lundi 15 octobre 2007 Statut Membre Dernière intervention 10 octobre 2013 1
16 nov. 2007 à 07:41
Salut jack, pour le fait que je demande DernierNiveau=1 après la boucle, ça se fait seulement si le programme n'a pas trouvé le pseudo dans le fichier, si il trouve le pseudo dans le fichier, il donne le niveau lu, et sort du sub :)
Donc il n'arrive dans la partie "DernierNiveau=1" que si la  recherche n'a pas été concluante, pour initialiser le tout (c'est pour celà que j'envoie le prog sur "savedonneespseudo", pour qu'il m'enregistre les données pour ce nouveau pseudo) :)

Ps: pour le seek, finalement je m'en suis servi pour lire dans un fichier dans lequel j'ai précédement (hier) enregistré les niveaux du jeu, le seek me permet de charger le niveau qui m'intérese directement sans le chercher avec une boucle ;-)

Et pi même si je ne m'en étais pas servi, grâce à toi j'ai pu voir la fonction, donc il n'y a pas de mal :D

Merci encore, et à une prochaine!
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
16 nov. 2007 à 17:18
Re
Décidemment, je n'avais pas les yeux en face des trous.
Ok pour le DernierNiveau, mais le "Exit Sub" n'est pas très 'propre', un peu brutal.
Dimensionne une variable :
   Dim bTrouvé As Boolean
Dans ta boucle de recherche, si tu trouves ce que tu cherches :
- mémorise les données
- supprime le Close qui est dans la boucle For-Next
- puis passe le bTrouvé à True
- Fais un "Exit For" pour sortir de la boucle
- Après avoir fermé le fichier (que tu aies trouvé ou pas la donnée), fais le simple test :
   If Not bTrouvé Then
      DernierNiveau = 1
      SaveDonneesPseudo (App.Path & "\Test.dat")
   End If
- et laisse la Sub se fermer naturellement.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
Rejoignez-nous