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 Serialize
mes objets en binaire et créer un en-tête qui me dirait comment analyser le fichier. Est-ce une mauvaise approche?
c#
.net
file-structure
corylulu
la source
la source
BinaryFormatter
.Réponses:
La méthode la plus simple consiste probablement à sérialiser votre structure en XML à l'aide de la
XMLSerializer
classe. 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
Packaging
bibliothèque en C # . C'est essentiellement ainsi que sont construits les fichiers .docx, .xslx, .pptx et autres formats de fichiers Office.la source
protobuf-net
pour 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.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.
la source
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.
la source
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 ...
la source