Question

J'ai une simulation qui lit de gros fichiers de données binaires que nous créons (10 à 100 Go). Nous utilisons le binaire pour des raisons de vitesse. Ces fichiers dépendent du système et sont convertis à partir de fichiers texte sur chaque système que nous exécutons. La portabilité ne me préoccupe donc pas. Les fichiers représentent actuellement de nombreuses instances d’une structure POD, écrites avec fwrite.

Je dois changer la structure, je veux donc ajouter un en-tête contenant un numéro de version de fichier, qui sera incrémenté à chaque modification de la structure. Depuis que je fais cela, je veux ajouter d'autres informations. Je pense à la taille de la structure, à l'ordre des octets et peut-être au numéro de version svn du code qui a créé le fichier binaire. Y a-t-il autre chose qu'il serait utile d'ajouter?

Était-ce utile?

La solution

D'après mon expérience, il est invariablement une perte de temps de deviner les données dont vous aurez besoin. L'important est de structurer vos métadonnées de manière extensible. Pour les fichiers XML, c'est simple, mais les fichiers binaires nécessitent un peu plus de réflexion.

J'ai tendance à stocker les métadonnées dans une structure à la fin du fichier, pas au début. Cela présente deux avantages:

  • Les fichiers tronqués / non terminés sont facilement détecté.
  • Les pieds de métadonnées peuvent souvent être ajouté aux fichiers existants sans impact sur leur code de lecture.

Le pied de page de métadonnées le plus simple que j'utilise ressemble à ceci:

struct MetadataFooter{
  char[40] creatorVersion;
  char[40] creatorApplication;
  .. or whatever
} 

struct FileFooter
{
  int64 metadataFooterSize;  // = sizeof(MetadataFooter)
  char[10] magicString;   // a unique identifier for the format: maybe "MYFILEFMT"
};

Après les données brutes, le pied de page des métadonnées et ALORS le pied de fichier sont écrits.

Lors de la lecture du fichier, recherchez la taille finale (FileFooter). Lisez le pied de page et vérifiez la chaîne magique. Ensuite, recherchez en fonction de metadataFooterSize et lisez les métadonnées. En fonction de la taille du pied de page contenu dans le fichier, vous pouvez utiliser les valeurs par défaut pour les champs manquants.

Comme le KeithB , vous pouvez même utiliser cette technique pour stocker les métadonnées sous forme de chaîne XML, offrant ainsi les avantages des deux métadonnées totalement extensibles, avec la compacité et la rapidité des données binaires.

Autres conseils

Pour les fichiers binaires volumineux, je me pencherais sérieusement sur HDF5 (Google pour cela). Même si ce n’est pas quelque chose que vous souhaitez adopter, il peut vous indiquer des pistes utiles pour concevoir vos propres formats.

Pour les fichiers binaires volumineux, en plus du numéro de version, j’ai tendance à mettre un nombre d’enregistrements et un CRC, la raison étant que les fichiers binaires volumineux sont beaucoup plus susceptibles d’être tronqués et / ou corrompus au cours du temps ou lors du transfert que les fichiers plus petits. J'ai récemment constaté avec horreur que Windows ne gérait pas cela du tout, car j'avais utilisé l'explorateur pour copier environ 2 To sur quelques centaines de fichiers sur un périphérique NAS connecté, et j'ai trouvé 2 ou 3 fichiers sur chaque copie étaient endommagés (pas complètement copié).

Un identifiant pour le type du fichier serait utile si vous souhaitez que d'autres structures soient écrites ultérieurement dans des fichiers binaires. Peut-être que cela pourrait être une courte chaîne pour que vous puissiez voir ce qu’il contient dans le fichier (via l’éditeur hexadécimal).

S'ils sont aussi volumineux, je réserverais une bonne portion d'espace (64 Ko?) au début du fichier et placerais les métadonnées au format XML suivi d'un caractère de fin de fichier (Ctrl-Z pour DOS / Windows, ctrl-D pour unix?). De cette façon, vous pourrez facilement analyser et analyser les métadonnées avec le large éventail d’outils disponibles pour XML.

Sinon, je vais avec ce que d'autres personnes ont déjà dit: horodatage pour la création de fichier, identificateur de la machine sur laquelle il est créé, essentiellement tout ce à quoi vous pouvez penser à des fins de diagnostic. Et idéalement, vous incluriez la définition du format de structure lui-même. Si vous changez souvent la structure, il est très pénible de conserver la version de code appropriée pour lire divers formats d'anciens fichiers de données.

L'un des gros avantages de HDF5, comme @highpercomp l'a mentionné, est que vous n'avez pas à vous soucier des modifications du format de la structure, tant que vous avez une convention de ce que sont les noms et les types de données. Les noms de structure et les types de données sont tous stockés dans le fichier lui-même, vous pouvez donc décomposer votre code C en petits morceaux et peu importe, vous pouvez toujours récupérer les données d'un fichier HDF5. Cela vous permet de vous soucier moins du format des données et plus de la structure des données, c’est-à-dire que la séquence d’octets m’importe, c’est le problème de HDF5 faites attention aux noms de champs et autres.

Une autre raison pour laquelle j'aime HDF5 est que vous pouvez choisir d'utiliser la compression, qui prend très peu de temps et vous permet de gagner énormément en espace de stockage si les données changent lentement ou sont sensiblement les mêmes, à l'exception de quelques erreurs erronées. d'intéressant.

@rstevens a déclaré "un identifiant pour le type de fichier" ... conseil judicieux. En règle générale, cela s'appelle un nombre magique et, dans un fichier, ce n'est pas un terme d'abus (contrairement au code, où il s'agit d'un abus). Fondamentalement, il s'agit d'un nombre - généralement au moins 4 octets, et je m'assure généralement qu'au moins un de ces octets n'est pas ASCII - que vous pouvez utiliser pour valider que le fichier est du type que vous attendez avec une faible probabilité d'être confondu . Vous pouvez également écrire une règle dans / etc / magic (ou son équivalent local) pour indiquer que les fichiers contenant votre numéro magique sont votre type de fichier spécial.

Vous devez inclure un numéro de version du format de fichier. Cependant, je recommanderais de ne pas utiliser le numéro SVN du code. Votre code peut changer lorsque le format du fichier ne change pas.

Outre les informations dont vous avez besoin pour la gestion des versions de schéma, ajoutez des détails qui peuvent être utiles si vous résolvez un problème. Par exemple:

  • horodatages du moment où le fichier a été créé et mis à jour (le cas échéant).
  • la chaîne de version de la construction (idéalement, vous avez une version incrémentée automatiquement à chaque génération "officielle" ... différente de la version du schéma de fichier).
  • le nom du système créant le fichier et éventuellement d'autres statistiques pertinentes pour votre application

Nous trouvons cela très utile (a) pour obtenir des informations que nous aurions sinon demander au client de fournir et (b) pour obtenir des informations correctes - il est étonnant de constater combien de clients déclarent utiliser une version différente du logiciel. à quoi les données prétendent!

Vous pouvez envisager de placer un décalage de fichier à une position fixe dans l'en-tête, ce qui vous indique où les données réelles commencent dans le fichier. Cela vous permettrait de modifier la taille de l'en-tête en cas de besoin.

Dans quelques cas, j'ai placé la valeur 0x12345678 dans l'en-tête afin de détecter si le format du fichier correspond à l'endianisme de la machine qui le traitait.

Comme le montre mon expérience en matière de configuration des équipements de télécommunication et de mise à niveau du micrologiciel, vous n’avez besoin que de plusieurs octets prédéfinis (c’est important) à partir de la version (partie fixe de l’en-tête). Le reste de l'en-tête est facultatif, en indiquant la version appropriée, vous pouvez toujours montrer comment le traiter. Ce qui est important ici, c'est de placer la partie 'variable' de l'en-tête à la fin du fichier. Si vous planifiez des opérations sur l'en-tête sans modifier le contenu du fichier lui-même. De plus, cela simplifie les opérations 'append' qui doivent recalculer la partie d'en-tête de variable.

C'est bien d'avoir des fonctionnalités pour les en-têtes de taille fixe (au début):

  • Champ 'longueur' commun (en-tête compris).
  • Quelque chose comme CRC32 (en-tête compris).

OK, une bonne idée pour le XML de partie variable ou un format assez extensible dans l'en-tête, mais est-ce vraiment nécessaire? J'avais beaucoup d'expérience avec l'encodage ASN ... dans la plupart des cas, son utilisation était dépassée.

Eh bien, peut-être aurez-vous une compréhension supplémentaire en regardant des éléments comme le format TPKT décrit dans RFC 2126 (chapitre 4.3).

Si vous mettez un numéro de version dans l'en-tête, vous pouvez modifier cette version à tout moment. Vous devez modifier la structure du POD ou ajouter de nouveaux champs à l'en-tête.

Donc, n’ajoutez pas de contenu à l’en-tête maintenant, cela pourrait être intéressant. Vous créez simplement du code que vous devez gérer mais qui a peu de valeur réelle.

Pour les fichiers volumineux, vous pouvez ajouter des définitions de données afin que votre format de fichier devienne auto-descriptif.

Ma variante combine les approches de Roddy et Jason S.

En résumé - placez les métadonnées au format texte à la fin du fichier avec un moyen de déterminer sa longueur stockée ailleurs.

1) Placez un champ de longueur au début de votre fichier afin de connaître la longueur des métadonnées à la fin plutôt que de prendre une longueur fixe. Ainsi, pour obtenir les métadonnées, il vous suffit de lire ce champ initial de longueur fixe, puis de récupérer le blob de métadonnées à la fin du fichier.

2) Utilisez XML, YAML ou JSON pour les métadonnées. Ceci est particulièrement utile / sûr si les métadonnées sont ajoutées à la fin car personne ne lisant le fichier pense automatiquement que tout est XML simplement parce que cela commence par XML.

Le seul inconvénient de cette approche est que, lorsque vos métadonnées augmentent, vous devez mettre à jour à la fois la tête du fichier et la queue, mais il est probable que d'autres parties auront été mises à jour de toute façon. S'il ne s'agit que de mettre à jour des anecdotes comme une date de dernier accès, la longueur des métadonnées ne changera pas et une mise à jour uniquement est nécessaire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top