Existe-t-il un moyen approprié de créer un format de fichier?

12

Je crée un format de fichier propriétaire pour une application que j'ai écrite en C # .NET pour stocker des informations de sauvegarde et peut-être en aval des actifs du projet. Existe-t-il une norme sur la façon de procéder de quelque façon? J'allais simplement Serializemes objets en binaire et créer un en-tête qui me dirait comment analyser le fichier. Est-ce une mauvaise approche?

corylulu
la source
2
J'éviterais BinaryFormatter.
CodesInChaos
3
Quelle que soit l'approche (des réponses) que vous choisissez, incluez toujours un numéro de version au format! Votre question suggère déjà que cela pourrait changer, et le numéro de version vous fera économiser beaucoup d'efforts si vous devez être compatible avec backwarsd.
Jan Doggen
N'oubliez pas de documenter correctement le format
Basile Starynkevitch

Réponses:

11

La méthode la plus simple consiste probablement à sérialiser votre structure en XML à l'aide de la XMLSerializerclasse. Vous n'auriez probablement pas besoin de créer un en-tête et une structure de corps distincts, mais sérialisez tous les actifs en XML. Cela vous permet d'inspecter / modifier facilement la structure de vos fichiers en dehors de votre propre programme, et est facilement gérable.

Cependant, si votre structure de fichiers est vraiment complexe, contenant de nombreux actifs différents de différents types, de sorte que la sérialisation de la structure entière en XML est trop lourde, vous pouvez envisager de sérialiser chaque actif séparément et de les compiler dans un seul package à l'aide de la Packagingbibliothèque en C # . C'est essentiellement ainsi que sont construits les fichiers .docx, .xslx, .pptx et autres formats de fichiers Office.

pswg
la source
Oui, mon projet est beaucoup plus complexe que cela, mais j'essaie également de le rendre moins lisible par l'utilisateur car nous pourrions les déployer dans un champ dans un contexte sous licence. J'utilise actuellement protobuf-netpour sérialiser mes données et cela fonctionne très bien. Mais je dois sérialiser les pièces séparément, donc ce dont vous parlez avec la bibliothèque de packaging ressemble à ce dont j'ai besoin.
corylulu
7
Cher dieu pas XML
James
2
@James ouais XML a ses inconvénients, bien sûr. Je préfère le packaging et XML dans la plupart des cas pour les mêmes raisons: 1. c'est un framework préexistant, donc nécessite peu d'efforts. 2. Les autres systèmes sont faciles à prendre en charge, car il s'agit d'une norme largement acceptée. 3. Il est facile pour un humain d'inspecter le fichier résultant pour vérifier le processus de sérialisation.
pswg
XML a des avantages, mais c'est à cause de ces avantages que je n'aime pas utiliser le sérialiseur XML. Je crois que cela nécessite que le XML soit dans un format spécifique. XML est un format semi-structuré, qui permet à mon format de fichier de changer au fil du temps et d'être toujours compatible en amont et même en aval. Dans le passé, j'ai écrit ma propre analyse XML tout en faisant attention à ne pas faire d'hypothèses sur la commande ou qu'il n'y ait pas de balises que je ne connais pas à l'avenir. Si vous pouvez charger l'intégralité du fichier XML, XPATH fonctionnerait probablement assez bien. Sinon, votre gauche avec une analyse de flux plus compliquée
Alan
Je suggère de regarder dans JSON
Basile Starynkevitch
7

De quelqu'un qui a dû analyser de nombreux formats de fichiers, j'ai des opinions à ce sujet d'un point de vue différent de la plupart.

  • Rendez le nombre magique très unique afin que les détecteurs de format de fichier des autres formats ne l'identifient pas à tort comme le vôtre. Si vous utilisez le binaire, allouez 8 ou 16 octets générés aléatoirement au début d'un format binaire pour le nombre magique. Si vous utilisez XML, allouez un espace de noms approprié dans votre domaine afin qu'il ne puisse pas entrer en conflit avec d'autres personnes. Si vous utilisez JSON, Dieu vous aide. Peut-être que quelqu'un a déjà trouvé une solution pour cette abomination d'un format.

  • Planifiez la compatibilité descendante. Enregistrez le numéro de version du format de manière à ce que les versions ultérieures de votre logiciel puissent gérer les différences.

  • Si le fichier peut être volumineux, ou s'il existe des sections de celui-ci que les gens voudront peut-être ignorer pour une raison quelconque, assurez-vous qu'il existe une bonne façon de le faire. XML, JSON et la plupart des autres formats de texte sont particulièrement terribles pour cela, car ils forcent le lecteur à analyser toutes les données entre l'élément de début et de fin même s'ils ne s'en soucient pas. EBML est un peu mieux car il stocke la longueur des éléments, vous permettant de sauter jusqu'à la fin. Si vous créez un format binaire personnalisé, il existe une conception assez courante où vous stockez un identifiant de bloc et une longueur comme première chose dans l'en-tête, puis le lecteur peut ignorer le bloc entier.

  • Stockez toutes les chaînes dans UTF-8.

  • Si vous vous souciez de l'extensibilité à long terme, stockez tous les entiers sous une forme de longueur variable.

  • Les sommes de contrôle sont agréables car elles permettent au lecteur d'interrompre immédiatement les données non valides, au lieu de pénétrer potentiellement dans des sections du fichier qui pourraient produire des résultats déroutants.

Trejkaz
la source
+1 pour m'avoir fait réaliser que je ne suis pas la seule personne à penser que json est une abomination d'un format.
RubberDuck
Pourquoi la haine pour json? Placez simplement une chaîne connue à un emplacement connu pour identifier le format. Problème résolu.
Esben Skov Pedersen
Ce n'est pas parfait, mais il fonctionne parfaitement avec javascript, plus rapide à analyser que XML et de plus petite taille, et toujours lisible par l'homme.
corylulu
1
"Pourquoi la haine pour JSON?" Pas de support pour les commentaires lisibles par l'homme, l'échappement de merde d'Unicode, et une syntaxe étrange m'obligeant à citer les clés même si elles ne contiennent jamais d'espaces. De plus, l'impossibilité habituelle d'étendre les choses parce que personne n'a pensé à l'espace de noms ... au moment où vous résolvez celui-ci, vous vous retrouvez avec quelque chose qui a l'air encore pire que XML en premier lieu, tout pour quoi, l'avantage d'éviter un certain angle supports?
Trejkaz
Oui, mais comme pour tout ce qui concerne la programmation, utilisez le bon outil pour le travail. Il existe des applications où XML est meilleur que JSON et vice versa.
corylulu
4

Eh bien, il arrive que ce que vous décrivez soit une très mauvaise approche. Cela suppose que lorsque vous dites «sérialiser», vous parlez d'utiliser la capacité d'un langage / framework à simplement prendre un objet et à sortir directement vers une sorte de flux binaire. Le problème est que les structures de classe changent au fil des ans. Serez-vous en mesure de recharger un fichier créé dans une version précédente de votre application si toutes vos classes changent dans une version plus récente?

Pour la stabilité à long terme d'un format de fichier, j'ai trouvé préférable de retrousser un peu vos manches maintenant et d'écrire spécifiquement vos propres méthodes de «sérialisation» / «streaming» dans vos classes. c'est-à-dire gérer manuellement l'écriture de valeurs dans un flux. Écrivez un en-tête au fur et à mesure de votre description qui décrit la version du format, puis les données que vous souhaitez enregistrer dans l'ordre dans lequel vous le souhaitez. Côté lecture, la gestion des différentes versions du format de fichier devient beaucoup plus facile.

Bien entendu, l'autre option est XML ou JSON. Pas nécessairement le plus grand pour le contenu lourd binaire, mais simple et lisible par l'homme ... un gros plus pour la viabilité à long terme.

GrandmasterB
la source
Je sérialise en utilisant protobuf-net ( code.google.com/p/protobuf-net ) qui est extensible. Mais vos points sont valides, cependant, je ne pense pas que ce soit une méthode de format de fichier qui soit à l'abri de cela.
corylulu
Ouais ... c'est pourquoi je dis parfois il suffit de se salir les mains et de gérer l'ordre dans lequel les données sont écrites et chargées manuellement.
GrandmasterB
L'application que je construis est loin d'être dynamique et a beaucoup trop de valeurs pour quelque chose comme ça.
corylulu
1
Plus l'application est compliquée, plus il est important d'avoir un contrôle très fin sur le format de fichier. Gardez à l'esprit que je ne dis pas que chaque classe ne devrait pas avoir sa propre sortie streamable ... juste que vous devriez contrôler cela pour chaque classe. Appelez ensuite ces routines.
GrandmasterB
Oui, j'ai mis en place des méthodes pour mettre à niveau les anciennes versions vers des versions modernes et j'ai une présentation très claire de la façon dont mes classes sont organisées. Je ne suis pas trop inquiet à ce sujet, mais je conviens que c'est important. J'y travaille depuis près d'un an, j'ai donc une vision assez claire du fonctionnement de sa structure.
corylulu
1

Je voudrais aussi aimer entendre des réponses à cette question des personnes avec des années plus d' expérience que moi - même.

J'ai personnellement implémenté plusieurs formats de fichiers pour mon travail, et je suis passé à l'utilisation d'un format de fichier XML. Mes exigences et le matériel avec lesquels j'interagis changent tout le temps, et on ne sait pas ce que je devrai ajouter au format à l'avenir. L'un des principaux avantages de XML est qu'il est semi-structuré . Pour cette raison, j'évite généralement la sérialisation XML automatique fournie par .NET car je pense qu'elle l'oblige à attendre un format exact.

Mon objectif était de créer un format XML qui permettrait d'ajouter de nouveaux éléments et attributs à l'avenir et que l'ordre des balises n'ait pas d'importance autant que possible. Si vous êtes sûr de pouvoir charger l'intégralité de votre fichier en mémoire, XPATH est probablement un bon choix.

Si vous traitez des fichiers particulièrement volumineux ou si, pour d'autres raisons, vous ne pouvez pas charger le fichier en même temps, il vous reste probablement à utiliser un XmlStreamReader et à rechercher des éléments connus et à revenir dans ces éléments avec ReadSubtree et à numériser à nouveau ...

Alan
la source
Cette réponse n'est pas très orientée vers le Q, ce site n'est pas destiné à être un forum de discussion mais est plutôt destiné à des questions / réponses non spéculatives. Vous avez fait valoir des points valables dans votre réponse qui pourraient être utilisés pour faire valoir pourquoi l'approche du questionneur est bonne ou non, mais elle n'est pas très ciblée. Veuillez concentrer votre réponse sur la question un peu plus, merci!
Jimmy Hoffa
@JimmyHoffa Bien que ma réponse a également appuyé la question de l'OP, j'a fait comprendre que je proposais un XML d'approche semi-structurée .. mais je ne vois ce que tu veux dire, je peux modifier
Alan