- PR -

.NETでのバイナリファイル操作について

1
投稿者投稿内容
kakel
会議室デビュー日: 2008/11/06
投稿数: 7
投稿日時: 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ではこれが普通なんでしょうか?

皆さんはアプリケーションを作る上で、ファイルで管理しなければならないものが
でてきた場合、どのようにして、ファイルに落としたり吸い上げたりしていますか?

よろしくお願いします。
セラフ
ベテラン
会議室デビュー日: 2005/12/01
投稿数: 95
お住まい・勤務地: 東北の顔の形といえば
投稿日時: 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

このへんの連載は大変おせわになりました。
kakel
会議室デビュー日: 2008/11/06
投稿数: 7
投稿日時: 2008-12-03 23:33
お返事ありがとうございます。

.NETは通常XMLだったのですか。

XMLとは・・.NETにシステム移行を試行している段階とはいえ、知りませんでした。
いや、正直にいうとXMLなんて使わないだろうと思い込んでいました。
URLのXML入門の冒頭を見てみましたが、おおいに関係ありそうです。
これはちょっと試すのに時間がかかりそう・・・な気がしますので試行錯誤してみて、
後日返事を記載させて頂きたいと思います。

情報ありがとうございました。
kakel
会議室デビュー日: 2008/11/06
投稿数: 7
投稿日時: 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次元以上の配列のシリアライズは可能でしょうか?

よろしくお願い致します。
kakel
会議室デビュー日: 2008/11/06
投稿数: 7
投稿日時: 2008-12-04 18:16
追記です。ビューアの方の件ですが、
byte配列のみ文字化け?してしまいますね。
intやcharの1次元配列の場合はきちんとXMLをブラウザでみたら表示されました。
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2008-12-04 19:22
コード:
public int[][] iDat;


配列の配列ならXMLシリアライズしてくれます。
kakel
会議室デビュー日: 2008/11/06
投稿数: 7
投稿日時: 2008-12-05 12:38
お返事ありがとうございます。

当初の「バイナリファイル操作」からずいぶんと横道にはずれてしまいましたが・・・
検索できた方、申し訳ない;;

配列の配列でやるといけました。ありがとうございます。
ウーン。配列の配列(ジャグ配列)と多次元配列はメモリ配置の違いだけだと思って
いましたが・・・
単に多次元配列にした場合、アドレスが先頭しかきられていなくて、シリアライズの
際に2次元以降をとってこれないだけ?
配列の配列だとアドレス参照を2回することになるからシリアライズ可能。
と考えればつじつまが合う。・・・ような気がします。

これだと4次元とか添え字の多いもののメンテが手間ですね〜;;
変数がたくさんあればなおさら・・・
多次元配列を使用すること自体が.NETの流儀ではないのか・・・

開発にあたり、以下の定義で望もうという結論に達しつつあります。
・デバッグ効率を考えて、テキスト形式(XML含む)のファイル保存にする。
・ファイルに保存する際のみはデバッグ効率の悪いbyte配列は使用禁止にする。
 (これでビューアはブラウザで十分)
・2次元配列以上の配列を禁止([2][5]ならアクセッサを用意して2X+Yみたいにする)

一旦、解決とさせて頂きますが、今後の為にと、もう少しおつきあい下さい。
考え方が違い、私はこうしていますよ。とかありましたら情報お待ちしています。
1

スキルアップ/キャリアアップ(JOB@IT)