IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Format de fichier extensible


Sujet :

C++Builder

  1. #1
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut Format de fichier extensible
    Bonjour,

    Je cherche un moyen facile (code, composant, astuce, etc.) pour créer un nouveau format de fichier extensible. Ce fichier fait partie d'un programme qui est en cours d'évolution ... pour une question de temps il est déjà distribué en l'état au client.
    J'avais pensé à utiliser un TIniFile. En effet, on peut ajouter des sections comme on le veut. Elles sont ignorées par les anciens programmes et si le fichier a été sauvés avec un ancien programme on sait quand même l'ouvrir dans un nouveau (la valeur de la clé étant remplacée tout simplement par une valeur par défaut).
    Le problème c'est que le fichier doit se comporter comme une archive. Il doit pouvoir stocker d'autres fichiers (<10ko). J'avais pensé les sauver en stream dans le fichier Ini mais tous les caratères ASCII ne passent pas ... de plus, à mon humble avis, il doit y avoir une manière plus jolie de gérer tout ça! Peut-être devrais-je me tourner du côté du XML mais je n'y connais strictement rien ...

    Un grand merci d'avance!
    Cordialement,
    Rodrigue
    Rodrigue

  2. #2
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    J'ai 2 types de solutions l'une est relative à des fichiers textes dont les lignes sont du type Identifiant = valeur du type de certain ficiers ini. Il est très facile alors d'ajouter les lignes nouvelles en ajoutant de nouveaux identifiants. L'autre est relative à des fichiers binaires ou on lit le fichier jusqu'au bout. Si une novelle version comporte plus de données alors capter l'erreur en lecture à partir d'un certain stade pour donner des valeurs par défaut aux nouvelles données. En fin d'execution sauver lea nouvelle structure et le tout est dit.

  3. #3
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Bonjour,

    J'aime bien l'idée du fichier Ini ! Notamment pour sa simplicité ... Le problème comme je le dis dans mon premier message :
    Le problème c'est que le fichier doit se comporter comme une archive. Il doit pouvoir stocker d'autres fichiers (<10ko). J'avais pensé les sauver en stream dans le fichier Ini mais tous les caratères ASCII ne passent pas
    Je n'arrive pas à sauver le stream comme un élément unique dans le fichier Ini. Peut-être avez-vous une solution ?

    Maintenant quant à la solution du fichier binaire, je la trouve très difficile (p-e que je me trompe ).

    Cordialement,
    Rodrigue
    Rodrigue

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    Un fichier binaire est T R E S facile à manipuler sutout pour des données structurées. Il est + dense qu'un fichier texte, on n'y fait pas d'eereur d'arroudi sur les float,... Seul petit inconvenient : on ne peut pas facilement l'editer "à la main".
    Il est alors quasi imédiat de pouvoir aller lire/écrire le bloc No n en calculant l'offset, de se déplacer de x blocs ou de pointer sur un element quelconque de l'un des blocs.
    Lors d'un changement de version si la nouvelle version contient plus de data à stocker il est + facile de concerver toute la 1er partie commune, de detecter la fin de fichier et compléter à la 1er execution de la novelle version.
    D'experience (25 ans de programation) je sais qu'il est aussi nettement preferable de noter le no de version en début de fichier. cela permet au soft de savoir comment décoder la suite sans perte de donnée ou risque de mélange. On est aussi quitte de la contrainte d'une compatibilite ascendante: si une novelle version du soft voit un fichier qui n'est pas de sa version, pas de chargement direct mais appel à transcodeur que le developpeur ecrit sans mal connaissant les structures des 2 versions impliquées.


    en C++ ouverture en réécriture

    FILE *f; f = fopen ( C,"wb"); (C char[] )
    voir les ordres du type
    SEEK_SET 0 Seeks from beginning of file
    SEEK_CUR 1 Seeks from current position
    SEEK_END 2 Seeks from end of file
    avec int fseek(f, offset, whence); pour aller en un point quelconque du fichier
    en lecture utiliser fread(Buffer,nombre,taille_element,f); (Buffer est une adresse)
    la taille d'un element s'obtient avec la fonction sizeof(XXX);
    pour lire et completer utiliser fopen(C,"rb+");
    bien entendu ne pas oublier fclose(f);

    pour rappel apres f=fopen(C,"rb"); on a la taille du fichier via
    taille = filelength(fileno(f)); // si fopen a marché et donc f != NULL

    tout cela est tres bien documenté sous borland avec les mots clef fopen, fseek, fclose.

    exemple tres simple ecrit "à la va-vite" ici pour illustrer => il manque peut-etre un ; ou 1 parenthèze!


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    struct Wave_File_Header
            {
            char                    RIFF[4]; //"RIFF" in ASCII form
            long                    Data_Size_plus_36; // filesize-8 = nbr data * bitsperdata+ 36
            char                    WAVE[4]; // lettres "WAVE"
            char                    fmt[4]; // lettress "fmt "
            long                    Remain_in_Chunk1; // 16 en format  PCM .
                                    // ce qui reste du Subchunk après ce nombre .
                                    // = audioformat+numchanel+samplerate+byterate+blockalign+bitpersample
                                    // =2+2+4+4+2+2 = 16
            short                   AudioFormat; //  PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
            short                   NumChannels; //  Mono = 1, Stereo = 2, etc.
            long                    SampleRate;//       8000, 44100, etc.
            long                    ByteRate; // SampleRate * NumChannels * BitsPerSample/8
            short                   BlockAlign; // NumChannels * BitsPerSample/8
            short                   BitsPerSample; //     8 bits = 8, 16 bits = 16, etc.
            // maintenant The "data" subchunk contient la taille des data puis les data eux-mêmes
     
            char                    data[4];// "data"
            long                    Data_Size; // taille des data = NumSamples * NumChannels * BitsPerSample/8
            // ici commence les data dans le fichier wave
       };
    // fonction qui change la frequence et retourne le nombre de data 
    // atention : le nombre d'echantillons est = à nombre de data / BitsPerSample * 8 c'est à dire en 116b il y a 2X moins de d'échantillon
    // que de data. De plus si dans le header on trouve stereo, le nombre d'echantillon / canal
    // est encore la moitié du chiffre ci-dessus
    // stop ici si les waves: le sujet est illustrer acces fichier binaire
     
    // BitsPerSample = 8 ou 16
     
    long Set_Frequency_and_return_Ndata(Ansistring WAV, short fr)
    // attention a l'execution d'1 telle routine s'assurer que fr est une frequence
    // admise par la carte son en place.  c'est facile de les connaitre mais cela est un autre sujet.
       {
       long l;
       char C[255];
       FILE *f;
       stuct  Wave_File_Header HD;
       if ( ! FileExists(WAV))
           { ShowMwessage("fichier absent"); return -1;}
       for (short i=1; i<=WAV.Length(); i++) { C[i-1] = WAV[i]; C[i]='\0';}
       f = fopen(C,"rb");
       if ( f == NULL) 
          { showMessage(Impossible d'ouvrir en lecture " + WAV);  return -1;}
       if (filesize(fileno(f)) < sizeof(HD)) 
          {ShowMessage("même pas les  44 bytes du header! fichier DETRUIT"); fclose(f); unlink(C); return -1;}
       fread(&HD,1,44,f);
       fclose(f);
       l = HD.SampleRate;  // ancien data  
       HD.SampleRate = fr;
       HDByteRate=HD.ByteRate*fr/l;  // pour cet example d'un header --.wav
       f = fopen(C,"rb+");  // pas "wb" qui ecrase le file pour en creer un new
       // pas besoin de fseek ici car on pointe deja au debut
       fwrite(&HD,44,1,f);
       fclose(f);
       return HD.Data_Size;
       }
     
    // ( j'ai tapé ce tout petit code ici sans test d'une eventuelle erreur de frappe )

  5. #5
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Points : 1 148
    Points
    1 148
    Par défaut
    Je pense aussi que le fichier binaire est le must.

    Pour une évolutivité et une compatibilité ascendante et descendante regarde du coté des formats de fichier de type "CHUNK" comme le Wave (exemple à ne pas suivre car ce format est devenu un bordel monstre !).

    En gros tu as ton entête de fichier où tu stockes ce dont tu as besoin. Puis dans ton fichier se suivent des blocs ou chunks.

    Chaque début de chunk est au format suivant :

    un identifiant sur 4 caractères par exemple afin de savoir quel type de chunk on va lire
    immédiatement après l'identifiant le nombre d'octet de ce chunk afin de pouvoir facilement le sauter et passer au chunk suivant si on est pas capable de le lire (identifiant inconnu).

    Voila avec ça tu devrais avoir ton bonheur
    Neilos

  6. #6
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Ok, merci!

    Je pensais qu'une telle solution existait déjà ... Style un composant pour faire des archives. En plus c'est bien le fichier binaire mais à chaque fois que j'ai un TMemoryStream à sauvegarder il faut que je l'écrive dans un tableau de char puis seulement aller écrire dans le fichier ... pas très rapide tout ça non?

    Cordialement,
    Rodrigue
    Rodrigue

  7. #7
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    Tu as la méthode SaveToFile du MemoryStream non ?

  8. #8
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Merci Greybird mais je connais la méthode SaveToFile... C'est vrai qu'une solution "simple" est possible.
    Il faudrait donc que je construise un TMemoryStream global dans lequel j'irais inscrire mes autres TMemoryStream que j'aurais segmentés par des repères (type de fichier + taille)...
    Je récupère la taille de chacun de mes TMemoryStream via leur méthode Size, le type de fichier est arbitraire mettons que je le code sur deux octets...
    Comment coller deux TMemoryStream ensemble ?

    Merci d'avance!
    Cordialement,
    Rodrigue
    Rodrigue

  9. #9
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Rodrigue
    Comment coller deux TMemoryStream ensemble ?
    Tu peux envisager, tout simplement, d'écrire le contenu du flux A à la fin du flux B, puis de détruire le flux A devenu inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // On va à la fin du flux B.
    B.Seek(0,soFromEnd);
    // Copie intégrale de A dans B.
    A.SaveToStream(B);
    // On peut détruire le flux A désormais.
    EDIT : Et une fois le TMemoryStream "complet" créé, un bon p'tit coup de SaveToFile et ZOU ! Terminé ! ;-)
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  10. #10
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Points : 1 271
    Points
    1 271
    Par défaut
    Il y a aussi la méthode CopyFrom je crois qui permet de copie les streams entre eux.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2007] Changement de format entre fichier sans extension -> Excel
    Par Floup dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 20/02/2012, 15h36
  2. Quel SGBD correspond aux fichiers à extension .DAT
    Par jcpitaud dans le forum Autres SGBD
    Réponses: 4
    Dernier message: 12/04/2006, 20h11
  3. [C / C++][Format de fichier] Le TIFF G4
    Par chronos dans le forum Windows
    Réponses: 1
    Dernier message: 17/06/2005, 15h57
  4. [Format de Fichier] Recherche de site
    Par Pedro dans le forum Windows XP
    Réponses: 5
    Dernier message: 12/04/2005, 16h11
  5. Quel format de fichier utiliser pour les maps ?
    Par fb57 dans le forum OpenGL
    Réponses: 3
    Dernier message: 23/09/2004, 20h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo