ファイル形式を作成する適切な方法はありますか?


12

C#.NETで記述したアプリケーション用に独自のファイル形式を作成して、保存情報を保存し、おそらくプロジェクトの資産を保存します。何らかの方法でこれを行う方法の基準はありますか?私は単純に行っていたSerializeバイナリに私のオブジェクトとどのようにファイルを解析するために私に言うだろうヘッダを作成します。これは悪いアプローチですか?


2
私は避けBinaryFormatterます。
CodesInChaos

3
選択したアプローチ(回答から)に関係なく、常に形式にバージョン番号を含めてください!あなたの質問はそれが変わるかもしれないことをすでに示唆しており、バージョン番号はあなたがbackwarsd互換性を持たなければならない場合あなたに多くの労力を節約します。
ヤンドッグゲン

フォーマットを適切に文書化することを忘れないでください
バジル・スタリンケビッチ

回答:


11

最も簡単な方法は、おそらくXMLSerializerクラスを使用して構造をXMLにシリアル化することです。おそらく、別個のヘッダーとボディ構造を作成する必要はないでしょうが、すべてのアセットをXMLにシリアル化します。これにより、独自のプログラムの外部でファイル構造を簡単に検査/編集することができ、簡単に管理できます。

ただし、ファイル構造が非常に複雑で、さまざまな種類のさまざまな種類のアセットが含まれているため、構造全体をXMLにシリアル化するのが面倒な場合はPackaging、C#のライブラリを使用して、各アセットを個別にシリアル化し、単一のパッケージにコンパイルすることを検討してください。これは、基本的に.docx、.xslx、.pptx、およびその他のOfficeファイル形式の構築方法です。


はい、私のプロジェクトはそれよりもはるかに複雑ですが、ライセンスされたコンテキストのフィールドにこれらを展開する可能性があるため、ユーザーの可読性を低くしようとしています。現在protobuf-net、データをシリアル化するために使用していますが、それは非常にうまく機能します。しかし、個別にピースをシリアル化する必要があるため、パッケージングライブラリで話していることは、私が必要としているように聞こえます。
corylulu

7
親愛なる神ではないXML-
ジェームズ

2
@Jamesええ、もちろんXMLには欠点があります。同じ理由で、ほとんどの場合、パッケージングとXMLを好みます。1。既存のフレームワークであるため、手間がかかりません。2.広く受け入れられている標準であるため、他のシステムでも簡単にサポートできます。3.人間が結果のファイルを調べて、シリアル化プロセスを確認するのは簡単です。
pswg

XMLには利点がありますが、XMLシリアライザーの使用が好きではないという利点があるためです。XMLを特定の形式にする必要があると思います。XMLは半構造化された形式であり、時間の経過とともにファイル形式を変更できますが、下位互換性や上位互換性も維持できます。過去に、私は独自のXML構文解析を作成しましたが、順序についての仮定を立てないように注意したり、将来気付かないタグがないようにしたりしました。XMLファイル全体をロードできる場合、XPATHはおそらく十分に機能します。それ以外の場合は、いくつかのより複雑なストリーム解析であなたの左
アラン


7

多くのファイル形式を解析しなければならなかった誰かから、私はこれについて異なる視点からほとんどの意見を持っています。

  • マジックナンバーを非常にユニークなものにして、他のフォーマットの人々のファイルフォーマット検出器がそれをあなたのものと誤認しないようにしてください。バイナリを使用する場合は、マジックナンバーのバイナリフォーマットの開始時に、ランダムに生成された8または16バイトを割り当てます。XMLを使用する場合は、ドメインに適切な名前空間を割り当てて、他の人と衝突しないようにします。JSONを使用している場合、神はあなたを助けます。たぶん誰かが今までにフォーマットの忌まわしい解決策を見つけ出したのかもしれません。

  • 後方互換性を計画します。ソフトウェアの新しいバージョンが違いに対処できるように、フォーマットのバージョン番号を何らかの方法で保存します。

  • ファイルが大きくなる可能性がある場合、または何らかの理由でスキップしたいセクションがある場合は、これを行うための良い方法があることを確認してください。XML、JSON、および他のほとんどのテキスト形式は、特に気に入らない場合でもリーダーが開始要素と終了要素の間のすべてのデータを解析することを強制するため、特にひどいです。EBMLは要素の長さを保存し、最後までスキップできるため、いくぶん優れています。カスタムバイナリ形式を作成する場合、ヘッダーに最初にチャンク識別子と長さを格納し、リーダーはチャンク全体をスキップできるという非常に一般的な設計があります。

  • すべての文字列をUTF-8で保存します。

  • 長期的な拡張性が必要な場合は、すべての整数を可変長形式で保存してください。

  • チェックサムは、混乱する結果を生成する可能性のあるファイルのセクションにステップインするのではなく、無効なデータでリーダーが即座に中止できるため、便利です。


+1は、jsonが形式の憎悪であると考える唯一の人ではないことを認識させてくれました。
ラバーダック

JSONが嫌いなのはなぜですか?既知の文字列を既知の場所に配置して、形式を識別します。問題が解決しました。
エスベンスコフペダーセン

完全ではありませんが、javascriptとシームレスに動作し、XMLよりも解析が速く、サイズが小さく、人間が読める形式です。
-corylulu

1
「なぜJSONが嫌いなのか?」人間が読めるコメント、Unicodeのがらくたのエスケープ、および空白が含まれていないにもかかわらずキーを引用する必要がある奇妙な構文はサポートされていません。さらに、名前空間について誰も考えなかったため、物事を拡張することができない通常のこと...それを解決するまでに、最初はXMLよりもさらに悪く見えるものになります。ブラケット?
-Trejkaz

ええ、しかし、プログラミングに関するすべてのことと同様に、仕事に適したツールを使用してください。XMLはJSONよりも優れているアプリケーションがあり、その逆も同様です。
corylulu

4

さて、あなたが説明することは非常に悪いアプローチになることがあります。これは、「シリアル化」と言うとき、オブジェクトを取得して何らかのバイナリストリームに直接出力する言語/フレームワークの機能を使用することについて話していることを前提としています。問題は、クラス構造が長年にわたって変化することです。すべてのクラスが新しいクラスで変更された場合、アプリの以前のバージョンで作成されたファイルを再ロードできますか?

ファイル形式の長期的な安定性を確保するために、スリーブを少しロールアップし、クラス内で独自の「シリアライズ」/「ストリーミング」メソッドを具体的に記述する方が良いことがわかりました。つまり、ストリームへの値の書き込みを手動で処理します。フォーマットバージョンを説明するヘッダーを記述し、必要なデータを必要な順序で保存します。読み取り側では、ファイルフォーマットの異なるバージョンの処理が非常に簡単になります。

もちろん、他のオプションはXMLまたはJSONです。バイナリの重いコンテンツには必ずしも最適ではありませんが、シンプルで人間が読める形式です...長期的な実行可能性には大きなプラスです。


拡張可能なprotobuf-net(code.google.com/p/protobuf-net)を使用してシリアライズしています。しかし、あなたのポイントは有効ですが、それらがこれに影響されないファイル形式の方法であるとは思いません。
-corylulu

うん...それは私が時々あなたがあなたの手を汚して、データが手動で書き込まれ、ロードされる順序を処理する必要があると言う理由です。
GrandmasterB

私が作成しているアプリケーションは、動的とはほど遠いものであり、そのようなものにはあまりにも多くの価値があります。
corylulu

1
アプリケーションが複雑になるほど、ファイル形式を非常に細かく制御することが重要になります。各クラスが独自のストリーミング可能な出力を持つべきではないと言っているのではないことに注意してください...クラスごとにそれを制御する必要があるだけです。次に、これらのルーチンを呼び出します。
GrandmasterB

ええ、レガシーバージョンを最新バージョンにアップグレードする方法があり、クラスのレイアウトが非常に明確にレイアウトされています。私はそれについて過度に心配していませんが、それが重要であることに同意します。私はこれにほぼ1年間取り組んでいるので、その構造がどのように機能するかについてかなり明確な見解を持っています。
corylulu

1

また、私は考えを愛する自分より年以上の経験を持つ人々からこの質問への答えを聞くために。

私は仕事のためにいくつかのファイル形式を個人的に実装しましたが、XMLファイル形式の使用に移行しました。私がやり取りする要件とハードウェアは常に変化するため、今後この形式に追加する必要があるものはわかりません。XMLの主な利点の1つは、半構造化されていることです。このため、.NETが提供する自動XMLシリアル化は、正確な形式を期待するように強制するため、通常は避けます。

私の目標は、将来的に新しい要素と属性を追加し、可能な限りタグの順序を無視できるXML形式を作成することでした。ファイル全体をメモリにロードできることが確実な場合は、おそらくXPATHが適しています。

特に大きなファイルを処理している場合、または他の理由でファイルを一度にロードできない場合は、おそらくXmlStreamReaderを使用して既知の要素をスキャンし、ReadSubtreeでそれらの要素に再帰してスキャンします...


この回答はQに向けられたものではありません。このサイトはディスカッション掲示板ではなく、非投機的なQ&Aを対象としています。回答者には、質問者のアプローチがなぜ良いのか、または良くないのかを示唆するために使用できる有効なポイントがいくつかありますが、あまり焦点が合っていません。質問に答えをもう少し集中してください、ありがとう!
ジミーホファ

@JimmyHoffa私の答えはまた、OPの質問をサポートしていましたが、私はそれは私がXML半構造化アプローチを示唆したことが明らかに作りました..しかし、私はあなたが何を意味するか見ています、私は編集することができます
アラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.