Page 1 sur 2

Variable structure et sauvegarde

Publié : jeu. 23/nov./2006 9:47
par Kwai chang caine
Bonjour

Peut on sauvegarder une variable structure avec une seule instruction ??

Code : Tout sélectionner

Structure Autorisations
 Logiciel.s
 Utilisateur.s
 Machine.s
EndStructure 

Acces.Autorisations

Acces\Logiciel = "1"
Acces\utilisateur = "2"
Acces\Machine = "3"

OpenFile(1,"c:\Essais.txt")
WriteLong(1,Acces) 
CloseFile(1)

Acces\Logiciel = ""
Acces\utilisateur = ""
Acces\Machine = ""

OpenFile(1,"c:\Essais.txt")
Acces =  ReadLong(1) 
CloseFile(1)
Ou bien est on obligé de sauvegarder chaque element de la structure les uns apres les autres ? :

Code : Tout sélectionner

Structure Autorisations
 Logiciel.s
 Utilisateur.s
 Machine.s
EndStructure 

Acces.Autorisations

Acces\Logiciel = "1"
Acces\utilisateur = "2"
Acces\Machine = "3"

OpenFile(1,"c:\Essais.txt")
WriteStringN(1,Acces\Logiciel) 
WriteStringN(1,Acces\utilisateur) 
WriteStringN(1,Acces\Machine) 
CloseFile(1)

Acces\Logiciel = ""
Acces\utilisateur = ""
Acces\Machine = ""

OpenFile(1,"c:\Essais.txt")
Acces\Logiciel = ReadString(1)
Acces\utilisateur = ReadString(1) 
Acces\Machine = ReadString(1)
CloseFile(1)
Merci
Bonne journée

Publié : jeu. 23/nov./2006 9:54
par Progi1984
Il faut sauvegarder chaque élément de la structure !

Publié : jeu. 23/nov./2006 10:06
par Kwai chang caine
Merci Progi de ta réponse rapide 8)

Et pour les listes chainées, c'est pareil, ou bien existe t'il une instruction pour la sauvegarder d'un coup ?

Publié : jeu. 23/nov./2006 10:51
par Progi1984
C'est pareil !

Par contre, attends d'avoir une autre réponse pour confirmer mes dires !

Publié : jeu. 23/nov./2006 11:04
par Kwai chang caine
Merci bien et bonne journée à toi :wink:

Publié : jeu. 23/nov./2006 11:49
par Flype
tu peux sauvegarder une structure dans un fichier dans certaines situations :

Code : Tout sélectionner

Structure Autorisations
  Logiciel.s{16}
  Utilisateur.s{16}
  Machine.s{16}
EndStructure 

Acces.Autorisations

Acces\Logiciel    = "MonLogiciel"
Acces\Utilisateur = "MonUtilisateur"
Acces\Machine     = "MaMachine" 

Debug @Acces\Logiciel
Debug @Acces\Utilisateur
Debug @Acces\Machine

If CreateFile(1,"c:\essais.txt")
  WriteData(1, @Acces, SizeOf(Autorisations))
  CloseFile(1) 
EndIf

Publié : jeu. 23/nov./2006 12:07
par Dorian
Merci Flype pour ton code. Celui-là va passer dans mes stock (pour le retrouver quand je serais bloqué ^^)

Publié : jeu. 23/nov./2006 15:03
par Guimauve
Flype ton astuce n'est l'idéal, tu donne une longueur fixe aux chaînes de caractères. Et si je te disais que les longueurs doivent rester variables alors ton astuce n'est plus valide.

Je me répète pour la x ième fois, quand vous avez une structure qui contient des chaînes de caractère qui doit être écrite dans un fichier binaire

ON DOIT TOUJOURS ÉCRIRE UN LONG POUR INDIQUER LA LONGUEUR DE LA CHAÎNE AVANT D'ÉCRIRE LE DATA DE LA CHAÎNE.

ENSUITE QUAND ON LIT DANS LE FICHIER, ON LIT UN LONG, AVEC SPACE ON INITIALISE LA CHAÎNE VIDE À LA BONNE LONGUEUR ET ON LIT LE DATA DE LA CHAÎNE.

Voiçi un exemple opérationnel.

A+
Guimauve

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; CODE GÉNÉRÉ AUTOMATIQUEMENT, NE PAS MODIFIER À
; MOINS D'AVOIR UNE RAISON TRÈS TRÈS VALABLE !!!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Déclaration de la Structure <<<<<

Structure Autorisations
   
   Logiciel.s
   Utilisateur.s
   Machine.s
   
EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les mutateurs <<<<<

Macro SetAutorisationsLogiciel(AutorizeA, P_Logiciel)
   
   AutorizeA\Logiciel = P_Logiciel
   
EndMacro

Macro SetAutorisationsUtilisateur(AutorizeA, P_Utilisateur)
   
   AutorizeA\Utilisateur = P_Utilisateur
   
EndMacro

Macro SetAutorisationsMachine(AutorizeA, P_Machine)
   
   AutorizeA\Machine = P_Machine
   
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les observateurs <<<<<

Macro GetAutorisationsLogiciel(AutorizeA)
   
   AutorizeA\Logiciel
   
EndMacro

Macro GetAutorisationsUtilisateur(AutorizeA)
   
   AutorizeA\Utilisateur
   
EndMacro

Macro GetAutorisationsMachine(AutorizeA)
   
   AutorizeA\Machine
   
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Update <<<<<

Macro UpdateAutorisations(AutorizeA, P_Logiciel, P_Utilisateur, P_Machine)
   
   SetAutorisationsLogiciel(AutorizeA, P_Logiciel)
   SetAutorisationsUtilisateur(AutorizeA, P_Utilisateur)
   SetAutorisationsMachine(AutorizeA, P_Machine)
   
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Lecture fichier Binaire <<<<<

Procedure ReadAutorisations(FileID.l, *AutorizeA.Autorisations)
   
   SetAutorisationsLogiciel(*AutorizeA, Space(ReadLong(FileID)))
   ReadData(FileID, @GetAutorisationsLogiciel(*AutorizeA), Len(GetAutorisationsLogiciel(*AutorizeA)))
   SetAutorisationsUtilisateur(*AutorizeA, Space(ReadLong(FileID)))
   ReadData(FileID, @GetAutorisationsUtilisateur(*AutorizeA), Len(GetAutorisationsUtilisateur(*AutorizeA)))
   SetAutorisationsMachine(*AutorizeA, Space(ReadLong(FileID)))
   ReadData(FileID, @GetAutorisationsMachine(*AutorizeA), Len(GetAutorisationsMachine(*AutorizeA)))
   
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Écriture fichier Binaire <<<<<

Procedure WriteAutorisations(FileID.l, *AutorizeA.Autorisations)
   
   WriteLong(FileID, Len(GetAutorisationsLogiciel(*AutorizeA)))
   WriteData(FileID, @GetAutorisationsLogiciel(*AutorizeA), Len(GetAutorisationsLogiciel(*AutorizeA)))
   WriteLong(FileID, Len(GetAutorisationsUtilisateur(*AutorizeA)))
   WriteData(FileID, @GetAutorisationsUtilisateur(*AutorizeA), Len(GetAutorisationsUtilisateur(*AutorizeA)))
   WriteLong(FileID, Len(GetAutorisationsMachine(*AutorizeA)))
   WriteData(FileID, @GetAutorisationsMachine(*AutorizeA), Len(GetAutorisationsMachine(*AutorizeA)))
   
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Lecture d'une liste chaînée dans le fichier en cours <<<<<

Procedure ReadLinkedListOfAutorisations(FileID.l, LList.Autorisations())
   
  LIST_MAX = ReadLong(FileID)
   
   For Index = 1 To LIST_MAX
      AddElement(LList())
      ReadAutorisations(FileID, LList())
   Next
   
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Écriture d'une liste chaînée dans le fichier en cours <<<<<

Procedure WriteLinkedListOfAutorisations(FileID.l, LList.Autorisations())
   
   WriteLong(FileID, CountList(LList()))
   
   ForEach LList()
      WriteAutorisations(FileID, LList())
   Next
   
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Macro de déboguage <<<<<

Macro DebugAutorisations(AutorizeA)
   
   Debug GetAutorisationsLogiciel(AutorizeA)
   Debug GetAutorisationsUtilisateur(AutorizeA)
   Debug GetAutorisationsMachine(AutorizeA)
   
EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code généré en : 00.031 secondes <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;/ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;/ <<<<< !!! ATTENTION - VOUS ÊTES MAINTENANT DANS UNE ZONE DE TEST - ATTENTION !!! <<<<<
;/ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

NewList Maliste.Autorisations()

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On ajoute des éléments à la liste

AddElement(Maliste())
UpdateAutorisations(Maliste(), "PureBasic", "Fred", "Windows")

AddElement(Maliste())
UpdateAutorisations(Maliste(), "Visual Designer", "Darth Vador", "Mac OS")

AddElement(Maliste())
UpdateAutorisations(Maliste(), "MS Word", "Abraham Lincolm", "Windows")

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On regarde ce que ça donne

Debug "On regarde ce que ça donne"

ForEach Maliste()
   
   Debug "-------------------------------------------"
   DebugAutorisations(Maliste())

Next

Debug "-------------------------------------------"

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On enregistre la liste dans un fichier binaire

Debug "On enregistre la liste dans un fichier binaire"

If CreateFile(0, "Mon fichier binaire.dat")
   
   WriteLinkedListOfAutorisations(0, Maliste())
   
   CloseFile(0)
Else 
   MessageRequester("Erreur", "Impossible de créer le fichier !")
EndIf

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On vide la liste

Debug "On vide la liste"

ClearList(Maliste())

Debug CountList(Maliste())

Debug "-------------------------------------------"

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On lit la liste dans un fichier binaire

Debug "On lit la liste dans un fichier binaire"

If OpenFile(1, "Mon fichier binaire.dat")
   
   ReadLinkedListOfAutorisations(1, Maliste())
   
   CloseFile(1)
Else 
   MessageRequester("Erreur", "Impossible de lire le fichier !")
EndIf

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; On regarde ce que ça donne

Debug "On regarde ce que ça donne depuis la lecture"
Debug "du fichier binaire"

ForEach Maliste()
   
   Debug "-------------------------------------------"
   DebugAutorisations(Maliste())
   
Next

Debug "-------------------------------------------"

; <<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< FIN DU FICHIER <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<

Publié : jeu. 23/nov./2006 15:08
par Flype
ah et j'oubliais - enregistrer les données c'est sympa que si on peut les recharger. donc voici un source plus complet :

Code : Tout sélectionner

; Example de persistence des données dans une structure
; PureBasic4.0 - flype - 2006.


; Définition de la structure 'persistente'

Structure Autorisations
  Version.l
  Logiciel.s{32}
  Utilisateur.s{32}
  Machine.s{32}
  MotDePasse.c[8]
EndStructure 

Acces.Autorisations


; On définit des valeurs pour la variable 'Acces'

Acces\Version     = 123456
Acces\Logiciel    = "MonLogiciel"
Acces\Utilisateur = "MonUtilisateur"
Acces\Machine     = "MaMachine" 
PokeS(@Acces\MotDePasse, "A0B1C2D3")


; On enregistre la variable 'Acces' et ses champs dans un fichier

If CreateFile(1,"c:\essais.txt")
  WriteData(1, @Acces, SizeOf(Autorisations))
  CloseFile(1) 
EndIf


; On remet à Zéro la variable 'Acces'

Acces\Version     = #Null
Acces\Logiciel    = #Null$
Acces\Utilisateur = #Null$
Acces\Machine     = #Null$
PokeS(@Acces\MotDePasse, #Null$)


; On recharge dans la variable 'Acces' les données enregistrées dans le fichier

If ReadFile(1,"c:\essais.txt") 
  ReadData(1, @Acces, SizeOf(Autorisations)) 
  CloseFile(1) 
EndIf 


; Pour preuve, les données sont bien remontées malgré la remise à zéro (ligne 34).

Debug Acces\Version
Debug Acces\Logiciel
Debug Acces\Utilisateur
Debug Acces\Machine
Debug PeekS(@Acces\MotDePasse, 8)

:)


Bon sinon il faut comprendre en fait que seuls les chaines de caractères '.s' ou '$' ne peuvent pas être enregistrées de cette façon puisqu'elles sont allouées dynamiquement en mémoire. Seul le pointeur de la chaine serait enregistré ce qui n'a aucun intérêt. Par contre avec des chaines 'fixes' ( champs.s{NbOctets} ) comme on a vu c'est OK. Mais ca fonctionne aussi avec des types de données plus classiques.

Publié : jeu. 23/nov./2006 15:17
par Flype
@Guimauve

ok d'accord, tu es prié de modérer tes propos.

qu'est ce que j'ai écris ici en avertissement ?
tu peux sauvegarder une structure dans un fichier dans certaines situations.
alors t'es gentil mais même si tu as raison, la question est de savoir si on peut enregistrer une structure dans un fichier en une ligne ou deux. la réponse est que dans la plupart des cas c'est NON, maintenant si on fait attention à ce qu'on fait, cela ne pose AUCUN problème !

une chaine de caractères est certes variables mais la longueur des données est souvent fixée à un maximum.

Enfin faite comme vous voulez - apprenez à maitriser différentes situations - j'en ai montré une - Guimauve en montre une autre - çà fait 2 méthodes. très bien.

Publié : jeu. 23/nov./2006 15:29
par Flype
ON DOIT TOUJOURS ÉCRIRE UN LONG POUR INDIQUER LA LONGUEUR DE LA CHAÎNE AVANT D'ÉCRIRE LE DATA DE LA CHAÎNE.

ENSUITE QUAND ON LIT DANS LE FICHIER, ON LIT UN LONG, AVEC SPACE ON INITIALISE LA CHAÎNE VIDE À LA BONNE LONGUEUR ET ON LIT LE DATA DE LA CHAÎNE.
en plus, excuse moi mais c'est faux.

d'où tu postule que TA façon c'est la SEULE viable - cà fait un peu dictat ta façon de parler au gens, non ?

et si je n'ai pas envie d'écrire un LONG avant ma chaîne ?
je peux - il y a d'autres méthodes. Le caractère 0 de fin de chaines est aussi une autre méthode.

Publié : jeu. 23/nov./2006 15:59
par Backup
moi ca que je ne comprends pas , c'est pourquoi il n'est pas fait allusion dans la Doc de ce genre d'écriture

Code : Tout sélectionner

 Logiciel.s{32} 
je ne savais même pas que cela existais !! 8O

pareil , pas trouvé d'info dans la Doc , sur les Structures a propos des tableaux Static !! :?

Code : Tout sélectionner

Logiciel.s[32] 

Publié : jeu. 23/nov./2006 16:11
par Guimauve
C'est vrai que j'y suis peut-être aller un peu fort, veuillez m'excuser.

Sauf que regarde bien ce qui arrive pendant la vie d'un programme

Le programme en question utilise cette Structure :

Code : Tout sélectionner

Structure Autorisations
  Logiciel.s{16}
  Utilisateur.s{16}
  Machine.s{16}
EndStructure 
Après 2 ans d'utilisation, et probablement beaucoup de donnée d'enregistré, genre 200 Go, la structure doit être modifié pour celle-ci

Code : Tout sélectionner

Structure Autorisations
  Logiciel.s{32}
  Utilisateur.s{64}
  Machine.s{32}
EndStructure 
Là si tu n'as pas écrit la longueur de la chaîne ça va vraiment être le bordel de charger les données des 2 versions avec le même système.
en plus, excuse moi mais c'est faux.

d'où tu postule que TA façon c'est la SEULE viable - cà fait un peu dictat ta façon de parler au gens, non ?

et si je n'ai pas envie d'écrire un LONG avant ma chaîne ?
je peux - il y a d'autres méthodes. Le caractère 0 de fin de chaines est aussi une autre méthode.
Je ne dis pas que c'est la seule méthode viable, ce que je dis c'est que c'est la méthode que semble être la plus robuste. Dans le cas de cette structure c'est facile tout les types sont identiques, parcontre si les types sont variés (.b, .c, .w, .l, .f, .q, .d) et des types utilisateurs en même temps dans la même structure, trouver le caractère de fin de chaîne semble est difficile voir peut-être même impossible.

Ma manière de programmer est très rigide certe, mais je dirais que depuis que fais les choses de cette manière, le temps de débogguage est réduit de 80 à 90% et les programmes sont bien plus stables.

Mais le plus important, ma méthode n'engage personne.

@Flype - Pour le message précédent, j'aurais pu mettre la font à 18, en gras et en rouge, mais je l'ai pas fais.

Guimauve

Publié : jeu. 23/nov./2006 19:14
par Flype
@Guimauve

je répète que tu as raison et je saisis parfaitement ce que tu veux dire :) .
je suis moi même développeur de softs (pour l'entreprise où je travaille). Mes logiciels ont pour certains déjà 3ans d'age, d'autres 2ans, d'autres tout récents. Et, oui, penser à l'évolutivité ( en plus de la compatibilité ) des programmes est quelque chose qui me vient à l'esprit au quotidien, du coup.
J'ai beaucoup de données aussi à stocker et il n'est pas rare que ces données doivent évoluer. Des moulinettes, j'en ai codées... Ceci dit, ma tache est simplifié énormément par l'utilisation de base de données (mysql ou postgres) via les commandes database de purebasic.

l'objectif que j'avais au travers de mon exemple n'était pas d'imposer ou meme de conseiller une facon de faire mais juste de montrer que c'est possible de sauvegarder une structure - brute de pommes - dans un fichier. si, bien sûr, la structure s'y prête et que l'on a une bonne raison de faire comme çà. On peut programmer sérieusement et parfois s'amuser avec des codes un peu exotiques du moment qu'on sait ce qu'on fait.

j'ai eu des cas en programmant des périphériques (toujours pour l'entreprise où je bosse) où j'ai dû codé comme çà parce que c'etait les recommandations du constructeurs (API en C)... et j'ai découvert à ce moment que c'était possible de le faire en PureBasic alors je partage mon savoir sur ce point précis.


@dobro
les string.s{taille} sont dans la documentation purebasic
CHM -> Variables, Types et Opérateurs -> Tableau Types basiques -> Dernière ligne.

OK, je te l'accorde la doc n'explique vraiment pas comment s'en servir ni à quoi ca sert. Cette fonctionnalité est arrivé avec PB4.0 et ca été évoqué quelquefois déjà je pense sur ce forum et beaucoup sur le forum officiel.

Attention ce type de String n'est pas terminé par un 0 comme les chaines classiques. Par contre çà c'est dans la doc (Ouf).

[EDIT]
c'est d'ailleurs pour cette raison précise (chaine non terminée par zéro)
que la dernière ligne de mon exemple est :
Debug PeekS(@Acces\MotDePasse, 8)

Publié : jeu. 23/nov./2006 20:45
par Kwai chang caine
Alors la !!!!!!on peux dire que j'ai eu une reponse :lol:

Moi qui dab est 300 visites et jamais de solutions, j'suis ébourrifé :lol:

Je vous remercie tous pour votre aide. 8)
Passez une excelente soirée