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

Partagez votre expérience de PureBasic avec les autres utilisateurs.
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 »

Merci pour le code Gebonet, juste une maj, le nombre d'enregistrement est codé sur 4 octets, donc tu peux utiliser un ReadLong pour la var "NE", plus pratique, la petite modif dans ton code :

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.l      ;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$="CodesPostaux"              ; 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    =ReadLong(#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)
; -- - --
:wink:

Les structures des fichiers DBase : http://ulisse.elettra.trieste.it/servic ... struct.htm
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 »

Bien vus...
En fait je n'ai pas trop travaillé... Je n'ai fait qu'adapter un de mes vieux travaux.... :wink:
Et merci aussi pour le lien :D
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) + .DBF

Message par GeBonet »

Bonjour,

Voilà une version plus compléte de la récupération d'un fichier DBASE III + , IV.
Sous cette forme, il faut évidement que le(s) fichier(s) soient dans le répertoire de l'application... :!:

De même les explications des structures des fichiers dBase, fournit à l'adresse donnée par flaith dans le post page précédente.

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;{
  #Windows
  #menu_Ouvrir
  #menu_Quitter
  #menu_Infos
  #Liste
  
  #B1
EndEnumeration ;}     

Structure BufferDBS
  N1.c      ;0    03h Fichier Dbase III+ Valide sans memo .DBT file; 83h Avec memo (.DBT).
  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... 
;
Dim EG$(200)
Dim EN$(200)
Dim EN1$(200)
Dim TP$(200)
Dim PR(200)
Dim NC(320)
; 
Declare AfficheInfos(N1,AA,MM,JJ,NE,LG,LG2,NV1)
;
LonBuf=SizeOf(BufferDBS)
;
; NOM des fichiers DBF Disponibles. 
; ---------------------------------
;  NOMFICH$="CLIENTS"
   NOMFICH$="CADRE"
;  NOMFICH$="HISTO"
;  NOMFICH$="RAPPORT"
;  NOMFICH$="VOYAGES"
;  NOMFICH$="ARCHI901"
;
RECOMMENCE:
;
NOMFICH$=InputRequester("Ouvrir un fichier DBASE","> Selection du fichier .DBF ","CADRE")
;
OpenFile(#B1,NOMFICH$+".DBF")   ; ---------------------------------------
FileSeek(#B1,0)                 ; Positionne en debut de fichier 
;                               ; ---------------------------------------
N1   =ReadAsciiCharacter(#B1)   ; NOMBRE 3 ou 83h            ; Indique si il y a mémo ou non (Ouvrir .DBT)
AA   =ReadAsciiCharacter(#B1)   ; MOIS  DE MISE A JOURS      ; Byte de  1 de 3
MM   =ReadAsciiCharacter(#B1)   ; ANNEE DE MISE A JOURS      ; Byte de  2 de 3
JJ   =ReadAsciiCharacter(#B1)   ; JOUR  DE MISE A JOURS      ; Byte de  3 de 3
NE   =ReadLong(#B1)             ; Nombre D'Enregistrement    ; Byte de  4 à 7 (Long)
LG   =ReadWord(#B1)             ; Nombre de Byte pour Entete ; Byte de  8 à 9 
LG2  =ReadWord(#B1)             ; Longueur d'ENREGISTREMENT  ; Byte de 10 à 11  
NV1  =Int((LG-1)/32)-1          ; Nombre de champs dans l'entête... 
; ------------------------------; ---------------------------------------
;  -- DBase File Structure --   ;
; ------------------------------; ---------------------------------------
; Sometimes it is necessary To delve into a dBASE table outside the control of the Borland Database 
; Engine (BDE). For instance, If the .DBT file (that contains memo Data) For a given table is 
; irretrievably lost, the file will Not be usable because the byte in the file header indicates 
; that there should be a corresponding memo file. This necessitates toggling this byte To indicate 
; no such accompanying memo file. Or, you may just want To write your own Data access routine. 
; Below are the file structures For dBASE table files. Represented are the file structures As used For 
; various versions of dBASE: dBASE III PLUS 1.1, dBASE IV 2.0, dBASE 5.0 For DOS, And dBASE 5.0 For Windows. 
; 
; Parfois il est nécessaire de se plonger dans fichier dBASE sans être sous DBASE (hors BDE) de Borland.
; Par exemple, si le fichier ".DBT" (qui contient des données mémo) pour une table donnée est irrémédiablement
; perdu, le fichier ne sera pas utilisable car le byte dans l'entête du fichier indique qu'il devrait y avoir
; un fichier mémo correspondant. Cela nécessite de basculer cet octet pour indiquer aucun fichier qu'il n'y a
; mémo d'accompagnement. Ou, vous pouvez juste vouloir écrire votre propre routine d'accès aux données. 
; Voici les structures des tables des fichiers dBASE. Ceux représenté ici, sont les structures des fichiers 
; utilisés par les différentes versions de dBASE, soit : dBase III Plus 1.1, dBASE IV 2.0 et 5.0 et en version 
; pour DOS et dBASE 5,0 pour Window.
;
; The table file header: 
; ---------------------------
; Byte  +Contents+Description  
;       |        |            
;  0    | 1 byte |Valid dBASE III PLUS table file (03h without a memo .DBT file; 83h with a memo).  
;  1- 3 | 3 bytes|Dernière mise a jours ; dans le format YYMMDD format.  
;  4- 7  32-bit   nombre d'enregistrement dans la table.  
;  8- 9  16-bit   nombre de bytes dans toute l'entête (32+les champs et descripteurs)
; 10-11  16-bit   Taille d'un enregistrement (Nbr de Bytes).  
; 12-14   3 bytes Bytes de Reserve.  
; 15-27  13 bytes Reserve pour dBASE III PLUS en réseau.  
; 28-31   4 bytes Bytes de reserve.  
; 32- n  32 bytes début des les champs et descripteurs, la structure de cette table voir ci-après)  
; n+1     1 byte  0Dh Placé comme caractère de fin de champs.
; 
; n above is the last byte in the field descriptor Array. The size of the Array depends 
; on the number of fields in the table file. 
;
; 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)

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  
; 
; Table Field Descriptor Bytes 
; ----------------------------
; Byte  Contents  Description 
; ----------------------------
;  0-10  11       bytes   Field name in ASCII (zero-filled).  
; 11      1       byte    Field type in ASCII (C, D, L, M, Or N).  
; 12-15   4       bytes   Field Data address (address is set in memory; not useful on disk).  
; 16      1       byte    Field length in binary.  
; 17      1       byte    Field decimal count in binary.  
; 18-19   2       bytes   Reserved For dBASE III PLUS on a LAN.  
; 20      1       byte    Work area ID.  
; 21-22   2       bytes   Reserved For dBASE III PLUS on a LAN.  
; 23      1       byte    SET FIELDS flag.  
; 24-31   1       byte    Reserved bytes.  
;
#Debut_Descripteur=32     ; Taille Secteur 0
; ------------------------------------------
NCar  =32         ; Buffer de dépard ou taille de la structure des champs... 
Ndecal=0          ; Decallage à 0
LG_Fentre=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 et prepare un espace de "NCar"    
  ReadData(#B1, @EN$,NCar);                 ; Pour y lire le nom du champs sur 11 Bytes 
  FileSeek(#B1,#Debut_Descripteur+Ndecal+11); Type de Champ en ASCII 
  TP$=Chr(ReadCharacter(#B1))               ; Type de donnée = (C, D, L, M, Or N): "+TP$
  FileSeek(#B1,#Debut_Descripteur+Ndecal+12); 4 bytes pour ladresse de champs de donnée
  PR.l=ReadLong(#B1)                        ; ">> Enregistrement ici      : "+Str(PR)
  FileSeek(#B1,#Debut_Descripteur+Ndecal+16);  >> 1 byte Field length in binary.  
  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  
; ---------------
;  Table Records 
; ---------------
; The records follow the header in the table file. Data records are preceded by one byte, 
; that is, a Space (20h) If the record is Not deleted, an asterisk (2Ah) If the record is 
; deleted. Fields are packed into records without field separators or record terminators. 
; The End of the file is marked by a single byte, With the End-of-file marker, an OEM code 
; page character value of 26 (1Ah). You can input OEM code page Data As indicated below. 
; ----------
; Les enregistrements suivent la table des entêtes dans le fichier. Enregistrements de données 
; qui sont précédées par un octet, soit un espace (20h) si l'enregistrement n'est pas supprimé, 
; un astérisque (2Ah) si l'enregistrement est supprimé. Les champs de l'enregsitrement sont inclus
; dans ce qui constitue alors un bloc sans séparateurs de champ ni de fin d'enregistrement.
; Seul la fin du fichier est marqué par un octet de fin de fichier, qui est le caractère 26 (1Ah).
; 
; --------------------------------------
;  Allowable Input For dBASE Data Types 
; --------------------------------------
; Data Type  Data Input 
;
; C (Character) All OEM code page characters.  
; D (Date)      Numbers And a character To separate month, day, And Year (stored internally 
;               As 8 digits in YYYYMMDD format).  
; N (Numeric)   - . 0 1 2 3 4 5 6 7 8 9  
; L (Logical)   ? Y y N n T t F f (? when Not initialized).  
; M (Memo)      All OEM code page characters (stored internally As 10 digits representing a .DBT block number).  
; ----------------------------------
;
; Binary, Memo, And OLE Fields And .DBT Files 
; 
; Memo fields store Data in .DBT files consisting of blocks numbered 
; sequentially (0, 1, 2, And so on). The size of these blocks are internally set 
; To 512 bytes. The first block in the .DBT file, block 0, is the .DBT file header. 
; Memo field of each record in the .DBF file contains the number of the block (in OEM 
; code page values) where the field's data actually begins. If a field contains no data, 
; the .DBF file contains blanks (20h) rather than a number. 
;
; When Data is changed in a field, the block numbers may also change And the number in 
; the .DBF may be changed To reflect the new location. 
;
; This information is from the Using dBASE III PLUS manual, Appendix C. 
; ----------
; Les données du champs Mémo sont rangées dans le fichier ".DBT" constitués de blocs numérotés 
; séquentiellement (0, 1, 2, et ainsi de suite). La taille de ces blocs sont en interne définie
; à 512 octets. Le premier bloc dans le fichier ".DBT", le bloc 0, est l'entête du fichier.
; Chaque Champ Mémo de l'enregistrement du fichier ".DBF" contient le numéro du bloc (en valeurs page 
; de code OEM) où les données du champ commence réellement dans le ".DBT". Si un champ ne contient pas
; de données, le fichier ".DBF" contient des blancs (20h), plutôt que d'un nombre.
;
; Lorsque les données sont modifiées dans un champ, les numéros de blocs peuvent aussi changer Et le 
; nombre dans la DBF. Peut être modifié pour refléter le nouvel emplacement.
;
; Ces informations sont tirées du manuel utilisateur dBASE III PLUS, l'annexe C.
; 
; ---------------------------------------------------------------------
;  Affichage ..... 
; ==============================================================
  Debut_Donnee=LG+1 ; Début de lecture des données du fichier 
  Position    =NE   ;   
  Ndecal      =0    ;
  ; ----------------;---------------
  If LG<300:w_main_width = 600 ; Etablit un minimum... 
  Else:w_main_width =LG*2:EndIf
  w_main_height = 590
  ValOptions | #PB_Window_ScreenCentered|#PB_Window_SystemMenu ;|#PB_Window_SizeGadget
  w_main_nr = OpenWindow(#PB_Any,0,0,w_main_width,w_main_height,"Lecture de "+nomFichier$,ValOptions);}
  ;{ ---------------------- Menu Barre ----------------------------------------------------
  If CreateMenu(0,WindowID(w_main_nr))   ;   Le Menu
    MenuTitle("Fichier")
      MenuItem(#menu_Ouvrir,"Ouvrir")
      MenuItem(#menu_Quitter,"Quitter")
    MenuTitle("Aides/Infos")
      MenuItem(#menu_Infos,"Informations")
  EndIf
  ; ---------------------- Status Barre ----------------------------------------------------
  Lgww=ww/3-10  
  CreateStatusBar(0,WindowID(w_main_nr))
    AddStatusBarField(150)
    AddStatusBarField(200)
    AddStatusBarField(#PB_Ignore)
    ; -------------------------------------------------------------------------
    Statu01$=" Nombre de Champs : "+Str(NV1)+".."
    Statu02$=" Nombre d'enregistrements : "+Str(NE)+".."
    StatusBarText(0, 0, Statu01$)
    StatusBarText(0, 1, Statu02$)
    Aff$="Taille fenetre X="+Str(WindowWidth(w_main_nr))+" Y="+Str(WindowHeight(w_main_nr))
    StatusBarText(0, 2, Aff$) 
  ;}
  ; -------------------------- La grille des données ------------------------------------
  ;{         PART 1   <<< ENTETE >>>
  For j=1 To NV1                          ; Première Ligne et première colonne... ENTETE
    LgCol=NC(J)*6:If LgCol<LgColP:LgCol=LgColP:Else:LgColP=LgCol:EndIf
    If J=1
      Caract=0
      Caract | #PB_ListIcon_GridLines | #PB_ListView_ClickSelect                              
      Caract | #PB_ListIcon_FullRowSelect | #PB_ListIcon_FullRowSelect
      Caract | #PB_ListIcon_AlwaysShowSelection
      Mot$=EG$(j); "Colonne "+Str(j)
      list_nr = ListIconGadget(#PB_Any,5,5,w_main_width-10,w_main_height-50, Mot$+":",LgCol ,Caract) 
    Else
      Mot$=EG$(j):; "Colonne "+Str(j)
      AddGadgetColumn(list_nr, j ,Mot$+":",LgCol) ; 150) ;
    EndIf
    
  Next j;}
  ; -  -  -  - -  -  -  - -  -  -  - -  -  -  -
  ; -  Decode et extrait les enregistrements  -
  ;{-  -  -  - -  -  -  - -  -  -  - -  -  -  -
  For i=1 To NE
    Enregistrement$=Space(LG2)
    FileSeek(#B1,Debut_Donnee+Ndecal)
    ReadData(#B1, @Enregistrement$,LG2):Ndecal+LG2
    Enreg$=Enregistrement$: En1$=""
    For j=1 To NV1
      En1$+Left(Enreg$,NC(j)):If j<NV1:En1$+Chr(10):EndIf
      Enreg$=Mid(Enreg$,NC(j)+1)
      If TP$(j)="D"           ; Type Date ...
        DAT$=Mid(En1$,7,2)+"/"+Mid(En1$,5,2)+"/"+Left(En1$,4):En1$+DAT$
      ElseIf TP$(j)="N"       ; Type numérique 
        RSet(En1$,NC(j)," ")
      ElseIf TP$(j)="M"       ; Type Mémo...
        
      EndIf
    Next j  
    ChaineBloc$=En1$
    AddGadgetItem (list_nr, -1, ChaineBloc$) ;  AJOUT <<<===========
  Next i;}
  ;                                             Attente pour la fenetre affichée.... 
  Repeat
    Event = WaitWindowEvent()
    EvWin = EventWindow()
    EvGad = EventGadget()
    EvTyp = EventType()
    EvMenu= EventMenu()
    ;
    Select Event
        
  		Case #PB_Event_Menu
  		  
  		  Select EvMenu
  		      
  		    Case #menu_Ouvrir     ; "Ouvrir"
  		      CloseFile(#B1)
  		      Goto RECOMMENCE     ; Recommence le programme
  		      
  		    Case #menu_Quitter    ; "Quitter"
  		      Debug "Quitter..."
  		      event =#PB_Event_CloseWindow
  		    Case #menu_Infos      ;"Informations"
  		      Debug "Information ..."
  		      AfficheInfos(N1,AA,MM,JJ,NE,LG,LG2,NV1)
  		  EndSelect
  		  
  		Case #PB_Event_Gadget

  		  Select EvGad 
  		    ;          
;   		    Case #Button_1  ;
;   		    Case #Button_2  ;
;           Case ......._n  ;
;   		    Case #Button_9  ;

  		  EndSelect
;   		  StatusBarText(#StatusBar_0, 0,"> Observation 1= "+Str(0))
;         StatusBarText(#StatusBar_0, 1,"> Observation 1= "+Str(1))
;         StatusBarText(#StatusBar_0, 2,"> Observation 1= "+Str(2))
;         StatusBarText(#StatusBar_0, 3,"> Observation 1= "+Str(3))
      Case #PB_Event_CloseWindow
        Break
        ;  
    EndSelect
  
  Until event =#PB_Event_CloseWindow
; 
; ==============================================================
;
; *********              Forme avec Debug            ***********
;                         (Retirer les Commentaires (;) ) 
; ==============================================================
; Debug "-------------------------------------------------------------------------------------"
; Debug "No.. - Entete colonne * Type * Precent * Nombre caractères"
; Debug "-----  ------------------------   ------   ----------   -------------------------------"
; LG_Fentre=0
; 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)
End
; -- - --
; *************************************************************************************
Procedure AfficheInfos(N1,AA,MM,JJ,NE,LG,LG2,NV1)
  
  #Text_1=101: #Text_2=102:  #Text_3=103
  #Text_4=104: #Text_5=105:  #Text_6=106
  #Window2=110:#StringGad=111
  ;
  If N1=3 : Fichier$="Type DBF":Else:Fichier$="Type DBF + DBT":EndIf
  ValOptions | #PB_Window_ScreenCentered|#PB_Window_SystemMenu
  If OpenWindow(#Window2,0,0,450,200,"Information sur le fichier : "+nomFichier$,ValOptions);
    TextGadget(#Text_1, 20,  20, 340, 20, "> PREMIER NOMBRE (3=DBF, 83h=DBT aussi)")
    TextGadget(#Text_2, 20,  50, 340, 20, "> DERNIERE DATE DE MISE A JOURS  ")
    TextGadget(#Text_3, 20,  80, 340, 20, "> NOMBRE D'ENREGISTREMENT        ")
    TextGadget(#Text_4, 20, 110, 340, 20, "> LONGUEUR DES DESCRIPTEURS      ")
    TextGadget(#Text_5, 20, 140, 340, 20, "> LONGUEUR DES ENREGISTREMENTS   ")
    TextGadget(#Text_6, 20, 170, 340, 20, "> NOMBRE DE CHAMPS               ")
    StringGadget(#StringGad+1,350, 20, 60, 20, Str(N1),#PB_Text_Right)
    StringGadget(#StringGad+2,350, 50, 60, 20, Str(JJ)+"/"+Str(MM)+"/"+Str(AA),#PB_Text_Right)  
    StringGadget(#StringGad+3,350, 80, 60, 20, Str(NE),#PB_Text_Right)  
    StringGadget(#StringGad+4,350,110, 60, 20, Str(LG),#PB_Text_Right)
    StringGadget(#StringGad+5,350,140, 60, 20, Str(LG2),#PB_Text_Right)
    StringGadget(#StringGad+6,350,170, 60, 20, Str(NV1),#PB_Text_Right)
  EndIf
  Repeat 
    Event = WaitWindowEvent()
  Until event =#PB_Event_CloseWindow
  CloseWindow(#Window2)
  
EndProcedure
;
;
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) + .DBF

Message par GeBonet »

Voici un système de gestion d'une BitMap...
Lire les commentaires...

Code : Tout sélectionner

;//////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;  Application des test Binaire à la création d'une "BitMap" de gestion de fichier.
;  
;                                                           GeBonet : Le 15/11/2011 
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////////////////
; =================================================================================== 
;          * < GESTION de BIT MAP > *
; =================================================================================== 
; Objet : Gestion d'une BitMap.  Mais Qu'est-ce qu'une BITMAP dans ce CAS ? 
; ----------------------------------------------------------------------------------- 
; C'est une "carte" représentant sous forme binaire l'occupation ou non d'une position 
; parmi un nombre déterminé d'enregistrement. Où si l'on veut à chaque 1 correspond une 
; position OCCUPÈE et un 0 sera une position LIBRE soit pour 8 enregistrements crée nous
; aurions la carte ="11111111" tandis que "11110111" nous dis que la position 4 est libre
; (les bits se lisent de droite à gauche). 
; 
; Cet exemple de 8 n'est pas anodin. Je l'ai pris pour illustrer le fait que c'est aussi un
; BYTE. D'ou qu'un seul BYTE peut servir pour connaitre l'occupation ou non de 8 enregistrements 
; qu'une carte binaire de 128 bytes permet de contrôler 1024 enregistrement et forcément 1 méga 
; de carte = 8 méga d'enregistrement. 
;
; L'INTERET de ce contrôle ? 
;                            Cela permet de ne pas faire croître un fichier et de réaffecter 
; directement les enregistrements effacés. Cela permet aussi au moment de l'effacement de ne
; supprimer que virtuellement l'enregistrement en mettant sa position dans la Map à 0 sans pour
; autant effacer réellement l'enregistrement. 
;
; Tout en étant que cela va plus vite de mettre à 0 un bit qu'un enregistrement qui ne sera  
; réellement effacé qu'au moment de sa réoccupation par un nouveau. 
; Soit une réelle gestion dynamique d'un fichier a accès direct. 
; 
; Donc le principal intérêt est que sur des fichiers à accès direct et de très grande taille
; cela permet une gestion très rapide des "trous" par réaffectation des espaces vacants sans
; devoir réorganiser quoi que ce soit. 
;
; Il va de soit que si l'on peu y associer la gestion d'un Index pour un travaille avec des 
; clefs pour retrouver les enregsitrements. Clefs auxquels on associerait la position de 
; l'enregistrement dans le fichier. 
; ---------------------------------------------------------------------
; Dès lors l'écriture d'un enregistrement se ferait selon la séquence :
; 
; 1- Recherche d'une place vacante du fichier direct grâce à la BitMap  
; 2- Ecriture des données dans le fichier direct a la position donnée par ma BitMap... 
; 2- Ecriture dans l'index de la clef avec la position des données dans le fichier direct.
;                                
; La lecture c'est l'inverse... : 
;                                
; 1- Grâce à la Clef nous obtenons la position de L'enregistrement
; 2- Avec la position je lirais de L'enregistrement ou qu'il soit dans le fichier direct... 
;                                
; Pour l'effacement : 
;    
; 1- On efface seulement la clef et son pointeur de position dans l'Index
; 2- Puis son BIT représentant sa position dans la BitMap. 
;    
; ----------------------------------------------------------------------------------------
;  Cette Simulation : Comporte 3 Phases ! (+1)
;
;  Mais avant cela nous allons créer une BitMap de 128 bytes avec tout ses bit occupé !  
;  Soit une 128 fois 255. A partir de cela :
;
;  Phase 1 : Nous allons libérer dans la BitMap de manière aléatoire 10 enregistrements 
;            et mettre à ZERO les 10 Bits qui representerons cette position devenue vaccante. 
;            plus retenir les positions libérées. 
;
;  Phase 2 : A partir des position retenue repositionné les enregistrements que l'on a
;            retenus et qui sont à ZERO, les positionner à "UN"... Occupé. 
; 
;  A ces deux phases j'ajouterais ...
;
; Phase TEST Si Bit est présent : Cette procedure permet de vérifier si un bit est 
;            à UN ou à ZERO... Test à inclure si vous le jugez utile. Il ne modifie 
;            en rien l'état du BIT, tester !    
;
; ==================================================================== 
; NOTE : J'utilise des tests Binaire qui ont été montré dans ce forum
;        afin de rester dans la ligne de travaille déjà prsenté et par 
;        extension une manière de les utiliser !
; ==================================================================== 
;
Debug "================================"
Debug "* Attention ICI test Bitmap !!!*"
Debug "================================"
Debug ""
; ----------------------------------
#Premier= 1 << 0 : #Second = 1 << 1
#Troisem= 1 << 2 : #Quatrie= 1 << 3
#Cinquie= 1 << 4 : #Sixieme= 1 << 5
#Septiem= 1 << 6 : #Huitiem= 1 << 7
; ----------------------------------
; Global BMap$
; ----------------------------------
Declare.s MetBitaUn(k, BMap$)
Declare.s RetireBit(k, BMap$)
Declare.s TestBitLibre(k, BMap$)
; ----------------------------------
Declare Gest_BitMap(BMap$, Fonc.c, Position.l)
; 
; ================================================================================
;  Création d'une BitMap virtuelle pour test de 128 bytes ou 1024 enregistrements
; ================================================================================
; Cette partie pour le test...
; 
Dim Retient(10)   ; Pour retenir les bytes choisis dans la Phase 1....

BMap$=""
NbByte=128        ; Taille d'une ligne de BitMap ! 
For i=1 To NbByte ; Ici création d'une BitMap Virtuelle de 128 Bytes pleine... 
  BMap$+Chr(255)  ; Soit l'équivalent de 128 x 8 = 1024 enregistrements
Next i            ; qui seront contrôlé !       
; 
; --------------------------------------------------------------------------------
;  Phase 1 : La BitMap est pleine (tout bit à 1) On RETIRE 10 Bits aléatoirement
; --------------------------------------------------------------------------------
;
For i=1 To 10       ; Ici on va choisir aléatoirement 10 enregistrement à mettre à 0
  ;                 ;               
  k=Random(1024)    : Debug "Enregistre="+Str(K)            :Retient(i)=k
  BMap$=RetireBit(k,BMap$); Va retirer le Bit correspondant à la position "k" (mettre à 0)
  ;                         A-t'il été mis à zéro... On vérifie... 
  OK$=TestBitLibre(k,BMap$):If OK$="0":Reponse$="OUI":Else:Reponse$="NON":EndIf
  Debug "Est-il à 0 => "+Reponse$
  Debug "------------------------"
Next i
; -------------------------------------------------------------------------------- 
; Affichage des enregistrements qui ont été mis à zéro dans la BitMap 
; 
For i=1 To 10 
  Debug "Bit mis à zéro pour l'enregistrement : "+Str(Retient(i))
Next i  
;
; --------------------------------------------------------------------------------
;  Phase 2 : La BitMap contient 10 bit qui on été mis à zéro on les remets à 1
; --------------------------------------------------------------------------------
; 
Debug "========= Remise à Un ============"
Debug ""
For i=1 To 10
  k=Retient(i)                ; Prend l'enregistrement dont le bit à été mis à zéro...
  Debug "Enregistre="+Str(K)  ; 
  BMap$=MetBitaUn(k, BMap$); Mise à un du bit représentant l'enregistrement 'k' dans la BMap$
Next i
a+1
a+1
End
; 
; ====================================================================
Procedure.s MetBitaUn(k, BMap$)   ; Mise à "UN" d'un Bit dans un Byte
  
  ByteConcerne=Int(k/8)+1             : Debug "ByteChoisi="+Str(ByteConcerne)
  Bit         =k-((ByteConcerne-1)*8) : Debug "Bit Choisi="+Str(Bit)
  If Bit=0:ByteConcerne=ByteConcerne-1: Bit=8: EndIf
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;         
  Select Bit ; Test bininaire en fonction du BIT   
    Case 1 : Byte | #Premier : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 2 : Byte | #Second  : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 3 : Byte | #Troisem : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 4 : Byte | #Quatrie : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 5 : Byte | #Cinquie : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 6 : Byte | #Sixieme : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 7 : Byte | #Septiem : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 8 : Byte | #Huitiem : Debug "Positionne le bit "+Str(Bit)+"="+RSet(Bin(Byte),8,"1")
  EndSelect
  Debug "--------------------"
  BMpa$=Left(BMap$,ByteConcerne-1)+Chr(Byte)+Mid(BMap$,ByteConcerne+1)
  ProcedureReturn BMpa$
  
EndProcedure  
;
Procedure.s RetireBit(k, BMap$)   ; Mise à "ZERO" d'un Bit dans un Byte
  
  ByteConcerne=Int(k/8)+1             : Debug "ByteChoisi="+Str(ByteConcerne)
  Bit         =k-((ByteConcerne-1)*8) : Debug "Bit Choisi="+Str(Bit)
  If Bit=0:ByteConcerne=ByteConcerne-1: Bit=8: EndIf
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;         
  Select Bit ; Test bininaire en fonction du BIT   
    Case 1 : Byte & ~(#Premier) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 2 : Byte & ~(#Second)  : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 3 : Byte & ~(#Troisem) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 4 : Byte & ~(#Quatrie) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 5 : Byte & ~(#Cinquie) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 6 : Byte & ~(#Sixieme) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 7 : Byte & ~(#Septiem) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 8 : Byte & ~(#Huitiem) : Debug "Retire le bit "+Str(Bit)+"="+RSet(Bin(Byte),8,"0")
  EndSelect
  Debug "--------------------"
  BMpa$=Left(BMap$,ByteConcerne-1)+Chr(Byte)+Mid(BMap$,ByteConcerne+1)
  ProcedureReturn BMpa$
  
EndProcedure  
; ==============================================="
;  Phase TEST Si Bit est présent                 "
;  Si OUI il rend la position du Bit-1, Sinon =0 "
; -----------------------------------------------"
Procedure.s TestBitLibre(k,BMap$)
  
  Debug " - - - - - - - - - - : "+Str(k)
  ByteConcerne=Int(k/8)+1             : Debug "ByteChoisi="+Str(ByteConcerne)
  Bit         =k-((ByteConcerne-1)*8) : Debug "Bit Choisi="+Str(Bit)
  If Bit=0:ByteConcerne=ByteConcerne-1:Bit=8:EndIf
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;
  Select Bit ; Test bininaire en fonction du BIT   
    Case 1 : Resultat=Byte & #Premier : Debug "Resultat : "+Str(Resultat)
    Case 2 : Resultat=Byte & #Second  : Debug "Resultat : "+Str(Resultat)
    Case 3 : Resultat=Byte & #Troisem : Debug "Resultat : "+Str(Resultat)
    Case 4 : Resultat=Byte & #Quatrie : Debug "Resultat : "+Str(Resultat)
    Case 5 : Resultat=Byte & #Cinquie : Debug "Resultat : "+Str(Resultat)
    Case 6 : Resultat=Byte & #Sixieme : Debug "Resultat : "+Str(Resultat)
    Case 7 : Resultat=Byte & #Septiem : Debug "Resultat : "+Str(Resultat)
    Case 8 : Resultat=Byte & #Huitiem : Debug "Resultat : "+Str(Resultat)
  EndSelect
  Debug " - - - - - - - - - -"
  ProcedureReturn Str(Resultat)
  
EndProcedure
; 
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) et BitMap +

Message par Kwai chang caine »

Et bin...on sent que t'es dans ton domaine de prédilection :wink:
Merci beaucoup pour ces exemples et leurs explications détaillées 8)

Pour avoir un fichier DBASE, si on a pas le giciel, je ne sais pas si ACCESS peut en créer..il me semble que oui, j'ai vu des extensions DB en export :roll:
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) et BitMap +

Message par GeBonet »

Kwai chang caine a écrit :Et bin...on sent que t'es dans ton domaine de prédilection :wink:
Merci beaucoup pour ces exemples et leurs explications détaillées 8)
Ben, j'ai essentiellement fait de la gestion, pour un tas d'entreprise en tout domaines...
Et si je devais faire du contrôle de processus (machine, planche à dessins, ou autre système connecté)
c'était toujours avec des bases de données pour gérer les systèmes. Tout comme le graphique, il était toujours attaché également à une production de résultats de capture de donnée de l'un ou l'autre système connecté ou activer un ou l'autre matériel. Je n'ai jamais fait de jeux excepté l'un ou l'autre truc qui serais considéré aujourd'hui comme ringard. Bien que je considère ceux qui s'y attèle comme de très bon développeurs...
Pour avoir un fichier DBASE, si on a pas le giciel, je ne sais pas si ACCESS peut en créer..il me semble que oui, j'ai vu des extensions DB en export :roll:
Je ne sais pas trop, je sais que Excell lis très bien les DBF, je suppose ACCESS Aussi, mais si tu as besoin d'un ou deux fichiers DBF, je peux te les passer.
Mais c'est surtout pour répondre à "Flaith" et les autres qui aurait chez eux ou dans leurs boite des DBF à traiter...
Voilà, voilà,
Bise, :lol:
Gerhard
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) et BitMap +

Message par Kwai chang caine »

Je croyais que les c'etait des DB...
Les DBF, je crois qu'ils sont lisible en ASCII ???
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) et BitMap +

Message par GeBonet »

Kwai chang caine a écrit :Les DBF, je crois qu'ils sont lisible en ASCII ???
Oui, ils sont lisibles quand on connait la structure et c'est ce qui est expliqué dans ce que j'ai posté et que l'on peux analyser à travers le code que j'ai passé... C'est donc un fichier à accès direct et qui a donc une structure avec des longueurs de champs FIXE et ayant aussi pour chacun des types définit (C=Caractère, N=Numérique, D=Date, L=Logique et M=Memo)... Mais il faut un peux lire :wink:
En plus, et c'est indiqué, le champs de type "Memo" du fichier principal (.DBF), est en fait un pointeur vers un deuxième fichier avec une extension ".DBT" et l'existence de ce fichier dépend du premier byte du fichier principal ".DBF"... 03h=il n'y a pas de DBT et 83h=il y en a un...
Donc, résumons :
- Un fichier ".DBF" à une partie descripteur de la suite sur 32 bytes (Nombre de champs, Nombre d'enregistrement, taille total avant les données, longueur de chaque enregistrement et si il y a un fichier mémo, etc..)
- 32 Bytes suivis des Champs, de leurs type et des longueurs de chacun
- Enfin les enregistrements de champs, de type et de longueur Fixe

Bon, le reste voir le programme si utile.. 8)
La dessus, bonne nuit...
Abraço,
Gerhard
PS: Ha, il y a aussi le programme pour gérer une BitMap, qui utilise les fonction logiques pour masquer les bits utiles ou non, voir pour les additionner ou soustraire... C'est un sujet que tu avais abordé je crois.
Ici tu en as une application !
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Re: Fichier a Acces Direct (Ramdom Access File) et BitMap +

Message par gnozal »

-- Info --

Pour utiliser des fichiers dBase, il y a la librairie Chetaah : http://cheetahdatabase.sourceforge.net/

Librairie : http://sourceforge.net/projects/cheetahdatabase/

Include pour Purebasic (DLL + exemples inclus) : http://sourceforge.net/tracker/download ... id=3400191

Exemple :

Code : Tout sélectionner

IncludeFile "..\..\include\Cheetah4_PureBASIC.pbi"

Procedure.l PBMain()
   
  Protected errcode.l
  Protected sData.s
  
  OpenConsole()
  ClearConsole()
   
  ;// CREATE A DBASE COMPATIBLE DATABASE 
  sData = "disk  = dbasetest.dbf;"
  sData + "type  = dbase;"
  sData + "memosize = 512;"           ; always 512 for dBase style databases
  sData + "field = custid,c,8,0;"     ; character
  sData + "field = custname,c,30,0;"  ; character
  sData + "field = amountdue,n,12,2;" ; numeric, 2 decimal places
  sData + "field = lastpymt,d,8,0;"   ; date
  sData + "field = isactive,l,1,0;"   ; logical y/n, t/f
  sData + "field = notes,m,10,0;"     ; dbase memos are always size 10 
  
  ; Create the actual database. A second file With a .dbt extension is
  ; created To hold the memo field text. If no fields were specified 
  ; With the Memo type then the .dbt would Not be created.
  errcode = xdbCreateDatabase( sData ) 
  If errcode : Goto ExitOut : EndIf
  PrintN("dBase database created.")


  ;// CREATE A FOXPRO COMPATIBLE DATABASE 
  sData = "disk  = foxprotest.dbf;"
  sData + "type  = foxpro;"
  sData + "memosize = 64;"
  sData + "field = custid,c,8,0;"     ; character
  sData + "field = custname,c,30,0;"  ; character
  sData + "field = amountdue,y,8,0;"  ; currency type
  sData + "field = lastpymt,t,8,0;"   ; datetime type
  sData + "field = isactive,l,1,0;"   ; logical y/n, t/f
  sData + "field = notes,m,4,0;"      ; FoxPro memos are always size 4
  
  ; Create the actual database. A second file With a .fpt extension is
  ; created To hold the memo field text. If no fields were specified
  ; With the Memo type then the .fpt would Not be created.
  errcode = xdbCreateDatabase( sData )
  If errcode : Goto ExitOut : EndIf
  PrintN("FoxPro database created.")
       

ExitOut:

   ;// SHUTDOWN THE SYSTEM (This will close files And free internal allocated memory)
   xdbShutdown()

   PrintN("Demo Completed")
   
   While Inkey() = "": Wend
        
EndProcedure

PBMain()
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) et BitMap +

Message par GeBonet »

Ben, merci... C'est toujours ça de plus ! :wink:
Surtout pour qui voudrais CRÉER et GÉRER un/des fichiers de type DBASE... !

Mon propos c'est la lecture d'un fichier DBASE et donc disposer de la description de la structure d'un fichier Dbase de manière à y avoir accès, donc d'en faire ce qu'on veux... Infos, basé bien évidement sur de la documentation issue des manuels de Borland...
A partir de ça la lecture par les codes ci-dessus est beaucoup plus simple et courte que le chargement d'une librairie... Qui de surcroit est fermée, c'est basé sur une "Dll".

Toutefois il est évident aussi que si l'on veux utiliser une forme de gestion complète de fichier de type Dbase, la librairie trouve là TOUTE son utilité. 8).
Encore merci ! :D
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) et BitMap +

Message par GeBonet »

Voici la dernière version que je publierais de la gestion d'une BitMap dédié à la gestion d'enregistrement sur disque dur !
Dernier rappel : Chaque bit représente sur une "Carte" une position occupé "1" ou vacante "0" d'où à chaque
position d'un bit dépend une position d'un enregistrement existant ou non, libre ou occupé ! Amplement
détaillé dans les commentaires.

Si cela peut servir à quelqu'un ??? Tant mieux :wink: Sinon... Tant pis ! :cry:

Code : Tout sélectionner

; //////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;  Application des test Binaire à la création d'une "BitMap" de gestion de fichier.
;  
;  (PAS UNICODE)                                         GeBonet      : Le 19/11/2011 
;                                                        Mise à jours : Le 28/11/2011
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////////////////
;  =================================================================================
;                             * < GESTION de BIT MAP > *                            
; ==================================================================================
;{ Explications et OBJET : Mais Qu'est-ce qu'une BITMAP dans ce CAS ?               
; ---------------------------------------------------------------------------------- 
; C'est une "carte" représentant sous forme binaire l'occupation ou non d'une position 
; parmi un nombre déterminé d'enregistrement. Où si l'on veut à chaque 1 correspond une 
; position OCCUPÈE et un 0 sera une position LIBRE soit pour 8 enregistrements crée nous
; aurions la carte ="11111111" tandis que "11110111" nous dis que la position 4 est libre
; (les bits se lisent de droite à gauche). 
; 
; Cet exemple de 8 n'est pas anodin. Je l'ai pris pour illustrer le fait que c'est aussi un
; BYTE. D'ou qu'un seul BYTE peut servir pour connaitre l'occupation ou non de 8 enregistrements 
; qu'une carte binaire de 128 bytes permet de contrôler 1024 enregistrement et forcément 1 méga 
; de carte = 8 méga d'enregistrement. 
;
; L'INTERET de ce contrôle ? 
; ------------------------ : Cela permet de ne pas faire croître un fichier et de réaffecter 
; directement les enregistrements effacés. Cela permet aussi au moment de l'effacement de ne
; supprimer que virtuellement l'enregistrement en mettant sa position dans la Map à 0 sans pour
; autant effacer réellement l'enregistrement. 
; 
; Tout en étant que cela va plus vite de mettre à 0 un bit qu'un enregistrement qui ne sera  
; réellement effacé qu'au moment de sa réoccupation par un nouveau. 
; Soit une réelle gestion dynamique d'un fichier a accès direct. 
; 
; Donc le principal intérêt est que sur des fichiers à accès direct et de très grande taille
; cela permet une gestion très rapide des "trous" par réaffectation des espaces vacants sans
; devoir réorganiser quoi que ce soit. 
;
; Il va de soit que si l'on peu y associer la gestion d'un Index pour un travaille avec des 
; clefs pour retrouver les enregsitrements. Clefs auxquels on associerait la position de 
; l'enregistrement dans le fichier. 
; *********************************************************************
; Dès lors l'écriture d'un enregistrement se ferait selon la séquence :
; *********************************************************************
; 1- Recherche d'une place vacante du fichier direct grâce à la BitMap  
; 2- Ecriture des données dans le fichier direct a la position donnée par ma BitMap... 
; 3- Ecriture dans l'index de la clef avec la position des données dans le fichier direct.
; *********************************************************************
; La lecture c'est l'inverse... et on ne touche pas à la BitMap  
; *********************************************************************
; 1- Grâce à la Clef nous obtenons la position de L'enregistrement
; 2- Avec la position je lirais de L'enregistrement ou qu'il soit dans le fichier direct... 
; *********************************************************************
; Pour l'effacement : 
; *********************************************************************
; 1- On efface seulement la clef et son pointeur de position dans l'Index
; 2- Puis son BIT représentant sa position dans la BitMap. 
; *********************************************************************
;}
; ----------------------------
;-  La SIMULATION CI-DESSOUS : 
;- ---------------------------
;{ Comporte 5 Phases ! (+1)         
; 
; Phase 1 : ou INITIALISATION des paraètres utiles...
;  
; Phase 2 : création d'une BitMap de 128 bytes avec tout ses bits occupés !  
;           Soit une 128 fois 255 plus le nombre de ligne en fonction du 
;           nombre d'enregistrements à gérer. 
;
; Phase 3 : Nous allons libérer dans la BitMap de manière aléatoire 10 enregistrements 
;           et mettre à ZERO les 10 Bits qui representerons cette position devenue vaccante. 
;           plus retenir les positions libérées. 
;
;      (+1) Par la même occasion on VERIFIE que le Bit à Bien été mis à ZERO !
;           ou TEST Si Bit est présent : Cette procedure permet de vérifier si un bit est 
;           à UN ou à ZERO... Test à inclure si vous le jugez utile. Il ne modifie 
;           en rien l'état du BIT, tester !    
;
; Phase 4 : Ayant des bits mis à zéro (Enregistrements libre) 
;           on fait Un TEST de recherche d'un enregistrement Libre !!!! 
;
; Phase 5 : A partir des positionz retenuez comme mis à "0", nous allons 
;           les positionner à "UN"... Occupé et le cycle est ainsi totalemen testé. 
; 
; ==================================================================== 
; NOTE : J'utilise des tests Binaire qui ont été montré dans ce forum   
;        afin de rester dans la ligne de travaille déjà prsenté et par 
;        extension une manière de les utiliser !                       
;}==================================================================== 
; ==================================================================================
;- Phase 1 : ou INITIALISATION des paraètres utiles...                                   
; ==================================================================================
;{
#Premier= 1 << 0 : #Second = 1 << 1 
#Troisem= 1 << 2 : #Quatrie= 1 << 3 
#Cinquie= 1 << 4 : #Sixieme= 1 << 5 
#Septiem= 1 << 6 : #Huitiem= 1 << 7 
; ----------------------------------
Declare.s MetBitaUn(k, BMap$)       
Declare.s RetireBit(k, BMap$)       
Declare.s TestBitLibre(k, BMap$)    
;                                   
Declare ChercheByteLibre()                                  
Declare CalculByteLigne(No)                                 
; ----------------------------------------------------------
Global NbLigneUtile.l,NbEnregistrement.l, Ligne, NbByte, Bit
Global MapRef$, BMap$                                       
;                                                           
Dim Retient(20)                                 ; Pour retenir les bytes choisis dans la Phase 3.
; ----------------------------------------------+------------------------------------------------
NbEnregistrement.l=9000                         ; Nombre d'enregistrement utile à priori...
NbLigneUtile.l    =Int(NbEnregistrement/1024)+1 ; Dimension du tableau de Bloc de 128 bytes
NbByte=128                                      ; Taille d'une ligne de BitMap ! 
;
Global Dim TblMAP$(NbLigneUtile)                ; Table des BitMap$ définie avec 'NbLigneUtile'
;
BMap$=LSet(BMap$,NbByte,Chr(255))               ; Création d'une ligne de Bytes de Bit à lire ou écrire
MapRef$=BMap$                                   ; On a ici initalisé les Bit comme état occupés...(a 1)
;}
; ----------------------------------------------+-----------------------------------
;- Phase 2 : création d'une BitMap de 128 bytes avec tout ses bits occupés !  
; ==================================================================================
;{
Debug "================================"
Debug "* Attention ICI test Bitmap !!!*"
Debug "================================"
Debug ""                                
; ===================================================================================
;  Création d'une BitMap virtuelle pour "NbEnregistrement" soit "NbLigneUtile"       
;  de 128 bytes ou 1024 enregistrements                                              
; ===================================================================================
; Cette partie pour le test...                                                    
;                                                                                 
For i=1 To NbLigneUtile   ; Ici création d'une BitMap Virtuelle de "NbLigneUtile"
  TblMAP$(i)=BMap$        ; de 128 Bytes pleine. Soit l'équivalent de 128 x 8 =  
Next i                    ; 1024 fois "NbLigneUtile" Bytes qui seront contrôlé ! 
; ------------------------+----------------------------------------------------------
; Dans l'exemple : Nous avons 9000 enregistrements à contrôler cela va donc donner :  
; NbLigneUtile=int(9000/1024)+1 => 8+1 = 9 lignes soit 9 x 1024 = 9216 enregistrements         
;} qui seront donc contrôlés.             
; ==================================================================================
;-  Phase 3 : La BitMap est pleine (tout bit à 1) On RETIRE 10 Bits aléatoirement 
; ==================================================================================
;{
  No=1024 : Retient(1)=No ; Simule un Byte particulier le 128 qui contient le 1024ème Bit.
  ;                       ; -------------------------------------------------------------
  Debug "Enregistrement ="+Str(No)+" <<==="   
  k=CalculByteLigne(No)   ; Recherche du Byte et la ligne BMap$ concernée
  BMap$=RetireBit(k,BMap$); Va retirer le Bit correspondant à la position "k" (mettre à 0)
  TblMAP$(Ligne)=BMap$    ; Repositionne la BitMap Modifié avec Bit mis à 0
  ;                       ; 
  ;                       ; Phase de selection Aléatoire d'enregistrement à mettre à zéro                                                                                        
For i=2 To 11             ; Ici on va choisir aléatoirement 10 enregistrement à mettre à 0 
  ;                       ; 
  No=Random(NbEnregistrement)+1 :Retient(i)=No ; Debug "Enregistre="+Str(No)             
  Debug "Enregistrement ="+Str(No)+" < ==="   
  k=CalculByteLigne(No)   ; Recherche du Byte et la ligne BMap$ concernée
  ;                       ; 
  ; ----------------------+---------------------------------------------------------------
  BMap$=RetireBit(k,BMap$); Va retirer le Bit correspondant à la position "k" (mettre à 0)
  ; ----------------------+---------------------------------------------------------------
  ;                       ; 
  ; On vérifie...         ; A-t'il été mis à zéro... ICI pour montrer 
  ;                       ; comment verifier si un Bit à bien été mis à zéro 
  OK$=TestBitLibre(k,BMap$)
  ;                       ;
  If OK$="0":Reponse$="OUI" : Else : Reponse$="NON":EndIf
  Debug "Est-il à 0 => "+Reponse$
  Debug "********************"
  TblMAP$(Ligne)=BMap$    ; Repositionne la BitMap Modifié avec Bit mis à 0
  ;
Next i
;}
; ==================================================================================
; Affichage des enregistrements qui ont été mis à zéro dans la BitMap               
; ==================================================================================
For i=1 To 11                                                                       
  Debug "Bit mis à zéro pour l'enregistrement : "+Str(Retient(i))                   
Next i                                                                              
; ----------------------------------------------------------------------------------
; Simulation de recherche d'un Bit Vaccant. En principe, c'est le premier disponible
; qui devrait être trouvé. Soit parmis les "Retient(i)", celui avec la plus petite  
; valeur.                                                                           
;}
; ---------------------------------------------------------------------------------- 
;- Phase 4 : Ayant des bits mis à zéro (Enregistrements libre)                       
; ---------------------------------------------------------------------------------- 
;{
Debug "============================================"                                
Debug "= Simule la recherche de position vaccante 1 ":Debug ""                               
Position=ChercheByteLibre()     ; Simultation de recherche de position vaccante ... 
Debug "----------------------------> Trouvé : "+Str(Position)+" Le premier "         
Debug ""
; ------------------------------+---------------------------------------------------   
; Met cette position trouvé à 1 ; Pour forcer la seconde recherche ailleurs....     
; ------------------------------+--------------------------------------------------- 
  No=Position                   ; Prend l'enregistrement dont le bit à été mis à zéro...
  Debug " Met Enregistrement ="+Str(No) +" trouvé à 1 "                                  
  k=CalculByteLigne(No)         ; Recherche du Byte et la ligne BMap$ concernée     
  ; ----------------------------+--------------------------------------------------- 
  BMap$=MetBitaUn(k, BMap$)     ; Mise à un du bit représentant l'enregistrement 'k' dans la BMap$
  ; ----------------------------+--------------------------------------------------- 
  TblMAP$(Ligne)=BMap$          ; Repositionne la BitMap Modifié avec Bit remis à 1 
; ------------------------------+--------------------------------------------------- 
Debug "============================================"                                
Debug "= Simule la recherche de position vaccante 2 "                               
Position=ChercheByteLibre()     ; Simultation de recherche de position vaccante ... 
Debug "----------------------------> Trouvé : "+Str(Position)+" La seconde "        
Debug ""                                                                             
;}
; ==================================================================================
;-  Phase 5 : La BitMap contient 10 bit qui on été mis à zéro on les remets à 1       
; ==================================================================================
;{ 
Debug "========= Remise à Un ============"
Debug ""
For i=1 To 10
  ;
  No=Retient(i)                 ; Prend l'enregistrement dont le bit à été mis à zéro...
  Debug "=======================":Debug "Enregistrement="+Str(No)
  k=CalculByteLigne(No)         ; Recherche du Byte et la ligne BMap$ concernée
  ; ----------------------------+---------------------------
  BMap$=MetBitaUn(k, BMap$)     ; Mise à un du bit représentant l'enregistrement 'k' dans la BMap$
  ; ----------------------------+---------------------------
  TblMAP$(Ligne)=BMap$          ; Repositionne la BitMap Modifié avec Bit remis à 1
  ;
Next i
;}
End
; ====================================================================
;- Les PROCEDURES de Gestion BITMAP -
; ====================================================================
Procedure.s MetBitaUn(k, BMap$) ; Mise à "UN" d'un Bit dans un Byte
  
  ByteConcerne=Int(k/8)+1: Bit =k-((ByteConcerne-1)*8) 
  If Bit=0:ByteConcerne=ByteConcerne-1: Bit=8: EndIf
  Debug "Byte Choisi="+Str(ByteConcerne)+" Bit Choisi="+Str(Bit)
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;         
  Select Bit ; Test bininaire en fonction du BIT   
    Case 1 : Byte | #Premier : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 2 : Byte | #Second  : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 3 : Byte | #Troisem : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 4 : Byte | #Quatrie : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 5 : Byte | #Cinquie : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 6 : Byte | #Sixieme : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 7 : Byte | #Septiem : Debug "Positionne le bit "+Str(Bit)+"="+Bin(Byte)
    Case 8 : Byte | #Huitiem : Debug "Positionne le bit "+Str(Bit)+"="+RSet(Bin(Byte),8,"1")
  EndSelect
  ;Debug "--------------------"
  BMpa$=Left(BMap$,ByteConcerne-1)+Chr(Byte)+Mid(BMap$,ByteConcerne+1)
  ProcedureReturn BMpa$
  
EndProcedure  
Procedure.s RetireBit(k, BMap$) ; Mise à "ZERO" d'un Bit dans un Byte
  
  ByteConcerne=Int(k/8)+1 : Bit =k-((ByteConcerne-1)*8)
  If Bit=0:ByteConcerne=ByteConcerne-1: Bit=8: EndIf
  Debug "Byte Choisi="+Str(ByteConcerne)+" Bit Choisi="+Str(Bit)
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;                             ; 
  Select Bit                    ; Test bininaire en fonction du BIT   
    Case 1 : Byte & ~(#Premier) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 2 : Byte & ~(#Second)  : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 3 : Byte & ~(#Troisem) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 4 : Byte & ~(#Quatrie) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 5 : Byte & ~(#Cinquie) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 6 : Byte & ~(#Sixieme) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 7 : Byte & ~(#Septiem) : Debug "Retire le bit "+Str(Bit)+"="+Bin(Byte)
    Case 8 : Byte & ~(#Huitiem) : Debug "Retire le bit "+Str(Bit)+"="+RSet(Bin(Byte),8,"0")
  EndSelect                     ; 
  ;Debug "--------------------"
  BMpa$=Left(BMap$,ByteConcerne-1)+Chr(Byte)+Mid(BMap$,ByteConcerne+1)
  ProcedureReturn BMpa$
  
EndProcedure  
Procedure.s TestBitLibre(k,BMap$); Test de l'état d'un Bit 0 ou 1 
  ;  Phase TEST Si Bit est présent                 
  ;  Si OUI il rend la position du Bit-1, Sinon =0 
  ; -----------------------------------------------  
  Debug " - - - - - - - - - - : "+Str(k)
  ByteConcerne=Int(k/8)+1             : Debug "ByteChoisi="+Str(ByteConcerne)
  Bit         =k-((ByteConcerne-1)*8) : Debug "Bit Choisi="+Str(Bit)
  If Bit=0:ByteConcerne=ByteConcerne-1:Bit=8:EndIf
  Byte=Asc(Mid(BMap$,ByteConcerne,1)) : Debug "ByteOrgine="+Bin(Byte)
  ;
  Select Bit                     ; Test bininaire en fonction du BIT   
    Case 1 : Resultat=Byte & #Premier : Debug "Resultat : "+Str(Resultat)
    Case 2 : Resultat=Byte & #Second  : Debug "Resultat : "+Str(Resultat)
    Case 3 : Resultat=Byte & #Troisem : Debug "Resultat : "+Str(Resultat)
    Case 4 : Resultat=Byte & #Quatrie : Debug "Resultat : "+Str(Resultat)
    Case 5 : Resultat=Byte & #Cinquie : Debug "Resultat : "+Str(Resultat)
    Case 6 : Resultat=Byte & #Sixieme : Debug "Resultat : "+Str(Resultat)
    Case 7 : Resultat=Byte & #Septiem : Debug "Resultat : "+Str(Resultat)
    Case 8 : Resultat=Byte & #Huitiem : Debug "Resultat : "+Str(Resultat)
  EndSelect
  Debug " - - - - - - - - - -"
  ProcedureReturn Str(Resultat)
  
EndProcedure
; ====================================================================
;- RECHERCHE D'une position VACCANTE -                               
; ====================================================================
Procedure ChercheByteLibre()  
  ; 
  ; Cherche une position libre dans la Carte représentant les enregistrements                   
  ; ------------------------------------------------------+-------------------------------------
  For J = 1 To NbLigneUtile                               ; Nombre ligne contenant les BMap$    
    If TblMAP$(J)<>MapRef$                                ; Y a t'il au moins un Byte<>255      
      For i=1 To NbByte                                   ; Recherce de ce Byte différent       
        Byte=Asc(Mid(TblMAP$(J),i,1))                     ;                                     
        If Byte<>255                                      ; Celui là est différent     
          Byte=Asc(Mid(TblMAP$(j),i,1))                   ; 
          FormBin$=RSet(Bin(Byte),8,"0")                  ; Forme Binaire du Byte               
          Ligne=j-1:TByt=Ligne*1024+(i-1)*8               ; Position jusque Byte Précédent       
          FormaBin$=LSet(FormBin$,8,"0")                  ; Ajuste à 8 bits                    
          Debug "> A l'Endroit "+FormaBin$                                                     
          FormbBin$=ReverseString(FormaBin$);             ; Inverse les bits pour obtenir 'lordre          
          Debug "< A l'Envers- "+FormbBin$                                                      
          Bit=FindString(FormbBin$,"0"):                  ; Determine le bit concerné.          
          Position=TByt+Bit                               ; Position à zéro trouvée...           
          ; ----------------------------------------------+-------------------------------------
          ProcedureReturn Position                        ; Renvois 
        EndIf
      Next I
    EndIf
  Next J
  ProcedureReturn #False                                  ; Rien de disponible
   
EndProcedure  
Procedure CalculByteLigne(No)
  ; 
  ; Calcul de la ligne pour l'enreistrement "No" et de "k" sur la ligne  
  ; 
  Reste=No % 1024               ; Evalue si c'est le dernier bit de la ligne... 
  Ligne=Int(No/1024)+1          ; Ligne normalement concernée
  If Reste=0:Ligne=Ligne-1:EndIf; Si Reste = 0, alors c'est le dernier bit de la ligne 
  BMap$=TblMAP$(Ligne)          ; précédente qui doit être mit à zéro... !               
  k=No-((Ligne-1)*1024)         ; k = Numéro Enregistrement concerné sur cette ligne... 
  Debug "Ligne Map ="+Str(Ligne)+" Bit Choisi="+Str(k)
  Debug "-----------------------------------"
  ProcedureReturn k
  
EndProcedure
; ====================================================================
; 
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) et BitMap +

Message par GeBonet »

Rappel :
Les codes "ExpleGestionDirect.pb" et "IncLectureDirect.pbi" de gestion à accès direct page 1 ont étés mis à jours
Ainsi que le dernier BitMap...
C'est tout ! :wink:
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) et BitMap +

Message par flaith »

Merci GeBonet :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) et BitMap +

Message par Kwai chang caine »

Oui merci beaucoup de tout ce travail 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Répondre