Fichier a Acces Direct (Ramdom Access File) et BitMap +.DBF

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Fichier a Acces Direct (Ramdom Access File) et BitMap +.DBF

Message par GeBonet »

Bonjour à tous,

Voilà, mon problème était de pouvoir travailler avec un des fichiers de type "aléatoire" avec enregistrements de longueur fixe
avec accès direct (Ramdon Acces Files) que l'on retrouve dans d'autres langages. Ou si on veut du type :
'Open "Adresses.dat" for Random As #Buffer Len=Longueur'.

Le problème pour créer un bloc de donnée de longueur fixe provenait de la nécessité de convertir les valeurs numériques
qu'elles soit "entier", "double précision", ou autres en une forme telle qu'elles aient des longueurs fixes en fonction de leurs types.
C'est ce que font les procédures crées par "Wilbert" du forum officiel.
A partir de là il "suffit" de composer l'enregistrement en fonction du Type(i) et de la longueur octroyé Long(i) pour chaque Champ$(i) de donnée.

Fichier à ACCES DIRECT de longueur fixe sur DISQUE :

* C'est simplement une autre forme de possibilité d'accéder aux données sur disque.

Avantage :

- Sur de très gros fichier, ne pas avoir à charger tout le fichier en mémoire
- D'accéder à l'enregistrement "N°" directement sans devoir lire les autres...
- Pouvoir travailler à plusieurs sur un même fichier en verrouillant l'enregistrement sur lequel on travaille (Mise à jours)
tout en laissant les autres en libre accès.
- Pouvoir mettre à jours n'importe quel enregistrement sans devoir déplacer les autres (c'est une pile de "blocDATA$" de même longueur...)
- Ajouter / Supprimer des enregistrements sans aucun déplacement des autres...
Dans ce cas il est préférable d'avoir une bonne gestion des enregistrements occupés ou libres via une Bitmap par exemple ou à la position de chaque BIT
corresponde la position d'un enregistrement sur le disque. Dès l'or l'état du Bit définit également l'état de l'enregistrement. Bit à 1 occupé et 0 libre.
Ce qui conduit par exemple au fait que pour supprimer un enregistrement , il suffit de mettre son Bit de la "BitMap" à 0…

Inconvénient / Désavantage majeur !

- La longueur fixe de l'enregistrement !
- En conséquence prédétermination obligatoire des longueurs des champs
- N'existe pas de système de base de conversion pour les valeurs numérique dans PureBasic tel que :
Par exemple : MKI, MKL, MKF, MKD, MKQ et CVI, CVL, CVF, CVD, CVQ) mais ici cela à été remédié dans ces exemples...

Méthodologie :

Pour travailler efficacement sur un fichier résident sur disque, il est préférable de disposer d'un enregistrement d'initialisation ou "Secteur Zéro". Ce secteur sera composé d'information identifiant le fichier et ayant les paramètres utiles à sa gestion. Il va de soit que cela est une convention et que celle-ci dépendra de celui qui le crée. Aussi je commencerais par définir mon "Secteur Zéro". Comme avec PureBasic on peut définir une structure, nous allons l'utiliser pour créer ce "Secteur". Il est évident que ce type de "Secteur Zéro" peut-être utilisé pour n'importe quel type de fichier… Même un séquentiel de PureBasic ou nous aurions cette structure pour le secteur d'initialisation et une autre structure qui définirait la nature des données elles mêmes.

Si la BitMap est d'un grand intérêt, elle n'est pas utilisée ici, mais le sera dans un prochain modèle. Si je ne l'ai pas installé ici c'est par soucis de présenter un système assez clair à lire et de le comprendre sans trop l'encombrer.

Nous avons donc un module charnière qui est le"IncLectureDirect.pbi", contenant la plupart des procédures de lectures, écritures dans le fichier Direct.
Puis, un module créant un fichier "EcritureDirect.pb" sur base des "data" inclue. Ce module utilise l'include ci-dessus.
Evidement un module lisant ce qui a été créé par le premier "LectureDirect.pb", utilisant aussi l'include…
Et enfin un modèles plus complet "ExpleGestionDirect.pb", qui lui présente une fenêtre qui est censé gérer un fichier d'adresse… Il y a donc une partie avec une fenêtre, une partie qui lis les datas définissant les types et longueur des champs et une boucle de gestion des différents champs de la fenêtre. Le tout reposant comme les deux premiers sur "IncLectureDirect.pbi"...

Les 3 programmes et l'Includes sont commentés... !
Ils ne sont pas spécialement sécurisés et presque toutes les variables sont Globales.
Voilà, si ça vous intéresse il y aura une suite avec la BitMap Inclue...
Voir une gestion indexée et ordonnée avec plusieurs clefs donc la première unique ou automatique...
Voilà, voilà...

Première partie l'Include "IncLectureDirect.pbi"

Code : Tout sélectionner

; **************************************************************************;
; Exemple de GESTION d'un FICHIER à ACCES DIRECT sur DISQUE     Vers.: 1.0  ;
; ---------------+----------------------------------------------------------;
; Auteur         : GeBonet (et merci à Wilbert pour MK...CV.. )             ;
; Mise en oeuvre : 01/11/2011                                               ;
; Dern. Update   : 11/11/2011   ****************************                ;
; PureBasic 4.6  :              *** IncLectureDirect.pbi ***                ; 
; XpPro,Windows 7:              ****************************                ; 
; ************   +----------------------------------------------------------;
;  ATTENTION : A compiler avec UNICODE décoché dans "Options du compilateur"; 
; ************   +----------------------------------------------------------;
; **************************************************************************;
; Tableaux de base utiles :       A INITIALISER SI ON UTILISE PAS AILLEURS AVANT... 
; EnableExplicit      
; Global Rep$
; --------------------------------------------------------------------------------------
;{ Si on travaillait avec plusieurs fichiers ces tableaux pourraient-être :
; ======>>> Type(NoFile, NbChamp), Long(NoFile, NbChamp) et Champ$(NoFile, NbChamp)
;
; En sachant que Type(j) ou Type(i,j) contient le type de donnee du Champ$(i) ou Champ$(i,j)
; et que selon le Cas il serait codé ou décodé selon que :
; Type = 0 :Champ$(j)=LSet(Champ$(j),long(j)," ") ; AlphaNumérique 
;        1 :Champ$(j)=MKI(Val(Champ$(j)))         ; Entier 
;        2 :Champ$(j)=MKL(Val(Champ$(j)))         ; Long 
;        3 :Champ$(j)=MKF(ValF(Champ$(j)))        ; Flottant 
;        4 :Champ$(j)=MKD(ValD(Champ$(j)))        ; Double     
;        5 :Champ$(j)=MKQ(Val(Champ$(j)))         ; Quad 
;        6 :Champ$(j)=Champ$(j)                   ; Date forme "jj/mm/aaaa"
;} --------------------------------------------------------------------------------------
Structure CV_MK_Struct  ;{ ***-- Conversion functions --***
	StructureUnion
		f.f
		d.d
		l.l
		q.q
		s5.s{5}
		s10.s{10}
	EndStructureUnion
EndStructure;}
;{ -                      CONSTANTES pour l'enregistrement ZERO -
;  - Entete de fichier standard - 40 Bytes ! Mais peut être allongé si nécéssite d'autre infos. 
  #File_Nature        =  0  ; 0 Nature du fichier (Voir code ci-après)     
  #File_RecNumber     =  1  ; 1 Nombre d'enregistrement
  #File_LongRecord    =  5  ; 5 Longueur de l'enregistrement
  #File_CreationDate  =  9  ; 9 Date de création
  #File_LastAccessDate= 13  ;13 Date dernier accès
  #File_KeyRecord     = 17  ;17 Champs qui contient la clef d'accès principale
  #File_BitMap        = 21  ;21 Optionnel si BitMap (Nbr. Enregistrement BitMap)
  #File_Reserve       = 25  ;25 Chaine de caractères variable mais < que "LongRECORD")
;}
Structure Record_Zero ;{ Enregistrement de Gestion du fichier... 
  
  NatureFILE.b        ; #File_Nature         =  0   ; Type de fichier 
  RecNumber.l         ; #File_RecNumber      =  1   ; Nombre d'enregistrement
  LongRECORD.l        ; #File_LongRecord     =  5   ; Longueur de l'enregistrement
  CreationDate.l      ; #File_CreationDate   =  9   ; Date de création
  LastAccessDate.l    ; #File_LastAccessDate = 13   ; Date dernier accès
  ChampDeLaClef.l     ; #File_KeyRecord      = 17   ; Champs qui contient la clef d'accès principale
  TailleBitMap.l      ; #File_BitMap         = 21   ; Optionnel si utile (nbr d'enregistrement utile)
  FlagReserve.s{15}   ; #File_Reserve        = 25   ; Chaine de caractères variable mais < que "LongRECORD"

EndStructure          ;} Longueur total       = 25 + 15 => 40 Bytes si FlagReserve.s = 15... 
Global *mon.Record_Zero ;  
#Max_Premier=SizeOf(Record_Zero)
;{ - - - - - Global - - - - - - - - - - - - - - - - - --
Global FirstRec, nomFichier.s ,Phrase.s
Global RecNo, Position, Resultat, Suivant 

Global DebFichier.q, FinFichier.q, Dernier.l, Nb_Colonne, list_nr
Global NbLigne, ChampKey, Expression$
Global NbrBitMap, BitMap$, Fonction
; --------------------------------------------------------
Global i, j, k, No, Type, DebutString, NbCar, D1$, Texte$
Global NoFile, NoKey, NbChamp, NbRecord, LongTOT, Nature
; --------------------------------------------------------

Global Nature, NatureFILE.b,  RecNumber.l,  LongRecord.l, LongTOT, CreationDate.l
Global LastAccessDate.l, ChampDeLaClef.l, TailleBitMap.l, FlagReserve.s

; Premier enregistrement (paramètres)
Global blocDATA$, Record$, Clef$, I$

Global FontID1: FontID1 = LoadFont(1, "Arial", 22, #PB_Font_Bold)
Global FontID2: FontID2 = LoadFont(2, "Arial", 10)
; --------------------------------------------------------------------------------------
; Tableaux de base si on utilise les DATAs pour fichier à longueur FIXE :
; -                 
Global Dim Type(NbChamp)    ; Tableau des types de données dans le fichier... 
Global Dim Long(NbChamp)    ; Tableau des longueur de champs dans le fichier... 
Global Dim Champ$(NbChamp)  ; Tableau recevant les données de chaque champs... 

;Global Dim TextToSort$(1)   ; Tableau si utilise le triage
;} -
; -    Declaration Gestion Fichiers
;{ - - - - - - - - - - - - - - - - - - - - - - - - - - -
Declare.s Creation_Fichier(NoFile, NomFichier.s)
Declare.s OuvreFichier(NoFile, NomFichier.s,LongTOT)
Declare LecturePremier()
Declare EcritPremier()
Declare EcritZero()
; - - - - : ------------------;
Declare.s Get(NoFile, RecNo)  ; 3  
Declare.s Put(NoFile, RecNo)  ; 4
Declare.s Add(NoFile, Record$); 5
Declare.s Upd(NoFile, RecNo)  ; 6 Mise a jours actuel     
Declare.s Del(NoFile, RecNo)  ; 7 Efface ""      ""       
Declare.s Nex(NoFile, RecNo)  ; 8 Suivant 
Declare.s Prv(NoFile, RecNo)  ; 9 Precedent
Declare.s Der(NoFile)         ;10 Dernier 
Declare.s Pre(NoFile)         ;11 Premier
; - - - - : ------------------;
Declare.s Cherche(NoFile, Key$)
Declare.s CloseRandom(NoFile)
; - - - - : ------------------;
Declare AfficheDebug()        ; Pour les TESTS 
Declare GadgetBalTip(WindowNumber.l, GadgetNumber.l, Text.s)
Declare Triage(Taille, Array TextToSort$(1))
; - - - - : ------------------;
Declare Gest_BitMap(BitMap$, FoncTion, RecNo)
;} - - - -: ------------------;

; -------------------------------------------------------------------------------------:
;{ -   Declaration Conversions  -
; 
Declare CV_Adapt(*cv, bytes)
Declare MK_Adapt(*cv, bytes)
; ----------------------------------
Declare.s MKI(i.i)
Declare.i CVI(s.s)
Declare.s MKF(f.f)
Declare.f CVF(s.s)
Declare.s MKD(d.d)
Declare.d CVD(s.s)
Declare.s MKL(l.l)
Declare.l CVL(s.s)
Declare.s MKQ(q.q)
Declare.q CVQ(s.s)
; ----------------------------------
Declare.s conver_En_DataBLOC(NbChamp, LongTOT, Array Type(1), Array Long(1), Array Champ$(1))   
Declare.s conver_Record_EnCHAMP(NbChamp, Record$, Array Type(1), Array Long(1), Array Champ$(1))
;} ---------------------------------------------------------------------------------------------:
; =======================================================
; - O U V R E FICHIER et C R E A T I O N si inexistant  -
; =======================================================
Procedure.s OuvreFichier(NoFile, NomFichier.s, LongTOT) ; Ouvre le fichier
  ; ENTREE : NoFile       : ID du fichier 
  ;        : NomFichier.s : Nom du fichier (avec extension)  
  ; -------------------------------------------------------------------
  FirstRec=SizeOf(Record_Zero)+1          ; Position pour écrire le premier enregistrement
  If OpenFile(NoFile, Rep$+NomFichier.s)  ; Ouverture du fichier    
    Resultat = IsFile(NoFile)             ; Valable ? 
    If Resultat                           ; Ok 
      DebFichier=Loc(NoFile)              ; Debut du fichier
      FinFichier=Lof(NoFile)              ; Fin du fichier
      ; -----------------------------------------------------------------------------------------------------
      If FinFichier=DebFichier            ; Elle sont égale si Le fichier est nouveau il doit etre initialisé 
        ;                     ;           ; -----------------------------------------------------------------
        Creation_Fichier(NoFile, NomFichier.s) ;  ALORS      - On crée l'enregistrement ZERO (Paramètres)
        ; --------------------------------- -----------------------------------------------------------------
      Else ; ICI le fichier existe et contient des données... 
        ; ----------------------------------------------------
        ; Lecture premier enregistrement... 
        LecturePremier()                  ; Lecture de l'enregistrement "0"
        ;
        Suivant=Loc(NoFile) 
        FinFichier=Lof(NoFile)
        FirstRec=SizeOf(Record_Zero)+1
        ; ------------
        NbLigne=RecNumber
        ;
      EndIf
      ; -----------------------------------------------
      ; Positionne le pointeur à la fin du fichier... (du premier)
      FileSeek(NoFile,FinFichier)         ; Se positionne en fin
      ProcedureReturn Str(FinFichier)
    EndIf  
  EndIf  
  ;    
EndProcedure
; =======================================================
; -               Initialisation du FICHIER             -
; =======================================================
Procedure.s Creation_Fichier(NoFile, NomFichier.s)      ; Création et Initialise le fichier
  ;                                             Ou initialisation du fichier ...
  FirstRec        =SizeOf(Record_Zero)        ; --------------------------------
  Nature          =Nature ; Type de fichier   ; 0=Séqu, 1=Direct long. FIXE, 2=Direct Long. VARIABLE 
  NbLigne         =0      ; Nombre d'enregistrement
  LongTOT         =LongTOT; Longueur de l'enregistrement
  CreationDate.l  =Date() ; Date de création
  ChampKey        =0      ;  Champ de la clef principale unique si il y a lieu
  NbrBitMap       =0      ; Taille de la BitMap s'il y a 
  Expression$     =LSet("GeBonet",15,"*") ; Chaine de 15 caractères 
  ;                       ; 
  EcritPremier()          ; Ecrit enregistrement 0
  ; 
EndProcedure
; =======================================================
; - E C R I T U R E Enregistrement ZERO (Init Secteur) -
; -------------------------------------------------------
Procedure EcritPremier()                                ; Ecriture du secteur ZERO
  ; Le premier enregistrement (0) est utilisé pour sauver des paramètres 
  ; de gestion du fichier ou des indicateurs de travail. Il doit être mis
  ; à jour après chaque écriture d'un enregistrement. Par appel de 'EcritZero()'
  ; ---------------------------------------------------------------------  
  If CreationDate  =0:CreationDate=Date():EndIf; Si la date de création n'existe pas !
  ;
  Nature=1        ; Fichier de type Direct 
  FirstRec         =SizeOf(Record_Zero)        ; Position du premier enregistrement
  FinFichier       =Lof(NoFile)                ; Fin de fichier (taille)    
  ; ---------------+---------------------------+-----------------------
  NatureFILE.b     =Nature                     ;  0 Etat du fichier ( 2 = Fichier de longueur Variable )
  RecNumber.l      =NbLigne                    ;  1 Nombre d'enregistrement
  LongRecord.l     =LongTOT                    ;  5 ---- SANS OBJET ICI......
  CreationDate.l   =CreationDate               ;  9 Date de création
  LastAccessDate.l =Date()                     ; 13 Date dernier accès
  ChampDeLaClef.l  =ChampKey                   ; 17 Champs qui contient la clef principale
  TailleBitMap.l   =NbrBitMap                  ; 21 ---- SANS OBJET ICI......
  FlagReserve.s    =Expression$                ; 25 Bloc disponible
  ; ---------------+---------------------------+-----------------------
  FileSeek(NoFile, #File_Nature )              ;    Initialisation pour secteur ZERO !  
  WriteString(NoFile,LSet("_",SizeOf(Record_Zero),"_"))
  EcritZero()

EndProcedure 
Procedure EcritZero()                                   ;
  
  FileSeek(NoFile, #File_Nature )       :WriteByte (NoFile, NatureFILE)
  FileSeek(NoFile, #File_RecNumber)     :WriteLong (NoFile, RecNumber)
  FileSeek(NoFile, #File_LongRecord)    :WriteWord (NoFile, LongRecord)
  FileSeek(NoFile, #File_CreationDate)  :WriteLong (NoFile, CreationDate)
  FileSeek(NoFile, #File_LastAccessDate):WriteLong (NoFile, LastAccessDate)
  FileSeek(NoFile, #File_KeyRecord)     :WriteLong (NoFile, ChampDeLaClef)
  FileSeek(NoFile, #File_BitMap)        :WriteLong (NoFile, TailleBitMap)
  FileSeek(NoFile, #File_Reserve)       :WriteString(NoFile,FlagReserve)
  
EndProcedure  
Procedure.s EcritRecord(NoFile,Position)                ; Ecriture de l'enregistrement à la "position"
  
  FileSeek(NoFile,Position)
  WriteData(NoFile,@blocDATA$, LongTOT); Ecriture sur disque   
  FlushFileBuffers(NoFile)             ; Force l'enregistrement
  NbLigne=NbLigne+1: EcritPremier()    ; Ajoute un ENregistrement secteur Zero...
  
EndProcedure  
; ------------------------------------------------------- 
; - L E C T U R E de l'Enregistrement ZERO              - 
; ------------------------------------------------------- 
Procedure LecturePremier()                              ; Lecture du secteur ZERO...
  ;
  FileSeek(NoFile, #File_Nature )       :NatureFILE     =ReadLong (NoFile)
  FileSeek(NoFile, #File_RecNumber)     :RecNumber      =ReadLong (NoFile)
  FileSeek(NoFile, #File_LongRecord)    :LongRecord     =ReadWord (NoFile)
  FileSeek(NoFile, #File_CreationDate)  :CreationDate   =ReadLong (NoFile)
  FileSeek(NoFile, #File_LastAccessDate):LastAccessDate =ReadLong (NoFile)
  FileSeek(NoFile, #File_KeyRecord)     :ChampDeLaClef  =ReadLong (NoFile)
  FileSeek(NoFile, #File_BitMap)        :TailleBitMap   =ReadLong (NoFile)
  FileSeek(NoFile, #File_Reserve)       :FlagReserve    =Left(ReadString(NoFile),15)
  FileSeek(NoFile, #File_Reserve+15)
  ;  
EndProcedure 
Procedure AfficheDebug()                                ; Affichage du Secteur ZERO...  
  ;                                                     ; 
  Define Event, Base, TxtID, WinID, Item                ;
  Base=20                                               ;
  ; ----------------------------------- Le fenêtre ------------------------
  WinID=OpenWindow(#PB_Any,0,0,350,395,"Secteur Zero",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
	;  
  ; -------------------------------------  Titre --------------------------
  TxtID=TextGadget(#PB_Any,0,10,350,40,"Carnet d'Adresse",#PB_Text_Center) 
  SetGadgetFont(TxtID, FontID1)
  ; ----------------------------------  Les libellés  ---------------------
  Item=Base+1
  EditorGadget(Item,10,55,330,325,#PB_Editor3D_ReadOnly)
  SetGadgetFont(Item, FontID2)
  ;                                                            
  AddGadgetItem(Item,-1,"Début Ecriture : "+Str(SizeOf(Record_Zero)+1))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Nature du Fichier : "+Str(NatureFILE))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Nombre Enregistrement : "+Str(RecNumber))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Longueur Enregistrement : "+Str(LongRecord))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Date Création : "+FormatDate("%dd/%mm/%yy",CreationDate))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Dernier accès : "+FormatDate("%dd/%mm/%yy",LastAccessDate))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Champ de la Clef : "+Str(ChampDeLaClef))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Lignes de la BitMap : "+Str(TailleBitMap))
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Réserve : "+FlagReserve) ; Left(FlagReserve,15)
  AddGadgetItem(Item,-1," ")
  AddGadgetItem(Item,-1,"Fin de fichier : "+Str(FinFichier))
  AddGadgetItem(Item,-1," ")
  ;  
  Repeat
    ;
    Event = WaitWindowEvent()  
  Until Event=#PB_Event_CloseWindow
  CloseWindow(WinID)
  
EndProcedure
; =====================================================
; - Extrait un enregistrement
Procedure.s Get(NoFile, RecNo)                          ; Lecture enregistrement "RecNo"
  
  Position=#Max_Premier+LongTOT*(RecNo-1)               ; ATTENTION : Ici l'enregistrement commence à 0
  blocDATA$=Space(LongTOT)                              ; Donc pour 10 bytes écrit le dernier est à la 
  FileSeek(NoFile,Position)                             ; position 9 (0->9) et le suivant à 10... 
  ReadData(NoFile,@blocDATA$, LongTOT)                  ; 
  conver_Record_EnCHAMP(NbChamp, blocDATA$, Type(), Long(), Champ$())  
  
EndProcedure
; =====================================================
; - Ecrit un enregistrement
Procedure.s Put(NoFile, RecNo)                          ; Ecriture enregistrement "RecNo"      
  ;                                                        Dans un espace existant....   
  blocDATA$=conver_En_DataBLOC(NbChamp, LongTOT, Type(), Long(),Champ$())
  ; Positionne le pointeur ...........; 
  Position=#Max_Premier+LongTOT*(RecNo-1)+1
  If Position+LongTOT>FinFichier                        ; Position hors dimension du fichier
    ProcedureReturn Add(NoFile, blocDATA$)              ; Passe en mode "Ajoute"
  EndIf  
  ProcedureReturn EcritRecord(NoFile,Position)          ; La positioon existe alors écrit
EndProcedure 
; =====================================================
; - Ajoute un enregistrement
Procedure.s Add(NoFile, blocDATA$)                      ; Ajoute un enregistrement
  
  ; Avec Bitmap... Ici on va chercher la position grace à la bitMap ;
  
  Position=Lof(NoFile)
  ProcedureReturn EcritRecord(NoFile,Position)
EndProcedure 
; =====================================================
; - Efface l'enregsitrement courant
Procedure.s Del(NoFile, RecNo)                          ; Efface ""      ""     
  ;
  ; Avec Bitmap... Ici on va mettre le BIT de la position à zéro 
  ;
  Position=#Max_Premier+LongTOT*(RecNo-1)
  blocDATA$=Space(LongTOT):NbLigne=NbLigne-1            ; 
  ProcedureReturn EcritRecord(NoFile,Position)
EndProcedure
; =====================================================
; - Mise à jour de l'enregsitrement courant
Procedure.s Upd(NoFile, RecNo)                         ; Mise a jours actuel     
  Position=#Max_Premier+LongTOT*(RecNo-1):NbLigne=NbLigne-1             
  blocDATA$=conver_En_DataBLOC(NbChamp, LongTOT, Type(), Long(),Champ$())
  ProcedureReturn EcritRecord(NoFile,Position)
EndProcedure
; =====================================================
; - Prend le Suivant 
Procedure.s Nex(NoFile, RecNo)                          ; Passe au Suivant                 
  If RecNo<RecNumber:RecNo+1:EndIf
  ProcedureReturn Get(NoFile, RecNo)
EndProcedure
; =====================================================
; - Prend le Précedent 
Procedure.s Prv(NoFile, RecNo)                          ; Passe au Précédent  
  If RecNo>1:RecNo-1:EndIf
  ProcedureReturn Get(NoFile, RecNo)
EndProcedure
; =====================================================
; - Prend le Dernier
Procedure.s Der(NoFile)                                 ; Passe au Dernier
  RecNo=RecNumber
  ProcedureReturn Get(NoFile, RecNo)
EndProcedure
; =====================================================
; - Prend le Premier
Procedure.s Pre(NoFile)                                 ; Passe au Premier
  RecNo=1
  ProcedureReturn Get(NoFile, RecNo)
EndProcedure
; =====================================================
; - Cherche avec la clef 
Procedure.s Cherche(NoFile, Key$)                       ; Recherche selon la clef 
  
  
  
EndProcedure  
; =====================================================
; - Ferme le fichier courant et son Index... 
Procedure.s CloseRandom(NoFile)               ; Ferme les fichiers        
;                    
; OpenFile(NoFile+1, Rep$+FichierIndex$)      ; Ouvre l'index... 
;   ;
;   For i=1 To NbRecord                   
;     WriteString(NoFile+1,Index(i,1))        ; Ecriture de la clef 
;     WriteLong(NoFile+1,Val(Index.s(i,2)))   ; Ecriture du pointeur
;   Next i  
;   ;
;   CloseFile(NoFile+1)                       ; Ferme l'index
  ;
  CloseFile(NoFile)                           ; Ferme le fichier principal
;  
EndProcedure
; ---------------------------------------------------------------------------------:
; --- 1 Convertion des Champ$() en Record$ ----------------------
Procedure.s conver_En_DataBLOC(NbChamp, LongTOT, Array Type(1), Array Long(1), Array Champ$(1))
  ; -------------------------------------------------------------------------------
  ;      CONVERTIR des Champ$() en un BLOC de longueur FIXE ! 
  ;      CONVERT Fields() in one Fixed lengh dataBLOC
  ; -------------------------------------------------------------------------------
  Protected j, Type
  ; ----------------
  blocDATA$=""  
  For j=1 To NbChamp  
    Type=Type(j)
    Select Type
      Case 0 :Champ$(j)=LSet(Champ$(j),long(j)," ") ; AlphaNumérique 
      Case 1 :Champ$(j)=MKI(Val(Champ$(j)))         ; Entier 
      Case 2 :Champ$(j)=MKL(Val(Champ$(j)))         ; Long 
      Case 3 :Champ$(j)=MKF(ValF(Champ$(j)))        ; Flottant 
      Case 4 :Champ$(j)=MKD(ValD(Champ$(j)))        ; Double     
      Case 5 :Champ$(j)=MKQ(Val(Champ$(j)))         ; Quad 
      Case 6 :Champ$(j)=Champ$(j)                   ; Date forme "jj/mm/aaaa"  
    EndSelect
    blocDATA$+Champ$(j)
  Next j  
  ProcedureReturn blocDATA$  
  
EndProcedure
; ---------------------------------------------------------------------------------:
; --- 2 Convertion du Record$ en Champ$()  ----------------------                  
Procedure.s conver_Record_EnCHAMP(NbChamp, Record$, Array Type(1), Array Long(1), Array Champ$(1))
  ; -------------------------------------------------------------------------------
  ;      CONVERTIR un enregistrement de longueur FIXE et place dans CHAMPS()
  ;      CONVERT Fixed lengh Record$ back in Field()
  ; -------------------------------------------------------------------------------    
  Protected j, Type
  ; ----------------
  For j=1 To NbChamp    
    Champ$(j)=Left(Record$,long(j))         ; Decompose en champs
    Record$=Mid(Record$,long(j)+1)          ; 
    Type=Type(j)                            ; Type de donnée 
    Select Type
      Case 1 :Champ$(j)=Str(CVI(Champ$(j))) ;  Entier < 65536 ou >-32335
      Case 2 :Champ$(j)=Str(CVL(Champ$(j))) ;  Entier - Long
      Case 3 :Champ$(j)=StrF(CVF(Champ$(j)));  Flottant 
      Case 4 :Champ$(j)=StrD(CVD(Champ$(j)));  Double 
      Case 5 :Champ$(j)=Str(CVQ(Champ$(j))) ;  Quad 
      Case 6                                ;  Date forme "jj/mm/aaaa"  
    EndSelect
  Next j  
   
EndProcedure
; -------------------------------------------------------------------------------------:
; - - - fonctions de conversion - - -
Procedure CV_Adapt(*cv, bytes) ;{
	EnableASM
	CompilerIf #PB_Compiler_Unicode
		MOV edx, *cv
		MOV ecx, bytes
		!push ebx
		!inc ecx
		!mov ebx, ecx
		!xor ecx, ecx
		!xor ax, ax
		!cv_adapt_unic_loop:
		!mov ax, [edx + ecx * 2]
		!mov [edx + ecx], al
		!inc ecx
		!cmp ecx, ebx
		!jng cv_adapt_unic_loop
		!pop ebx
	CompilerEndIf
	MOV edx, *cv
	MOV ecx, bytes
	!add edx, ecx
	!mov ax, [edx]
	!cv_adapt_loop:
	!dec edx
	!rcr ax, 2
	!jc cv_adapt_skip
	!btr word [edx], 7
	!cv_adapt_skip:
	!loop cv_adapt_loop
	DisableASM
EndProcedure
Procedure MK_Adapt(*cv, bytes)
	EnableASM
	MOV edx, *cv
	MOV ecx, bytes
	!xor ax, ax
	!mk_adapt_loop:
	!bts word [edx], 7
	!rcl ax, 2
	!inc edx
	!loop mk_adapt_loop
	!or ax, 0x5555
	!mov [edx], ax
	CompilerIf #PB_Compiler_Unicode
		MOV edx, *cv
		MOV ecx, bytes
		!inc ecx
		!xor ax, ax
		!mk_adapt_unic_loop:
		!mov al, [edx + ecx]
		!mov [edx + ecx * 2], ax
		!sub ecx, 1
		!jnc mk_adapt_unic_loop
	CompilerEndIf
	DisableASM
EndProcedure
; ------------------
Procedure.s MKI(i.i)
  I$=Right("0000"+Hex(i),4)
  ProcedureReturn I$
EndProcedure 
Procedure.i CVI(I$) 
  I=Val("$"+I$)
  ProcedureReturn I
EndProcedure  
; ------------------
Procedure.s MKF(f.f)
	Protected cv.CV_MK_Struct\f = f
	MK_Adapt(@cv, 4)
	ProcedureReturn cv\s5
EndProcedure
Procedure.f CVF(s.s)
	Protected cv.CV_MK_Struct\s5 = s
	CV_Adapt(@cv, 4)
	ProcedureReturn cv\f
EndProcedure
; ------------------
Procedure.s MKD(d.d)
	Protected cv.CV_MK_Struct\d = d
	MK_Adapt(@cv, 8)
	ProcedureReturn cv\s10
EndProcedure
Procedure.d CVD(s.s)
	Protected cv.CV_MK_Struct\s10 = s
	CV_Adapt(@cv, 8)
	ProcedureReturn cv\d
EndProcedure
; ------------------
Procedure.s MKL(l.l)
	Protected cv.CV_MK_Struct\l = l
	MK_Adapt(@cv, 4)
	ProcedureReturn cv\s5
EndProcedure
Procedure.l CVL(s.s)
	Protected cv.CV_MK_Struct\s5 = s
	CV_Adapt(@cv, 4)
	ProcedureReturn cv\l
EndProcedure
; ------------------
Procedure.s MKQ(q.q)
	Protected cv.CV_MK_Struct\q = q
	MK_Adapt(@cv, 8)
	ProcedureReturn cv\s10
EndProcedure
Procedure.q CVQ(s.s)
	Protected cv.CV_MK_Struct\s10 = s
	CV_Adapt(@cv, 8)
	ProcedureReturn cv\q
EndProcedure
;}
; --------------------------------------------------------------------
; --- La BITMAP ou carte de représentation de l'occupation DISQUE !   
; --------------------------------------------------------------------
; ENTREE : BitMap$      = Chaine contenant la bit map
;          Fonction     = 1 ou 2 (Ecrit ou supprime, met a 1 ou 0)
;          RecNo        = Position …A supprimer si FONC=2 met a 0
;                         
; SORTIE : RecNo        = Position vaccante OU -99 si erreur dans routine
;          BitMap$      = Chaine contenant la bit map modifiée
; =====================================================================






; =====================================================================
; - Procédures Gadget BallooonTools... 
; --------------------------------------------------------
Procedure GadgetBalTip(WindowNumber.l, GadgetNumber.l, Text.s)
  Protected Tooltip.l, Balloon.TOOLINFO
  Tooltip = CreateWindowEx_(0, "ToolTips_Class32", "", #WS_POPUP | #TTS_NOPREFIX | #TTS_BALLOON, 0, 0, 0, 0, WindowID(WindowNumber), 0, GetModuleHandle_(0), 0)
  SendMessage_(Tooltip, #TTM_SETTIPTEXTCOLOR, GetSysColor_(#COLOR_INFOTEXT), 0)
  SendMessage_(Tooltip, #TTM_SETTIPBKCOLOR, GetSysColor_(#COLOR_INFOBK), 0)
  SendMessage_(Tooltip, #TTM_SETMAXTIPWIDTH, 0, 180)
  Balloon\cbSize = SizeOf(TOOLINFO)
  Balloon\uFlags = #TTF_IDISHWND | #TTF_SUBCLASS
  Balloon\hwnd = GadgetID(GadgetNumber)
  Balloon\uId = GadgetID(GadgetNumber)
  Balloon\lpszText = @Text
  SendMessage_(Tooltip, #TTM_ADDTOOL, 0, @Balloon)
  ProcedureReturn Tooltip
EndProcedure  
; ---------------------------------- FIN D'INCLUDE ------------------------------------:
Premier programme de simulation de création : "EcritureDirect.pb"

Code : Tout sélectionner

; **************************************************************************;
; Exemple de GESTION d'un FICHIER à ACCES DIRECT sur DISQUE     Vers.: 1.0  ;
; ---------------+----------------------------------------------------------;
; Auteur         : GeBonet (et merci à Wilbert pour MK...CV.. )             ;
; Mise en oeuvre : 01/11/2011                                               ;
; Dern. Update   : 11/11/2011      *************************                ;
; PureBasic 4.6  :                 *** EcritureDirect.pb ***                ;                                         ; 
; XpPro,Windows 7:                 *************************                ; 
; ************   +----------------------------------------------------------;
;  ATTENTION : A compiler avec UNICODE décoché dans "Options du compilateur"; 
; ************   +----------------------------------------------------------;
; **************************************************************************;
;{ -------+---------------------------------------------------------------------------/
; Le problème pour créer un bloc de donnée de longueur fixe provient du fait de la 
; conversion des valeurs numériques qu'il soit entier ou double prècision et les autres.  
; Il faut qu'ils aient des longueurs fixes. C'est ce que font les procedures crées par
; "wilbert" du forum officiel. A partir de là il "suffit" de composer l'enregistrement 
; en fonction du "Type(i)" et de la longueur octroyé pour chaque donnée. 
; 
; Fichier à ACCES DIRECT de longueur fixe sur DISQUE : 
; ----------------------------------------------------
; C'est simplement une autre forme de possibilité d'accèder au données . 
; 
; Avantages :
; 
; - Sur de très gros fichier, ne pas avoir à charger tout le fichier en mémoire
; - D'accèder à l'enregistrement "N°" directement sans devoir lire les autres... 
; - Pouvoir travailler à plusieurs sur un même fichier en verrouillant l'enregistrement
;   sur lequel on travaille (Mise à jours) et en laissant les autres en libre accès. 
; - Pouvoir mettre à jours n'importe quel enregistrement sans devoir déplacer les autres
;   (c'est une pile de blocDATA$ de même et identique longueur... )
; - Ajouter / Supprimer des enregistrements sans aucun déplacement des autres... 
;   Dans ce cas il est préférable d'avoir une bonne gestion des enregistremets occupés ou 
;   libres via une Bitmap par exemple ou chaque BIT représente l'occupation 1, ou libre 0.
;   Ce type de gestion évite les trous, l'expension inutile du fichier tout en maintenant
;   un accès contrôlé, direct et rapide à n'importe quel enregistrement. 
;
; Inconvénient / Désavantage majeur 
;
; - La longueur fixe de l'enregistrement ! 
; - En conséquence prédetermination obligatoire des longueurs des champs
; - N'existe pas de système de base de conversion pour les valeurs numérique dans PB 
;   tel Que par exemple : MKI, MKL, MKF, MKD, MKQ et CVI, CVL, CVF, CVD, CVQ)
; 
; ---------------------------------------------------------------------
; -   DONNEES UTILES POUR LA GESTION D'UN TEL FICHIER ! 
; ---------------------------------------------------------------------
; -   S T R U C T U R E de l'Enregistrement ZERO (Init Secteur)
; ---------------------------------------------------------------------
; Cet enregistrement doit avoir une structure fixe minimum avec des infos de bases 
; tel que par EXEMPLE : 
;
; ; Structure Record_Zero
; ;                                              Position ;                       Type de fichier  
; ;   NatureFILE.b        ; #File_Check          =  0   ; Type de fichier 
; ;   RecordNumber.l      ; #File_RecNumber      =  1   ; Nombre d'enregistrement
; ;   LongRECORD.l        ; #File_LengRecord     =  5   ; Longueur de l'enregistrement
; ;   CreationDate.l      ; #File_CreationDate   =  9   ; Date de création
; ;   LastAccessDate.l    ; #File_LastAccessDate = 13   ; Date dernier accès
; ;   ChampDeLaClef.l     ; #File_KeyRecord      = 17   ; Champs qui contient la clef d'accès principale
; ;** TailleBitMap.l      ; #File_BitMap         = 21   ; Optionnel si utile.... (nombre d'enregistrement)
; ;   FlagReserve.s{15}   ; #File_Reserve        = 25   ; Chaine de caractères variable mais < que "LongRECORD"
; ; 
; ; EndStructure
; ; Global mon.Record_Zero 
; ---------------------------
; NOTE : Forme qui pourrait s'appliquer à toute forme de fichier voir 
;
; Codes "NatureFILE.b" (premier Byte)
; -----------------------------------
;   0 = Séquentiel 
;   1 = Direct avec enregistrement de longueur FIXE
;   2 = Direct avec enregistrement de longueur VARIABLE 
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; - La longueur ou taille du fichier peut être connue par : File_Size.l =Lof(NoFile)"
; - Et le dernier enregistrement par                        LastRecord.l=File_Size-LengRecord 
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; - L'accès à un enregistrement est donné par : 
;
; ON A  : #Max_Premier=SizeOf(Record_Zero)          ; Taille de l'enregistrement Zéro ! (voir ci-après)
;         #Premier_REC=#Max_Premier+LongueurBitMap+1; Position du premier enregistrement 
;
;      ** Si TailleBitMap existe il faudra ajouter à #Max_Premier + (TailleBitMap x LongRECORD)
;         en effet il faut créer "TailleBitMap" enregsitrements pour constituer la BitMap en sachant
;         que pour chaque Byte on contrôle 8 bit donc 8 enregistrements... 
;         d'ou : 128 bytes = 1024 enregsitrements, 256=>2048, 512=>4096, 1024=>8192 etc... 
;         et si on à plusieurs enregistrement on multiplie par autant. Ainsi par exemple :
;         si nous avons 5 enregsitrements de 1024 = 5120 Bytes cela contrôle 40960 enregistrements
;         et le premier enregistrement commencerais à : Position= LongTOT x (No-1)+ #Premier_REC 
;         avec #Premier_REC = #Premier_REC + (5  x 1024) => #Premier_REC + 5096
;
; SI    : No      = le numéro d'enregistrement 
; ET    : LongTOT = sa Longueur
; ALORS : Position= LongTOT x (No-1)+ #Premier_REC (y inclus s'il y a lieu (TailleBitMap x LongRECORD)) 
;       : d'ou "FileSeek(#File,Position)" permet de lire les "LongTOT" bytes suivants correspondant à 
;       : l'enregistrement "No"
;} 
; 
;{- Attribution du répertoire Rep$ -
Global Rep$                          ; Localisation de l'application                                              
Rep$= GetPathPart(ProgramFilename()) ; Le programme actuel se trouve ICI 
      SetCurrentDirectory(Rep$)		   ; On fixe le répertoire  
;}  
; - - - - - - - - - - - - - - - - - - - - - - - - - - - 
EnableExplicit    
; 
; ------------------------------------------
  XIncludeFile "IncLectureDirect.pbi"
; ------------------------------------------
;   
Nature  = 1 ; Nature du fichier
NoFile  = 1 ; No du Fichier
NoKey   = 1 ; Champ contenant la clef si il y a lieu
NbChamp = 8 ; Nombre de champs 
NbRecord=10 ; Nombre d'enregistrement (en réalité donné par le Secteur ZERO du fichier)
LongTOT = 0 ; Longueur du bloc de donnée ou enregistrement ! 
;
; - Initialisation des paramètres de codage - 
; 
ReDim Type(NbChamp)        ; Tableau des types de données dans le fichier... 
ReDim Long(NbChamp)        ; Tableau des longueur de champs dans le fichier... 
ReDim Champ$(NbChamp)      ; Tableau recevant les données de chaque champs... 
; 
Restore Carnet1 ;{   A Remarquer : que ces données pourraient venir d'un fichier...  
For i=1 To NbChamp   ; Pour chaque champ 
  Read.i Type(i)     ; Lecture du Type
  Read.i Long(i)     ;   "" de la longueur
  LongTOT+Long(i)    ; Cumule dans LongTOT la longueur que devra avoir le bloc de donnée.
Next i;}             ; ou taille de l'enregsitrement dans le fichier a acces DIRECT... 
;
; ================================================================
; - Exemple de Création de données dans le fichier ci-dessous 
;   afin d'être lue par le programme de lecture "LectureDirect.pb" 
;
NomFichier.s="FichierTestX.dat"
OuvreFichier(NoFile, NomFichier.s, LongTOT)
; 
AfficheDebug(); Pendant période de test ... 
; *****************************************************************************
; > ------------   >>>   ICI ECRITURE DES ENREGISTREMENTS <<<< ----------------'
; ==========================================================
; - - PARTIE 1 Enregistrement des Donnée à partir des DATA  
;{ ---------------------------------------------------------
; Partie de création pour tester -- A partir du premier bloc de données 
; 
; Note : Si ce programme est executé plusieurs fois il ajoute à chaque 
;        fois les 10 lignes de data ci-dessous...
; -----------------------------------------
;
  For i=1 To NbRecord                     ; -----------------------------------------------------------
    For j=1 To NbChamp:Read.s Champ$(j)   ; Lecture des données à partir des DATA, normalement à partir 
    Debug Champ$(j):Next j                ; d'une fenêtre de saisie de donnée ou autre.... 
    ;                                       -----------------------------------------------------------
    Debug "--------------------"
    RecNo=i+RecNumber                     ; On ajoute aux enregistrement existant (RecNumber)
    Put(NoFile, RecNo) 
    Debug "Ecrit No : "+Str(i+RecNumber)  ; 
  Next i
  FileSeek(NoFile,DebFichier)             ; Relecture du premier enregistrement ...
  EcritPremier();                         ; pour y écrire le nouvel Etat !!! 
;}
End
; -------------------------------------------------------------------------------------:
;                      10 lignes de DATA pour faire les TESTS
; -------------------------------------------------------------------------------------:
DataSection ;{ 
  ;"          1    ,   2  ,    3   ,  4 ,     5       ,  6 ,       7       ,       8        "
  ; Data.s "Sujet" ,  N1  , "Titre", N2 , "NomFamille", N3 , "Nom Editeur" , "AnnéeCopyright"
  ; -------------------------------------------------------------------------------------------:
  Carnet1:  
  ;{        Type  | Longueur |  Objet 
  Data.i     0    ,   16     ; "Sujet"
  Data.i     1    ,    4     ;  N1             Long 
  Data.i     0    ,   34     ; "Titre"
  Data.i     3    ,    5     ;  N2             Float 
  Data.i     0    ,   34     ; "NomFamille"
  Data.i     4    ,   10     ;  N3             Double 
  Data.i     0    ,   29     ; "Nom Editeur"
  Data.i     6    ,   10     ; "AnnéeCopyright"
  ;}
  ; ---------------------------------------------------------------------------------------- "
  Carnet2:  ; Donnée d'exemple correspondant au descripteur ci-dessus pour éviter l'encodage..
  ;{ 
  Data.s "Histoire","12","Fisionomía histórica de Chile","223.6","Eyzaguirre","31236.17","Editorial universitaria","03/05/1999"
  Data.s "Tourisme","62233","Salvador da Bahia : 100 Colorfotos","-556.9","Richter","218915.152","Alpina-Ceú azul de Copacabana","02/06/2000"
  Data.s "Poésie de france","2","Oeuvres complètes Tome premier","3265.32","Boileau","25322.60","Hachette","12/06/1830"
  Data.s "Vie pratique","128","Manuel scout des arbres","122.125","Vieux Castor","2253.36","Au Lasso (éd. Scoutes)","22/12/1938"
  Data.s "Album enfant","6632","Nouvelles aventures du petit diable Malice, Les","832.86","Scheggia","5523.36","Chagor","11/10/1959"
  Data.s "Enseignement","23","Allemand sans peine, L","122","Chérel","653.47","Assimil","01/01/1960"
  Data.s "Album enfant","692","Album des jeunes 1961, L'","563.85","Collectif","225.33","Sélection du Reader's Digest","18/05/1960"
  Data.s "Religion","6","Sainte Bible, La","854.134","Collectif","875.3","Cerf","22/10/1961"
  Data.s "Essai","18","Présence de Camus","66532.121","Simon","12.41","Renaissance du livre","26/11/1961"
  Data.s "Biographie","956","Napoléon","124.16","Bainville","8965332.22","Librairie générale française","15/08/1965"
  ;}
EndDataSection;}
Deuxième la lecture des données crées par le précedent "LectureDirect.pb"

Code : Tout sélectionner

; **************************************************************************;
; Exemple de GESTION d'un FICHIER à ACCES DIRECT sur DISQUE     Vers.: 1.0  ;
; ---------------+----------------------------------------------------------;
; Auteur         : GeBonet (et merci à Wilbert pour MK...CV.. )             ;
; Mise en oeuvre : 01/11/2011                                               ;
; Dern. Update   : 11/11/2011      ************************                 ;
; PureBasic 4.6  :                 *** LectureDirect.pb ***                 ;
; XpPro,Windows 7:                 ************************                 ; 
; ************   +----------------------------------------------------------;
;  ATTENTION : A compiler avec UNICODE décoché dans "Options du compilateur"; 
; ************   +----------------------------------------------------------;
; **************************************************************************;
;{- Attribution du répertoire Rep$ -
Global Rep$                          ; Localisation de l'application                                              
Rep$= GetPathPart(ProgramFilename()) ; Le programme actuel se trouve ICI 
      SetCurrentDirectory(Rep$)		   ; On fixe le répertoire  
;} 
; - - - - - - - - - - - - - - - - - - - - - - - - - - -      
EnableExplicit      
;
; ------------------------------------------
  XIncludeFile "IncLectureDirect.pbi"
; ------------------------------------------
;   
NoFile  = 1 ; No du Fichier
NoKey   = 1 ; Champ contenant la clef si il y a lieu
NbChamp = 8 ; Nombre de champs 
NbRecord=10 ; Nombre d'enregistrement (en réalité donné par le Secteur ZERO du fichier)
LongTOT = 0 ; Longueur du bloc de donnée ou enregistrement ! 
;
; - Initialisation des paramètres de codage - 
; 
ReDim Type(NbChamp)        ; Tableau des types de données dans le fichier... 
ReDim Long(NbChamp)        ; Tableau des longueur de champs dans le fichier... 
ReDim Champ$(NbChamp)      ; Tableau recevant les données de chaque champs... 
;
; - Exemple de lecture du fichier créer avec "EcritureDirect.pb" 
; 
Restore Carnet1 ;{
For i=1 To NbChamp   ; 
  Read.i Type(i)     ; Lecture du Type
  Read.i Long(i)     ;   "" de la longueur
  LongTOT+Long(i)    ; Cumule dans LongTOT la longueur que devra avoir le bloc de donnée.
Next i;}
;
NomFichier.s="FichierTestX.dat"
OuvreFichier(NoFile, NomFichier.s, LongTOT)
AfficheDebug()      ; Montre l'état du secteur ZERO du fichier 
Debug RecNumber
;
; >>>>>>>>>>>>>>>>>>>>>>>>>>>   ICI LECTURE DES ENREGISTREMENTS <<<<<<<<<<<<<<<<<<<<<<<<'
;
;{  Phase decodage des enregistrement 
Debug "***************************************"
Debug ">   Phase DECODAGE Nomale... "
Debug "***************************************"
;   
If RecNumber>NbRecord:NbRecord=RecNumber:EndIf
;
For No=1 To NbRecord
  ;                             
  RecNo=No:Get(NoFile, RecNo)
  ;
  Debug "N° ENregistrement = "+Str(RecNo)
  Debug ". . . . . . . . .. .. . . . . . ."
  For j=1 To NbChamp
    Debug Str(j)+"- "+Champ$(j)
  Next j  
  Debug " -- -- -- -- -- -- -- -- -- "
  
Next No;}
; ===========================================
;{  Accès Aléatoire aux données du fichier
Debug "================================="
Debug "*--     ACCES ALEATOIRE       --*"
Debug "================================="
;
For No=1 To 7
  RecNo=Random(NbRecord-1)+1
  Get(NoFile, RecNo)
  ;
  Debug "N° ENregistrement = "+Str(RecNo)
  Debug ". . . . . . . . .. .. . . . . . ."
  For j=1 To NbChamp
    Debug Str(j)+"- "+Champ$(j)
  Next j  
  Debug " -- -- -- -- -- -- -- -- -- "
Next No  
Debug "***************** Dernier ******************************************************";}
End
; -------------------------------------------------------------------------------------:
;  - lignes de DATA pour définir le type et la longueur de chaque Champs(i) - 
; -------------------------------------------------------------------------------------:
DataSection ;{ 
  ;"          1    ,   2  ,    3   ,  4 ,     5       ,  6 ,       7       ,       8        "
  ; Data.s "Sujet" ,  N1  , "Titre", N2 , "NomFamille", N3 , "Nom Editeur" , "AnnéeCopyright"
  ; -------------------------------------------------------------------------------------------:
  Carnet1:  
  ;         Type  | Longueur |  Objet 
  Data.i     0    ,   16     ; "Sujet"
  Data.i     1    ,    4     ;  N1             Long 
  Data.i     0    ,   34     ; "Titre"
  Data.i     3    ,    5     ;  N2             Float 
  Data.i     0    ,   34     ; "NomFamille"
  Data.i     4    ,   10     ;  N3             Double 
  Data.i     0    ,   29     ; "Nom Editeur"
  Data.i     6    ,   10     ; "AnnéeCopyright"

EndDataSection;}
; ============================================================================================:
La suite le dernier prochain post...
Merci.
Dernière modification par GeBonet le lun. 28/nov./2011 23:49, modifié 3 fois.
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

Voici la suite ...
Troisième programme : "ExpleGestionDirect.pb"

Code : Tout sélectionner

; **************************************************************************;
; Exemple de GESTION d'un FICHIER à ACCES DIRECT sur DISQUE     Vers.: 1.0  ;
; ---------------+----------------------------------------------------------;
; Auteur         : GeBonet (et merci à Wilbert pour MK...CV.. )             ;
; Mise en oeuvre : 01/11/2011                                               ;
; Dern. Update   : 11/11/2011      *****************************            ;
; PureBasic 4.6  :                 *** ExpleGestionDirect.pb ***            ;                                         ; 
; XpPro,Windows 7:                 *****************************            ;
;                                                                           ;
; ************   +----------------------------------------------------------;
;  ATTENTION : A compiler avec UNICODE décoché dans "Options du compilateur"; 
; ************   +----------------------------------------------------------;
;                                                                           ;
; **************************************************************************;
;{- Attribution du répertoire Rep$ -                                        ;
Global Rep$                          ; Localisation de l'application        ;                                      
Rep$= GetPathPart(ProgramFilename()) ; Le programme actuel se trouve ICI    ;
      SetCurrentDirectory(Rep$)		   ; On fixe le répertoire                ;
;} 
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;  
EnableExplicit 
; 
; ------------------------------------------
  
  XIncludeFile "IncLectureDirect.pbi"       ; Contient les procédures de gestion etc...
  
; ====================================  START =========================================:
Enumeration ;{ Enumération Fenetre
  ;
  #Window_0                       ; Pour la fenêtre ... 
  #StatusBar_0                    ; Status barre    ...
  ;                               ; Les libellés    ...
  #Text0=5                        ; 
  #Text1 : #Text2  : #Text3 : #Text4 : #Text5
  #Text6 : #Text7  : #Text8 : #Text9 : #Text10  
  ;               Les Champs de saisie...
	#String_1 :	#String_2 :	#String_3 :	#String_4 :	#String_5
	#String_6 :	#String_7 :	#String_8 :	#String_9 :	#Editor_1
	;               Les Boutons de contrôle...
	#Button_1 :	#Button_2 :	#Button_3 :	#Button_4 :	#Button_5
	#Button_6 :	#Button_7 :	#Button_8 :	#Button_9
	;
EndEnumeration ;}
; --------------------------------------------------------
; - Global ----
; -------------------------------------------------------- 
Global Event, EvWin, EvGad, EvTyp, EvMenu, Options, Taille
Global nb_gadget, num_gadget, nb_max_gadget
Global ww,wh,hw,lw,nhw,nlw,nx,ny,nh,nl
; --------------------------------------------------------
; - Fonts -----
; --------------------------------------------------------       
Global FontID1: FontID1 = LoadFont(1, "Arial", 22, #PB_Font_Bold)
Global FontID2: FontID2 = LoadFont(2, "Arial", 10)
;
; -------------------------------------------
; - Initialisation des paramètres de codage - 
; -------------------------------------------
Restore Carnet1 ;       ; Récupère les paramètres relatif aux champs de la fenêtre ci-dessus 
Read.i NbChamp          ; Nombre de champs 
; --------------------------------------------------------------------------------------
; Tableaux de base si on utilise les DATAs pour fichier à longueur FIXE :               
; --------------------------------------------------------------------------------------
; Si on travaillait avec plusieurs fichiers ces tableaux pourraient-être :              
;{======>>> Type(NoFile, NbChamp), Long(NoFile, NbChamp) et Champ$(NoFile, NbChamp)     
;
; En sachant que Type(j) ou Type(i,j) contient le type de donnee du Champ$(i) ou Champ$(i,j)
; et que selon le Cas il serait codé ou décodé selon que :
; Type = 0 :Champ$(j)=LSet(Champ$(j),long(j)," ") ; AlphaNumérique 
;        1 :Champ$(j)=MKI(Val(Champ$(j)))         ; Entier 
;        2 :Champ$(j)=MKL(Val(Champ$(j)))         ; Long 
;        3 :Champ$(j)=MKF(ValF(Champ$(j)))        ; Flottant 
;        4 :Champ$(j)=MKD(ValD(Champ$(j)))        ; Double     
;        5 :Champ$(j)=MKQ(Val(Champ$(j)))         ; Quad 
;        6 :Champ$(j)=Champ$(j)                   ; Date forme "jj/mm/aaaa"
;} --------------------------------------------------------------------------------------
ReDim Type(NbChamp)     ; Tableau des types de données dans le fichier... 
ReDim Long(NbChamp)     ; Tableau des longueur de champs dans le fichier... 
ReDim Champ$(NbChamp)   ; Tableau recevant les données de chaque champs... 
;                       ; 
For i=1 To NbChamp      ; Paramètres qui doivent servir à constituer le "dataBLOC$"
  Read.i Type(i)        ; Lecture du Type
  Read.i Long(i)        ;   "" de la longueur
  LongTOT+Long(i)       ; Cumule dans LongTOT la longueur que devra avoir le bloc de donnée.
Next i  ;               ; 
; =====================================================================================:
;   POUR LE FICHIER ADRESSE DE LA FENETRE CI-DESSUS, voici les :                       : 
;                                                                                      :
;   LIGNES de DATAs pour définir le TYPE et la LONGUEUR de chaque Champs(i)            :
; -------------------------------------------------------------------------------------:
DataSection ;{ 
  ; -----------------------------------------------------------------------------------:
  Carnet1:  
  Data.i    10    ;          ; Nombre de champs 
  ; --------------+----------+----------------------
  ;         Type  | Longueur |No+  Objet           ;
  Data.i     0    ,   10     ; 1 "Numéro d'ordre : "
  Data.i     0    ,   25     ; 2 "Nom et Prénom : "
  Data.i     0    ,   30     ; 3 "Adresse Rue/N°: "
  Data.i     2    ,    5     ; 4 "Code Postal : "
  Data.i     0    ,   30     ; 5 "Localité : "
  Data.i     0    ,   20     ; 6 "Pays  : "
  Data.i     0    ,   11     ; 7 "Téléphone Fixe: "
  Data.i     0    ,   11     ; 8 "Telephone GSM : "
  Data.i     0    ,   40     ; 9 "Email principal : "
  Data.i     0    ,   50     ;10 "Commentaire :"

EndDataSection;}
; ************************************************************
; Memorise les paramètres des Gadgets... 
; ------------------------------------------------------------
Procedure sauve_taille_gadget(id_window,nb_max_gadget)
   
  Structure gadget
    id.l
    x.l
    y.l
    l.l
    h.l
  EndStructure
  ; 
  Global Dim gadget.gadget(1)
  nb_gadget=0
  For num_gadget=0 To nb_max_gadget ; Du premier gadget jusque... nb_max_gadget
    If IsGadget(num_gadget)         ; Y a t'il un gadget de ce numéro 
      ;                               Debug num_gadget
      nb_gadget=nb_gadget+1         ; Compte les Gadgets... 
      ReDim gadget.gadget(nb_gadget); Redimensionne a la taille de "Compte"
      gadget(nb_gadget)\id=num_gadget
      gadget(nb_gadget)\x=GadgetX(num_gadget)
      gadget(nb_gadget)\y=GadgetY(num_gadget)
      gadget(nb_gadget)\h=GadgetHeight(num_gadget)
      gadget(nb_gadget)\l=GadgetWidth(num_gadget)
    EndIf
  Next
  gadget(0)\id=nb_gadget              ; Nombre de Gadget
  gadget(0)\h=WindowHeight(id_window) ; Hauteur de la fenêtre
  gadget(0)\l=WindowWidth(id_window)  ; Largeur de la fenêtre
  ;
EndProcedure
Procedure resize_gadget(id_window) ; Redimentionnement
  
  hw=gadget(0)\h
  lw=gadget(0)\l
  nhw=WindowHeight(id_window)
  nlw=WindowWidth(id_window)
  For num_gadget=1 To gadget(0)\id
    ;Debug num_gadget
    If IsGadget(gadget(num_gadget)\id)
      nx=gadget(num_gadget)\x*nlw/lw
      ny=gadget(num_gadget)\y*nhw/hw
      nh=gadget(num_gadget)\h*nhw/hw
      nl=gadget(num_gadget)\l*nlw/lw
      ResizeGadget(gadget(num_gadget)\id,nx,ny,nl,nh)
    EndIf
  Next
   
EndProcedure
; - Procedure de la fenêtre travaillant avec les données 
;   correspondantes avec les Data ci-dessus
Procedure Open_Window_0()   ; Fenetre de travaille pour cet exemple ! 
  ;
  ww=496:wh=385
  Options = #PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget|#PB_Window_SystemMenu|#PB_Window_ScreenCentered
	If OpenWindow(#Window_0,0,0,ww,wh,"Fenetre Adresse TEST",Options)
	  ; - - - - - - - - - - - - - -  - - - - - - - - - - - -
	  If CreateStatusBar(#StatusBar_0, WindowID(#Window_0))
      AddStatusBarField(496/4)
      AddStatusBarField(496/4)
      AddStatusBarField(496/4)
      AddStatusBarField(496/4)
    EndIf
    ; ------------------------------------------  Titre
    TextGadget(#Text0,82,14,340,40,"Carnet d'Adresse",#PB_Text_Center)
    SetGadgetFont(#Text0, FontID1)
    ; ------------------------------------------  Les libellés 
		TextGadget(#Text1 , 20, 63,100,20,"Numéro d'ordre : ")
		TextGadget(#Text2 , 20, 93,100,20,"Nom et Prénom : ")
		TextGadget(#Text3 , 20,123,106,20,"Adresse Rue/N°: ")
		TextGadget(#Text4 , 20,153,100,20,"Code Postal : ")
		TextGadget(#Text5 ,230,153, 75,20,"Localité : ")
		TextGadget(#Text6 , 20,181, 78,20,"Pays  : ")
		TextGadget(#Text7 , 20,216,110,20,"Téléphone Fixe: ")
		TextGadget(#Text8 ,230,217,110,20,"Telephone GSM : ")
		TextGadget(#Text9 , 20,248,110,20,"Email principal : ")
		TextGadget(#Text10, 20,280, 90,20,"Commentaire :")
		;
		For i=6 To 16:SetGadgetFont(i, FontID2):Next i  
		; ------------------------------------------ Champs normaux
		DebutString=#String_1
		StringGadget(#String_1,145, 65, 80,20,"")
		StringGadget(#String_2,145, 95,155,20,"")
		StringGadget(#String_3,145,120,180,20,"")
		StringGadget(#String_4,145,150, 65,20,"")
		StringGadget(#String_5,290,150,160,20,"")
		StringGadget(#String_6,145,180,125,20,"")
		StringGadget(#String_7,145,215, 80,20,"")
		StringGadget(#String_8,340,215, 95,20,"")
		StringGadget(#String_9,145,250,195,20,"")
		; ------------------------------------------  Champs Editeur
    EditorGadget(#Editor_1,145,280,295,40)
    ; ------------------------------------------  Les boutons
    Texte$="Appuyer sur un des bouton c'est faire l'action indiquée par rapport "
		Texte$+"à ce qui est affiché à l'écran ou va affecter la fenêtre. "
		Texte$+"Par exemple : ICI va Créer, Modifier ou Supprimer un enregistrement par "
		Texte$+"ce qu'il se trouve dans la fenetre..."
		; -
    ButtonGadget(#Button_1, 15,340, 32,20,"|<<")
		ButtonGadget(#Button_2, 50,340, 32,20,"<")
		ButtonGadget(#Button_3, 85,340, 62,20,"Nouveau")
		ButtonGadget(#Button_4,150,340, 62,20,"Modifie")
		ButtonGadget(#Button_5,215,340, 62,20,"Supprime")
		ButtonGadget(#Button_6,280,340, 62,20,"Vide Ecran")
		ButtonGadget(#Button_7,345,340, 62,20,"Quitter")
		ButtonGadget(#Button_8,410,340, 32,20,">")
		ButtonGadget(#Button_9,445,340, 32,20,">>|")
		; -
		GadgetBalTip(#Window_0, #Button_1,"Va au premier")
		GadgetBalTip(#Window_0, #Button_3,Texte$)
    GadgetBalTip(#Window_0, #Button_3,Texte$)
    GadgetBalTip(#Window_0, #Button_4,Texte$)
    GadgetBalTip(#Window_0, #Button_5,Texte$)
    GadgetBalTip(#Window_0, #Button_6,Texte$)
    GadgetBalTip(#Window_0, #Button_9,"Va au dernier !")
	EndIf
EndProcedure
; ======================================================================================
; 
; 
; 
; 
;  __________________________________________________________________
; //////////////////////////// START DE BASE \\\\\\\\\\\\\\\\\\\\\\\\\
; -
; -> Appel autre Procedure de départ si utiles... 
; -
NomFichier.s="PremierAdresseTest.dat"         ; Nom du fichier à ouvrir (ou creer)
OuvreFichier(NoFile, NomFichier.s, LongTOT)   ; 
AfficheDebug()                                ; Montre l'état du secteur ZERO du fichier 
Debug RecNumber
; -
; ================================================================================
; Ces procedure ne sont pas dans l'include pour des raisons pratique d'accès     : 
; et dépendent de l'origine ou destinations des données traitée dans le fichier. :
; Ici elle viennent et vont dans une fenêtre, mais pourraient très bien venir de : 
; l'importation/exportation Internet ou autres...                                :
; - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - -:
Procedure AfficheCHAMPS() ; Affiche le contenu des champs                        :
  
  For j=1 To NbChamp    
    Type  =Type(j)    ; Type de donnée 
    Phrase=Trim(Champ$(j))
    k=DebutString+J-1
    Select Type
      Case 1, 2 :Phrase=RSet(Str(Val(Phrase)) ,Long(j)) ;  Entier < 65536 ou >-32335
      Case 3    :Phrase=RSet(Str(ValF(Phrase)),Long(j)) ;  Flottant 2 decimales
      Case 4    :Phrase=RSet(Str(ValD(Phrase)),Long(j)) ;  Double 
      Case 5    :Phrase=RSet(Str(Val(Phrase)),Long(j))  ;  Quad 
      Case 6                                            ;  Date forme "jj/mm/aaaa"  
    EndSelect
    SetGadgetText(k,Phrase)
  Next j  
  
EndProcedure  
Procedure ChargeCHAMPS()  ; Charge le tableau du contenu de la fenetre           :
  
  For j=1 To NbChamp    
    k=DebutString+J-1  
    Champ$(j)= GetGadgetText(k)
  Next j
  
EndProcedure  
Procedure VideCHAMPS()    ; Vide la fenetre                                      :
  For j=1 To NbChamp    
    k=DebutString+J-1
    SetGadgetText(k,""):Champ$(j)=""
  Next j
EndProcedure    
Procedure Verifie()       ; Verifie si tout les champs ont été encodés..         : 
  k=0                     ; Pour valider l'entrée il suffit que len(D1$)>0
  For j=1 To NbChamp    
    k=DebutString+J-1
    If Len(GetGadgetText(k))=0:D1$+"N":Else:D1$+"O":EndIf
  Next j
  If FindString(D1$,"N"):D1$="":EndIf
  ProcedureReturn Len(D1$)  
EndProcedure  
; - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - -: 
; ================================================================================ 
Open_Window_0()
sauve_taille_gadget(#Window_0,50); 50 c'est le nombre de gadget max, comme dans mes programme l'énumeration 
;
;{ Limitation des longueur des champs toujours après avoir activé la fenêtre 
k=0
For i=DebutString To DebutString+8  ; Pour les ID des champs concernés
  NbCar=Long(k+1):k+1               ; k=selecteur de la Long(k) 
  SendMessage_(GadgetID(i),#EM_SETLIMITTEXT,NbCar,0)
Next i  		  
SendMessage_(GadgetID(#Editor_1),#EM_SETLIMITTEXT,Long(NbChamp),0)
;}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :
; Ici si le fichier n'est pas vide alors on affiche le premier !
;
If RecNumber>0:RecNo=1          ;
  Get(NoFile, RecNo): AfficheCHAMPS()
EndIf  
; ------- Boucle de Traitement des autres champs et Boutons de la fenêtre 
Repeat ;{
  ;
  Event = WaitWindowEvent()
  EvWin = EventWindow()
  EvGad = EventGadget()
  EvTyp = EventType()
  EvMenu= EventMenu()
  ;
  Select Event
      
		Case #PB_Event_Menu

		Case #PB_Event_Gadget
		  ;                               ; Ici met le champs avec focus en évidence ...
      If EventType() = #PB_EventType_Focus And GadgetType(EventGadget())=#PB_GadgetType_String
				SendMessage_(GadgetID(EventGadget()),#EM_SETSEL,0,-1) ; Ici met le champs avec focus en évidence ...
			EndIf
			;            
		  Select EvGad 
		    ;          
		    Case #Button_1  ; Premier     ; Se rend au premier enregistrement
		      If RecNo>0:RecNo=1          ; 
		        Get(NoFile, RecNo): AfficheCHAMPS()
		      EndIf  
		      
		    Case #Button_2  ; Precedent   ; Va prendre le 
		      If RecNo>1 :RecNo-1         ; 
		        Get(NoFile, RecNo): AfficheCHAMPS()
		      EndIf                       ; 
		      
        Case #Button_3  ; Nouveau     
          ChargeCHAMPS()              ; Charge le tableau à partir champs fenetre
          Taille=Verifie()            ; Verifie s'il y a une quantité de données raisonables
          If Taille>30                ; Supérieur alors on prend
            RecNo=RecNumber+1         ; Ajoute un enregistrement
            Put(NoFile, RecNo)        ; Ecriture enregistrement "RecNo"      
          Else                        ; Trop faible...
            VideCHAMPS()              ; Vide les champs
          EndIf   
		    Case #Button_4  ; Modifie     ; 
		      ChargeCHAMPS()              ; Charge le tableau à partir champs fenetre
		      Upd(NoFile, RecNo)          ; Met à jours l'enregistrement 
		      
		    Case #Button_5  ; Supprime    ; 
		      Del(NoFile, RecNo)          ; Efface
		      If RecNo+1<=RecNumber       ; Essaye de trouver le suivant
		        RecNo+1:Get(NoFile, RecNo); Si exsiste le prend
		      ElseIf RecNo-1>0
		        RecNo-1:Get(NoFile, RecNo); Sinon prend precedent
		      EndIf  
		      AfficheCHAMPS()             ; Affiche un des deux. 
		      
		    Case #Button_6  ; Annule      ; Nettoye la fenetre mais ne touche 
		      VideCHAMPS()                ; pas à l'enregistrement qui était affiché
		      
		    Case #Button_7  ; Quitte      ; Et Ferme les fichiers        
		      If NbLigne>0:CloseRandom(NoFile)      
		      EndIf: End
		      
		    Case #Button_8  ; Suivant     ; Va prendre le suivant 
		      If RecNo<RecNumber :RecNo+1 ; 
		        Get(NoFile, RecNo): AfficheCHAMPS()
		      EndIf  
		      
		    Case #Button_9  ; Dernier     ; Va chercher le Dernier ...   
		      If RecNo>0:RecNo=RecNumber  ; 
		        Get(NoFile, RecNo): AfficheCHAMPS()
		      EndIf  
		      
		  EndSelect
		  StatusBarText(#StatusBar_0, 0,"> Enreg. Actuel : "+Str(RecNo))
		  StatusBarText(#StatusBar_0, 1,"> Nbr. Enreg. = "+Str(RecNumber))
		  
		Case #PB_Event_SizeWindow         ; Redimensionne la fenêtre proportionellement 
      resize_gadget(0)                ;  -------------------------------------------
    Case #PB_Event_CloseWindow
      If NbLigne>0:CloseRandom(NoFile):EndIf ; Ferme les fichiers        
		  End
    ;  
	EndSelect
ForEver
;}
; -------
End
; ------------- - ---------- - - ---------  FIN -------------------------------
C'est tout :D
A++
Dernière modification par GeBonet le lun. 28/nov./2011 23:46, modifié 1 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Ar-S »

Je n'ai pas le cerveau disponible pour étudier tout cela maintenant mais j'y reviendrai et te remercie, c'est de la crème !
Image
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Kwai chang caine »

C'est tout :D
T'es un drôle toi :lol: :lol:

Waooouuuhh ce code de la mort !!!! 8O
Merci mille fois GEBONET 8)

C'est vrai à l'arrivée dans PB, cette fonction de VB en autres, m'a manqué cruellement :(
Avec le temps...on apprend à s'en passer...comme des retour à la ligne :mrgreen:
Mais bon...c'est cool que quelqu'un essaye de la recréer 8)

Dis donc ... jamais j'aurais cru qu'il faille tout ça pour juste gérer un RANDOM 8O
Passé un temps, je voulais aussi essayer de recréer cette fonction, j'ai bien fait de ne pas me lancer, je serais surement jamais arrivé au bout :oops:
Tu veux dire que VB il se tape tout ce genre de code pour juste gérer un petit fichier de 10 enregistrements ?? :roll:

Si c'est le cas, je doit reconnaitre que quand même ils se sont cassé la "nénette" pour simplifier la vie des utilisateurs.
Déjà j'avais remarqué ça avec les VARIANT et leur charrette de 16 octets, et les SAFEARRAY et leur structure de la "ROME" 8O

En fin de compte...c'est un peu le début d'une base de donnée, le RANDOM, me trompe-je ???? :roll:

J'ai pas compris l'histoire des BITMAPS....car pour moi c'est une image...mais bon ....j'attends la suite ....et peut être comprendrais-je

En tout cas encore merci de tout ce travail GEBONET 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

Kwai chang caine a écrit :C'est tout :D
Ben oui...
Dis donc ... jamais j'aurais cru qu'il faille tout ça pour juste gérer un RANDOM
En fait il faut pas tout ça... Tout ça c'est déjà et surtout pour utiliser un ou des fichiers de ce type. Avec les fonctions "Get", "Put", "Next", "Previous" etc...

PureBasic n'as pas de "OPEN Filename$ FOR RANDOM AS #Buffer LEN=Longueur",
et surtout pas de FIELD #Buffer, 30 as NomPrenom$, 20 AS Rue$, MKI$(CodePostal%)... ETC...
Mais le principe du "premier secteur", que j'utilise ici et explique, il faut aussi le faire avec les fichier RANDOM des langages qui l'utilisent...
Du moins moi, je le faisais. Un peu comme le BOOT secteur... Mais du fichier. Et j'utilise aussi ce principe avec PureBasic en utilisant une "Structure" comme dans ce cas ci et rien que pour le secteur zero.
En fin de compte...c'est un peu le début d'une base de donnée, le RANDOM, me trompe-je ???? :roll:
Oui, exactement et comme tu le dis un début surtout avec son index.
J'ai pas compris l'histoire des BITMAPS....car pour moi c'est une image...mais bon ....j'attends la suite ....et peut être comprendrais-je
C'est pas très compliqué...
Imagine une chaine de 8 caractères qui serait des Bits de 1 ou 0 tel que : "11101001"
Et que "12345678" sont les positions de chaque 1 ou 0 dans cette chaine.
Que les "1" représente les enregistrements occupés et "0" les enregistrements libres.
Alors rien qu'en regardant la chaine je peux voir que le 4ième bit est à zéro et donc que l'enregistrement 4 du fichier sur disque est libre, et c'est donc là que je vais écrire mon enregistrement et bien sur que ma chaine "11101001" deviendra "11111001" car j'aurais positionné le 4ième "bit" de la chaine de 8 à 1 à la place du "0". Dans ce cas, les suivants à écrire serait donc le 6 et 7ième... Après ça plus de place, à moins que d'étendre le fichier et la BitMap.

L'intérêt c'est que si j'ai cette table en mémoire je sais exactement ou écrire sur DISQUE... De plus si je fais cela au niveau binaire alors 1 byte contrôlera 8 enregistrements... 1024 en contrôlera 8192 etc...

A l'inverse, si j'efface un enregistrement... J'ai pas besoin de l'effacer physiquement sur disque. Il suffit de mettre le "Bit" qui représente l'enregistrement à "0"... Avantage, rapidité et possibilité de récupérer l'enregistrement tant que l'on à pas réécrit là ou le "0" indique que c'est libre :wink:

Autre avantage, c'est qu'un fichier arrivé à maturité, ne bouge plus vraiment beaucoup en taille. Et surtout si on récupère les espaces qui ont été effacés. C'est un peux comme le cimetière d'un village avec une population +/- stable, on récupère les concessions une fois libéré. La taille du cimetière ne bouge plus lui. 8)

D'ailleurs, j'ai posté à ce sujet en Aout 2010 à l'adresse :
http://www.purebasic.fr/french/viewtopi ... ap#p117869
Là j'abordais un autre système de gestion, avec un Hasch code perso qui lui accepte les clef en double... (Concurrent du MAP).
C'est d'ailleurs ce système de BitMap que je couplerais avec le système de gestion de fichier ci-dessus et qui sera en fait transparent à l'utilisation. Autrement dit, la gestion se fera de la même manière qu'avec les programmes ci-dessus (ce sera de la popote interne).

Puis la suite sera la possibilité de gérer plusieurs fichiers en simultané, puis... :lol:
Bon, assez pour ce soir.
A++

J'oubliais de répondre à :
Tu veux dire que VB il se tape tout ce genre de code pour juste gérer un petit fichier de 10 enregistrements ?? :roll:
En fait que ce soit 1, 10 ou 100.000 enregistrements il ne faut pas plus de code et heureusement que c'est pas proportionnel 8)
Dernière modification par GeBonet le jeu. 10/nov./2011 10:06, modifié 1 fois.
Fred
Site Admin
Messages : 2805
Inscription : mer. 21/janv./2004 11:03

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Fred »

A noter qu'on peut aussi utiliser les fixed string dans une structure pour avoir des 'records' facilement:

Code : Tout sélectionner

Structure PeopleRecord
  Nom${30} ; Toujours 30 caractères
  Prenom${20} ; Toujours 30 caractères
  Age.l ; Toujours 4 octects
EndStructure

; Puis on peut utiliser WriteData(#File, @People.PeopleRecord, SizeOf(PeopleRecord))
; et ReadData(#File, @People.PeopleRecord, SizeOf(PeopleRecord)) pour le le relire
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

Bonjour,
Fred a écrit :A noter qu'on peut aussi utiliser les fixed string dans une structure pour avoir des 'records' facilement:

Code : Tout sélectionner

Structure PeopleRecord
  Nom${30} ; Toujours 30 caractères
  Prenom${20} ; Toujours 30 caractères
  Age.l ; Toujours 4 octects
EndStructure

; Puis on peut utiliser WriteData(#File, @People.PeopleRecord, SizeOf(PeopleRecord))
; et ReadData(#File, @People.PeopleRecord, SizeOf(PeopleRecord)) pour le le relire
Tout à fait... Et c'est ce que j'utilise pour le premier secteur...
Et WriteData(#File, @dataBLOC$, LongBLOC) et ReadData(#File, @dataBLOC$, LongBLOC) pour les bloc de donnée précédé de FileSeek(#File,Position) :wink:
Mon seul problème c'est que dans ce que je voudrais reproduire , l'utilisateur de mon programme devrais lui pouvoir déterminer sa longueur des champs, la nature des contenus et le tout sans passer par un langage de programmation traditionnel (ce serais un "Générateur de programme" pas générateur de code comme la plupart des RAD, plus près d'Access sans la difficulté du VBA, mais avec un micro langage spécifique, pas plus de 10 instructions et dédié à la gestion).
Autrement dis la seule solution qui fonctionne pour tout, est que tout, absolument tout soit paramétrable, et c'est de passer par des tableaux... Tout en étant que je suis déjà gêné aux entournures avec les tableaux de PB, puisqu'ils imposent par exemple des constantes dans les "For/Next/step"
L'idéal serait de pouvoir créer des structures "variables" :wink: style :

Code : Tout sélectionner

LgNom=30
LgPrenom=15
Structure PeopleRecord(NoFile) 
	Nom${LgNom} ; 
	Prenom${LgPrenom} ;
	Age.l ; Toujours 4 octects 
EndStructure 
Mais bon, c'est pas comme ça... En attendant la longueur fixe crée par :

Code : Tout sélectionner

; ---------------------------------------------------------------------------------:
; --- 1 Convertion des Champ$() en Record$ ----------------------
Procedure.s conver_En_DataBLOC(NbChamp, LongTOT, Array Type(1), Array Long(1), Array Champ$(1))
  ; -------------------------------------------------------------------------------
  ;      CONVERTIR des Champ$() en un BLOC de longueur FIXE ! 
  ;      CONVERT Fields() in one Fixed lengh dataBLOC
  ; -------------------------------------------------------------------------------
  Protected j, Type
  ; ----------------
  blocDATA$=""  
  For j=1 To NbChamp  
    Type=Type(j)
    Select Type
      Case 0 :Champ$(j)=LSet(Champ$(j),long(j)," ") ; AlphaNumérique 
      Case 1 :Champ$(j)=MKI(Val(Champ$(j)))         ; Entier 
      Case 2 :Champ$(j)=MKL(Val(Champ$(j)))         ; Long 
      Case 3 :Champ$(j)=MKF(ValF(Champ$(j)))        ; Flottant 
      Case 4 :Champ$(j)=MKD(ValD(Champ$(j)))        ; Double     
      Case 5 :Champ$(j)=MKQ(Val(Champ$(j)))         ; Quad 
      Case 6 :Champ$(j)=Champ$(j)                   ; Date forme "jj/mm/aaaa"  
    EndSelect
    blocDATA$+Champ$(j)
  Next j  
  ProcedureReturn blocDATA$  
  
EndProcedure
; ---------------------------------------------------------------------------------:
; --- 2 Convertion du Record$ en Champ$()  ----------------------                  
Procedure.s conver_Record_EnCHAMP(NbChamp, Record$, Array Type(1), Array Long(1), Array Champ$(1))
  ; -------------------------------------------------------------------------------
  ;      CONVERTIR un enregistrement de longueur FIXE et place dans CHAMPS()
  ;      CONVERT Fixed lengh Record$ back in Field()
  ; -------------------------------------------------------------------------------    
  Protected j, Type
  ; ----------------
  For j=1 To NbChamp    
    Champ$(j)=Left(Record$,long(j))         ; Decompose en champs
    Record$=Mid(Record$,long(j)+1)          ; 
    Type=Type(j)                            ; Type de donnée 
    Select Type
      Case 1 :Champ$(j)=Str(CVI(Champ$(j))) ;  Entier < 65536 ou >-32335
      Case 2 :Champ$(j)=Str(CVL(Champ$(j))) ;  Entier - Long
      Case 3 :Champ$(j)=StrF(CVF(Champ$(j)));  Flottant 
      Case 4 :Champ$(j)=StrD(CVD(Champ$(j)));  Double 
      Case 5 :Champ$(j)=Str(CVQ(Champ$(j))) ;  Quad 
      Case 6                                ;  Date forme "jj/mm/aaaa"  
    EndSelect
  Next j  
   
EndProcedure
Me convient très bien. Maintenant, il à très longtemps que je n'ai plus la science infuse...
D'ailleurs ce problème de fichier à accès direct je l'ai évoqué dans la rubrique "Request and WishLists"
http://www.purebasic.fr/english/viewtop ... ndom+Acces
En tout cas merci.
A++
Note: EN fait il s'agit d'un Soft que j'ai réalisé et commercialisé il y a + de 20 ans que je voudrais transposer sous Windows, et pour bien faire avec PureBasic au lieu de PDS 7.1 de Microsoft à l'époque pour la dernière version... Maintenant il faut savoir aussi que j'ai perdu quelque neurones dans l'arrêt de développement de 1996-97 jusque 2008 moment ou je suis revenus et rencontré PureBasic... :wink:
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Kwai chang caine »

En fait il faut pas tout ça... Tout ça c'est déjà et surtout pour utiliser un ou des fichiers de ce type. Avec les fonctions "Get", "Put", "Next", "Previous" etc...
Oui oui...c'est ce que je voulais dire...et ben, y doit y'en avoir des pages de codes dans VB6 :roll:
A l'inverse, si j'efface un enregistrement... J'ai pas besoin de l'effacer physiquement sur disque. Il suffit de mettre le "Bit" qui représente l'enregistrement à "0"... Avantage, rapidité et possibilité de récupérer l'enregistrement tant que l'on à pas réécrit là ou le "0" indique que c'est libre
Compris...c'est un peu comme tu l'as déjà dit, le fonctionnement de la FAT d'un DD :D
C'est cool, c'est vrai pourquoi, essayer de l'effacer, puisque n'importe comment l'espace lui a été attribué par des FIELD :roll:
Dans ce cas, les suivants à écrire serait donc le 6 et 7ième... Après ça plus de place, à moins que d'étendre le fichier et la BitMap.
Ok, alors les BITMAP rien a voir avec les images, quel bouffon ce KCC :lol:
Peut être en fait en traduisant, une CARTE de BIT ?? :roll:

On se demande pourquoi le format des images BMP à pris ce nom ??? :roll:
Et en plus BITMAP ça veut aussi dire le style de gestion d'un dessin..BITMAP ou VECTORIEL 8O

Bon j’espère que y'a plus de place pour ce mot....bientôt ça pourrait devenir aussi le nom d'un chien :lol: :lol:
Pourquoi pas celui du chien le plus moche du monde qui viens de mourir en pleine gloire le pauvre, à 17 ans :(

Image

En tout cas merci de toutes ces explications GEBONET 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Ar-S »

La photo montre le chien mais ils ont oublié de dire que là il est mort depuis 17 ans :lol: :lol: :lol:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Fichier a Acces Direct (Ramdom Access File)

Message par Kwai chang caine »

:lol: :lol: :lol: :lol: :lol:
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Fichier a Acces Direct (Ramdom Access File)

Message par falsam »

Mon commentaire de Noob Inside : Pourquoi ne pas utiliser SQLite en natif dans PB ?
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Re: Fichier a Acces Direct (Ramdom Access File)

Message par flaith »

Sympa GeBonet :D
J'entrevoie la possibilité de faire une lib permettant de lire des fichier type DBase et autres...
Pourquoi ? Dans beaucoup d'entreprises, il existe des bases toujours sous cet ancien format, une petite lib permettant de les lire et de les convertir en SQLite permettra de pérenniser ces anciennes bases avec une nouvelle mouture, programmé sous Purebasic évidement :wink:
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

flaith a écrit :J'entrevoie la possibilité de faire une lib permettant de lire des fichier type DBase et autres...
Pourquoi ? Dans beaucoup d'entreprises, il existe des bases toujours sous cet ancien format, une petite lib permettant de les lire et de les convertir en SQLite permettra de pérenniser ces anciennes bases avec une nouvelle mouture, programmé sous Purebasic évidement :wink:
En fait, non seulement c'est possible, mais je l'ai fait pour DB et cela existe donc aussi sous le doux nom de "CONVDBSE" depuis au moins 1988... Il "suffit" de l'adapter à PB, ce que je peux si cela peux aider ?
En fait dans DBase III et III+ c'est aussi l'entête du fichier qui est structuré d'une certaine manière puisqu'il contient à la fois les titres des champs mais aussi les type etc. Si je me rappelle bien. Quand aux données elles sont des enregistrements de longueur fixe à accès direct... et viennent directement après ce Bloc d'entête qui est très variable puisque cela dépend du nombre de champs qu'il traite! Et une des difficultés était justement là.
Maintenant cela m'intéresserait d'avoir un fichier DBase pour faire les test de récupération... Moi, je n'en ai plus. Ou il faudrait que je recherche beaucoup sans savoir si je trouverais. :wink:
Voilà, voilà !
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

Bonjour,
falsam a écrit :Mon commentaire de Noob Inside : Pourquoi ne pas utiliser SQLite en natif dans PB ?
Oui, bien sur que c'est une solution... Mais c'est une solution qui bien qu'étant dans le domaine publique resterais attaché aux concepteurs pour son évolution, du moins ce n'est que mon avis.
D’où a ce sujet, je crois que ce serais mieux qu'en interne, PureBasic dispose d'un système d'accès direct en natif tout a fait "PureBasic". Ce ne sont que quelques instructions comme dans presque tout les Basics (De Gwbasic, QB, à GFAbasic jusqu'aux plus actuels, FreeBasic, PowerBasic et Realbasic etc.). A cela Ajouter un bon ISAM là peut-être un peu plus complexe. Et le voilà, complétement prêt à attaquer certains domaines (marché) plus facilement sans devoir dépendre de l'évolution des autres...
Et ce n'est pas pour cela qu'il faudrait abandonner, les SQlite, MySql etc... Bien au contraire. Mais cela le rendrait vraiment et tout a fait indépendant dans sa gestion de fichier, les autres apportant un plus et des ouvertures possibles comme cela le fait maintenant, mais pas obligatoire.
Mais bien entendu ce n'est qu'un avis... :wink:
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Fichier a Acces Direct (Ramdom Access File)

Message par GeBonet »

J'ai retrouvé quelques fichiers DBASE... Et voici vite fait une manière de récupérer les données à partir de Pure Basic...
A Adapter !!!

Code : Tout sélectionner

; -------------------------------
; Decodage de fichiers DBF !!! 
; ------------------------------- 
;{- Attribution du répertoire Rep$ -
Global Rep$                          ; Localisation de l'application                                              
Rep$= GetPathPart(ProgramFilename()) ; Le programme actuel se trouve ICI 
      SetCurrentDirectory(Rep$)		   ; On fixe le répertoire  
;} 
;
Enumeration
  #B1
EndEnumeration
#Debut_Descripteur=32     ; Taille Secteur 0
Structure BufferDBS
  N1.c      ;0
  AA.c      ;1
  MM.c      ;2
  JJ.c      ;3
  NE.w      ;4
  NE2.w     ;6
  LG.w      ;8
  LG2.w     ;10
EndStructure
; 
; Tableau pour paramètres... Simplement a redimensionner si utile ! 
Dim EG$(200)
Dim EN$(200)
Dim EN1$(200)
Dim TP$(200)
Dim PR(200)
Dim NC(320)
; 
MOPA$=Chr(0)+Chr(73)
; 
LonBuf=SizeOf(BufferDBS):     
NOMFICH$="VOYAGES"              ; Nom du fichier avec Extension DBF... 

OpenFile(#B1,NOMFICH$+".DBF")    ; 
FileSeek(#B1,0)                  ; Positionne en debut de fichier 
;                                ; ---------------------------------------
N1    =ReadAsciiCharacter(#B1)   ; NOMBRE 1 
AA    =ReadAsciiCharacter(#B1)   ; MOIS DE MISE A JOURS
MM    =ReadAsciiCharacter(#B1)   ; ANNEE DE MISE A JOURS
JJ    =ReadAsciiCharacter(#B1)   ; JOUR DE MISE A JOURS
NE    =ReadWord(#B1)             ; NOMBRE D'ENREGISTREMENT
NE2   =ReadWord(#B1)             ; NOMBRE D'ENREGISTREMENT
LG    =ReadWord(#B1)             ; LONGUEUR DE LA DESCRIPTION
LG2   =ReadWord(#B1)             ; LONGUEUR DE L'ENREGISTREMENT
; ------------------------------
Debug "-----------------------------------------------------------------------------"
;                       123456789012345678901234567890123456   3 Espace par caractères ??? 
Debug "> PREMIER NOMBRE                                      : "+Str(N1)
Debug "> DERNIERE DATE DE MISE A JOURS      : "+Str(JJ)+"/"+Str(MM)+"/"+Str(AA)
Debug "> NOMBRE D'ENREGISTREMENT               : "+Str(NE+NE2)
Debug "> LONGUEUR DES DESCRIPTEURS         : "+Str(LG)
Debug "> LONGUEUR DES ENREGISTREMENTS : "+Str(LG2)
NV1  =Int((LG-1)/32)-1
Debug "> NOMBRE DE VARIABLES                            : "+Str(NV1)
;        
; =======================================================
; Decodage et affichage des champs et paramètres associés.
; =======================================================
;
If NE+NE2>200
   ReDim EN$(NE+NE2+100)
   ReDim EG$(NE+NE2+100)
EndIf  
; -----------------------------------------------------
NCar  =32         ; Buffer de dépard
Ndecal=0          ; Decallage à 0
For i=1 To NV1    ; Pour tout les champs on récupère les entêtes et taille des champs.
  EN$=Space(NCar) ; ------------------------------------------------------------------
  FileSeek(#B1,#Debut_Descripteur+Ndecal)   ; Positionne le pointeur avec decallage "NCar"    
  ReadData(#B1, @EN$,NCar);                 ; 
  FileSeek(#B1,#Debut_Descripteur+Ndecal+11); 
  TP$=Chr(ReadCharacter(#B1))               ; ">> Type de donnée          : "+TP$
  FileSeek(#B1,#Debut_Descripteur+Ndecal+12); 
  PR.w=ReadWord(#B1)                        ; ">> Enregistrement ici      : "+Str(PR)
  FileSeek(#B1,#Debut_Descripteur+Ndecal+16); 
  NC=ReadAsciiCharacter(#B1)                ; ">> Carcactère du champ : "+Str(NC)
  ;                                         ; 
  EG$(I)=EN$:TP$(I)=TP$:PR(i)=PR:NC(i)=NC   ; Création des tables de paramètres 
  Ndecal+NCar                               ; Incrémente le décallage .... 
  ;                                         ; 
Next i  
Debug "-------------------------------------------------------------------------------------"
Debug "No.. - Entete colonne * Type * Precent * Nombre caractères"
Debug "-----  ------------------------   ------   ----------   -------------------------------"
For i=1 To NV1
  Debug Str(i)+"- "+Left(EG$(i)+"###########################",15)+"   :   "+TP$(i)+"   :   "+Str(PR(i))+"   :   "+Str(NC(i))
Next i  
;
Debug "-----------------------------------------------------------------------------"
Debut_Donnee=LG+1 ; Début de lecture des données du fichier 
Position    =NE   ;   
Ndecal      =0

;-  -  -  - -  -  -  - -  -  -  - -  -  -  -
;-  Decode et extrait les enregistrements  -
;-  -  -  - -  -  -  - -  -  -  - -  -  -  -
For i=1 To NE
  ;
  Enregistrement$=Space(LG2)
  FileSeek(#B1,Debut_Donnee+Ndecal)
  ReadData(#B1, @Enregistrement$,LG2):Ndecal+LG2
  EN$(i)=Enregistrement$
  Debug RSet(Str(i),2,"0")+" : "+Enregistrement$+" ==> "+Str(Len(Enregistrement$))
  Enreg$=EN$(i):
  Debug "----------------"
  For j=1 To NV1
    En1$(j)=Left(Enreg$,NC(j)):Enreg$=Mid(Enreg$,NC(j)+1)
    If TP$(j)="D" 
      DAT$=Mid(En1$(j),7,2)+"/"+Mid(En1$(j),5,2)+"/"+Left(En1$(j),4):En1$(j)=DAT$
    EndIf
    Debug Str(Nc(j))+" :"+En1$(j)
  Next j  
  Debug "----------------"
Next i
; -- - --
CloseFile(#B1)
; -- - --
Voilà, voilà... :P
Répondre