- - PR -
.NETでのバイナリファイル操作について
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2008-12-03 19:47
いつもお世話になっております。
以前、VB、VC++6.0で開発をしておりました。 今回VS2008を購入し、C#にて開発を行おうと、試行段階として色々試しておりました。 具体的には、C#のファイル操作に関して、みなさんに質問があります。 ●以前(VS6.0で)やっていたこと 2次元配列の入れ子(全体では4次元等)のint、char、double等さまざまなデータを VCの構造体(struct)を定義して、ファイルに一括で読み書き(ポインタ渡し)していました。 これをC#でやろうとしたら、調べたところ、下記の3点程度方法がみつかりました。 1.型ごとにBinaryReaderやBinaryWriterを使って1個ずつ読み書きする方法 (int32ならReadInt32()等) 2.一度byte型配列に格納してから、リード/ライトする この場合、MarshalAsを使って、配列等は合算のSizeConst=XXXで指定 PtrToStructureやStructureToPtrを使用して構造体へ変換(過去ログ参照) 3.using Microsoft.VisualBasicのFileSystemクラスを使用して FilePut/FileGetで読み書きする方法 2と3の場合、多次元配列の変数になると、配列の添え字を変更するのではなく、 SizeConstの値を変更しなければならず、変更の都度、計算して変更しなくては なりません。 また、.NETの流儀といいますか、わざわざ隠しているポインタを使用するのも どうかと思います。(.NETの流儀が本当にそうかは微妙ですけど) そうなると1のものしかなくなってくるわけですが、構造体(クラスでもいい)の 中身が変わってきた場合に、そこの処理をちまちま変更しなければなりません。 まぁ、ちまちまといってもforのループカウンタの数を変えたり、ReadCharと ReadInt32の順番をいれかえたりするだけでしょうけどね。 .NETではこれが普通なんでしょうか? 皆さんはアプリケーションを作る上で、ファイルで管理しなければならないものが でてきた場合、どのようにして、ファイルに落としたり吸い上げたりしていますか? よろしくお願いします。 | ||||
|
投稿日時: 2008-12-03 22:36
オブジェクトの情報をファイルに書き出すのであれば、.NETではシリアラズが最も一般的だと思います。XML形式や、バイナリ形式で書き出せたはずです。
http://www.atmarkit.co.jp/fdotnet/easyxml/easyxml09/easyxml09_01.html 後は、XMLやら型指定されたデータセットなどで保存しておいて、使いやすいように読み出しながら使用するとかでしょうか。 .NETは基本的にXMLが好きなようです XML関連のライブラリが充実しております。 http://www.atmarkit.co.jp/fdotnet/easyxml/index/index.html このへんの連載は大変おせわになりました。 | ||||
|
投稿日時: 2008-12-03 23:33
お返事ありがとうございます。
.NETは通常XMLだったのですか。 XMLとは・・.NETにシステム移行を試行している段階とはいえ、知りませんでした。 いや、正直にいうとXMLなんて使わないだろうと思い込んでいました。 URLのXML入門の冒頭を見てみましたが、おおいに関係ありそうです。 これはちょっと試すのに時間がかかりそう・・・な気がしますので試行錯誤してみて、 後日返事を記載させて頂きたいと思います。 情報ありがとうございました。 | ||||
|
投稿日時: 2008-12-04 17:13
けっこう時間がかかると思っていましたが、できました。
binaryformaterを使ってバイナリでシリアライズ、デシリアライズ共にできました。 ありがとうございました。 当初、調べていた時に以下をみつけて試していたのですが、 http://dobon.net/vb/dotnet/file/xmlserializer.html バイナリエディタでみた時に先頭データに変なデータが入っている。これは、フォーム とかの情報を格納しておくものだと、思い込んでしまったのが・・・ デシリアライズまでやってみるべきでした。 まぁ、あとは作ったファイルをExcelのVBAからも流用したりとか考えてたのもあり、 読むのが手間だと思ってたのもあります。 (Excelでも2007からはXMLのライブラリ充実?) でも、自分に遠回りしたからわかったこともあります。(といいきかせる。) 調べて思ったのですが、1バイトでも少ないファイルフォーマットでバイナリで 管理するという方法はもう古いもの扱いされているようですね。 容量の問題が昔はあったから、プログラマに好まれていたのがバイナリ形式のファイル だっただけみたいです。 容量を気にしなくてもよくなった今だからと改めて実感しました。 さてさて、話を戻します。 これってBinaryformatterを使わずに、テキスト形式(XML等)で保存しとけば、 デバッグの際も目に見えて、バイナリファイルを1バイトずつ追うような作業 からも離れ、エディタとかでみれればもっとデバッグ効率あがるかも。 XMLのコメントつければ、それが何なのかすぐわかりますよね〜。 って思ったのですが。byte[3]などの配列の場合、データを並べても、例えば、 <name>123456</name> となったら、 [0]=123, [1]=4, [2]= 56なのか [0]=12, [1]=34, [2]= 56なのかわからないか・・・ (ファイル内部自体はわかっているんでしょうが) こんなことを解消してくれるようなXML形式でもバイナリ形式でも[0]は123ですとか 見せてくれるビューアのようなものはあるのでしょうか? また、XML形式でもやってみました。 2次元intやbyte配列でシリアライズできず・・・(バイナリ形式ではいけた) こちらは、XmlSerializer(typeof(stTest))でInvalidOperationExceptionが スローされてしまいます。コンパイルはとおりますが、実行時にエラーとなります。 テストなので、バイナリでも使用したクラスを再利用しています。 定義したクラス [Serializable()] public class stTest { public byte[] uFlg = new byte[10]; public byte[] uNo = new byte[20]; public int [,] iDat = new int [10,8]; ※ public byte[,] uDat = new byte[20,3]; ※ } private void serializeSample() { stTest zTest = new stTest(); //(データ入力は省略) using (XmlTextWriter writer = new XmlTextWriter(@"パス", System.Text.Encoding.GetEncoding("Shift-JIS"))) { XmlSerializer slz = new XmlSerializer(typeof(stTest)); slz.Serialize(writer, zTest); } } クラスの※部分をコメントにすれば例外は発生しません。 XMLだと多次元はできないとか制約があるのでしょうか。 だらだらと書いてしまいましたが、簡潔には以下の2点です。 ●シリアライズしたファイルのビューアはあるのか ●XML形式でクラス内の2次元以上の配列のシリアライズは可能でしょうか? よろしくお願い致します。 | ||||
|
投稿日時: 2008-12-04 18:16
追記です。ビューアの方の件ですが、
byte配列のみ文字化け?してしまいますね。 intやcharの1次元配列の場合はきちんとXMLをブラウザでみたら表示されました。 | ||||
|
投稿日時: 2008-12-04 19:22
配列の配列ならXMLシリアライズしてくれます。 | ||||
|
投稿日時: 2008-12-05 12:38
お返事ありがとうございます。
当初の「バイナリファイル操作」からずいぶんと横道にはずれてしまいましたが・・・ 検索できた方、申し訳ない;; 配列の配列でやるといけました。ありがとうございます。 ウーン。配列の配列(ジャグ配列)と多次元配列はメモリ配置の違いだけだと思って いましたが・・・ 単に多次元配列にした場合、アドレスが先頭しかきられていなくて、シリアライズの 際に2次元以降をとってこれないだけ? 配列の配列だとアドレス参照を2回することになるからシリアライズ可能。 と考えればつじつまが合う。・・・ような気がします。 これだと4次元とか添え字の多いもののメンテが手間ですね〜;; 変数がたくさんあればなおさら・・・ 多次元配列を使用すること自体が.NETの流儀ではないのか・・・ 開発にあたり、以下の定義で望もうという結論に達しつつあります。 ・デバッグ効率を考えて、テキスト形式(XML含む)のファイル保存にする。 ・ファイルに保存する際のみはデバッグ効率の悪いbyte配列は使用禁止にする。 (これでビューアはブラウザで十分) ・2次元配列以上の配列を禁止([2][5]ならアクセッサを用意して2X+Yみたいにする) 一旦、解決とさせて頂きますが、今後の為にと、もう少しおつきあい下さい。 考え方が違い、私はこうしていますよ。とかありましたら情報お待ちしています。 |
1