C#初心者です。

バイナリファイルをダンプしてイメージヘッダ等を構造体に入れて
各フィールド単位で操作したいのですが、最も簡単な方法はありますか?

このQ&Aに関連する最新のQ&A

A 回答 (3件)

MSDNに目を通しましょう。


全部書いてありますよ。


C#を2、3年ほど書いてないのでなんとなくです。


public class BITMAPFILEHEADER
{
public ushortbfType;
public uintbfSize;
public ushortbfReserved1;
public ushortbfReserved2;
public uintbfOffBits;

public void Read(BinaryReader b)
{
bfType= b.ReadUInt16();
bfSize= b.ReadUInt32();
bfReserved1= b.ReadUInt16();
bfReserved2= b.ReadUInt16();
bfOffBits= b.ReadUInt32();
};

public void Write(BinaryWriter b)
{
b.Write(bfType);
b.Write(bfSize);
b.Write(bfReserved1);
b.Write(bfReserved2);
b.Write(bfOffBits);
}
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
見よう見まねでクラスを作って試してみたら結構簡単に出来ました。
こちらの方がややこしくなくていいですね。しかも想定外のC#での初自作クラスも経験できたのでよかったです。

でもMSDNは初心者にはとっつきにくいです。でももっとよく調べるよう心がけます。
どうもありがとうございました。
この質問はこれで打ち切りにいたします。
回答してくださった両名の方々ありがとうございました。

お礼日時:2009/05/28 22:57

メモリを一括で読み込んでマッピングでできたほうが簡単そうには見えますけども。


BinaryReaderで、構造体に素直に読み込むのがいいのでは?
    • good
    • 0
この回答へのお礼

こんにちは、BinaryReader を調べたのですが、VBのサンプルしか出てこなかったのでうまくイメージできません。
この方法だとunsafeでなくもっと簡単に出来るのでしょうか?

お礼日時:2009/05/27 20:48

 こんにちは。


 C言語等に良く有る、構造体のポインタに向かってfread()する様な感じと言う事でしょうか。

 以下のURLに、配列や構造体をポインタにキャストしてコピーしているコード等が色々と記載されています。
 http://d.hatena.ne.jp/Schima/20090512/1242139542

 上記を参考に、以下を試してみましたが、ちゃんと出来る様です。ソリューションの設定にある「アンセーフコードの許可」にチェックを入れて下さい。
 
//19バイトの構造体
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct PERSON
{
unsafe public fixed byte pszName[16];//名前
public byte fAge;//年齢
public ushort wAddress;//住所番号
}

private void Form1_Load(object sender, EventArgs e)
{
//バイナリファイルオープン
System.IO.FileStream fileStream = new System.IO.FileStream("test.bin", System.IO.FileMode.Open);
int fileSize = (int)fileStream.Length;

//ファイルからバッファにデータを吸い上げる
byte[] buffer = new byte[fileSize];
fileStream.Read(buffer, 0, fileSize);

//バッファから構造体に向かってメモリコピー
PERSON person = new PERSON();
unsafe
{
Marshal.Copy(buffer, 0, new IntPtr(&person), fileSize);
}

fileStream = null;
}
    • good
    • 0
この回答へのお礼

こんな漠然とした質問に回答ありがとうございます。
やりたかったのは、まさにこの通りです。

以下のような感じで出来ることを確認できました。

public struct sImageHeader
{
// 全部で20byte
unsafe public fixed byte Machine[2];
unsafe public fixed byte NumberOfSections[2];
unsafe public fixed byte TimeDateStamp[4];
... 略
}

byte[] buffer = new byte[20];
fileStream.Read(buffer, 0, 20);


sImageHeader sih = new sImageHeader();
unsafe
{
Marshal.Copy(buffer, 0, new IntPtr(&sih), 20);
}

構造体のメンバをstring型に入れなおそうとすると、unsafe領域でないと駄目みたいなことを言われました。
unsafe ということで色々制約があるようですね、もっと勉強します。

どうもありがとうございました。

お礼日時:2009/05/27 20:45

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC#で構造体の配列を持った構造体を使いたいのですが

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します
となり

fixed をつけると

固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double

となってしまいます

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するに...続きを読む

Aベストアンサー

C# では、配列は「単なる連続したメモリ領域」ではなくて「添字によってオブジェクトを格納できるオブジェクト」であることに注意しなくてはいけません。つまり、C では配列は一種の構造体でしたが、C# では配列は参照型のオブジェクトです。
よって、C のように予めサイズを固定しておくということは基本的にできません。配列の大きさは配列のインスタンスが作られるときに動的に決まります。

C# では、参照型のオブジェクトを構造体のメンバにすることはあまりありません。null 値の扱いが面倒だからです。
また、C# では構造体の大きさは大きくとも 20 バイト程度までにします。C# では基本的に「構造体へのポインタ」はありません。巨大な構造体をそのまま扱うのはメモリの使い方の観点からいって非効率的です。

今回の件では、構造体ではなくクラスにするのがよいかと思われます。

QC#でバイナリデータをテキストフォームへ表示させるには?

C#でバイナリデータをテキストフォームへ表示させるには?

C#でバイナリファイルをテキストへ変換するツールを作成しています。
バイナリデータを配列へ格納し、その配列をテキスト変換してテキストフォームへ出力させるという処理を作成したいのですが、どうすれば良いのかどうしてもわかりません。

どのようなコードをどのようにして書けばよいのか、ご教示いただけないでしょうか。
よろしくお願いします。

(ちなみにC#を始めて1週間ほどです)

Aベストアンサー

下記のURLご参照ください。

参考URL:http://yellow.ribbon.to/~tuotehhou/index.php?CSharp0001

QC言語で構造体のメンバを簡単に出力する方法ありますか?

いつもお世話になっています。

C言語の質問です。
単体テストログを取るために、
“関数Aをコールする前後で、関数Aに引数として渡す構造体のメンバをすべて”printf(もしくはfprintf)で出力して比較確認しなければならないのですが、

構造体のメンバが250とか、150とかあり、メンバ名もxxx_01,xxx_02などのようにエクセルなどで簡単に加工して作れるものではないので、いちいちメンバ名を指定しなければならないのでとても大変です。

オブジェクト指向言語なら、for each文とかでオブジェクトのメンバを簡単に取り出せるのでしょうが(間違っているかもしれません・・・)、C言語で構造体のメンバを、for文などのループを使って簡単に出力できる方法はないでしょうか?

メンバの型は、一定ではなく、char、int、double、別の構造体のポインタ型(これは出力しなくて良い)と混在しています。メンバが全て同一の型ならポインタで構造体の先頭アドレスからsizeof(メンバの型)の分インクリメントしていけば出力できそうな気もしますが、メモリ上に連続して確保されるのかも私にはわからないので困っています。

enumで列挙して・・・というのも調べてみましたが、応用は出来ないようでした。

どなたか、地道にメンバ名を書いて出力する以外の方法をご存知の方、いらっしゃいましたらお知恵をお貸しください。
よろしくお願いいたします。
※説明不足の点がありましたら補足いたします。

いつもお世話になっています。

C言語の質問です。
単体テストログを取るために、
“関数Aをコールする前後で、関数Aに引数として渡す構造体のメンバをすべて”printf(もしくはfprintf)で出力して比較確認しなければならないのですが、

構造体のメンバが250とか、150とかあり、メンバ名もxxx_01,xxx_02などのようにエクセルなどで簡単に加工して作れるものではないので、いちいちメンバ名を指定しなければならないのでとても大変です。

オブジェクト指向言語なら、for each文とかでオブジェクトのメンバを...続きを読む

Aベストアンサー

コードを書かないという方向性の提案を一つ。
デバッガに構造体の内容を出力させるというのはどうでしょうか。

struct {
int a;
char *b;
double c;
}
という型を持つ変数xがあったとして、gdbでは下記のような出力が得られます。
(gdb) print x
$1 = {
a = 123,
b = 0x2fd0 "ABC",
c = -9876.5
}

QC# インスタンスの破棄

C#でインスタンスの破棄を明示的に行いたいのですが、
実際の開発現場では、どのように行っているのでしょうか?

自分で調べると「ガベージコレクタ」が暗黙的に行っているようですが明示的には行わないのが普通なのでしょうか?
もしくは、「Dispose」を使用して明示的に行うのが普通なのでしょうか?

実際に開発されている方からすると簡単な事かもしれませんが教えて頂けると助かります。

以上ですが、よろしくお願いいたします。

Aベストアンサー

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム系のオブジェクトや
データベースとのコネクションなどです。これは開発会社や
開発チーム、案件によって若干違っていて、徹底するところや
適当なところもあります。個人的には徹底したい派ですが。。。

ガベージコレクションが発生するとプログラムの実行動作が
遅くなり、また瞬間的に大きな負担がかかることがあります。
そのため全てをガベージコレクタに任せるのではなく、
明示的に開放できるもの、メモリを大量に消費するものは
その都度、適切に開放していくことで処理効率が良くなります。

プログラミング関連の調べ物で、サンプルソース等を見ることが
あるかと思います。この時サンプルで明示的に開放していたら、
それは明示的に開放したほうが良いもの、と思いましょう。
これだけでもステップアップになりますね。

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム...続きを読む

QC#で共有変数の定義をするには

C#で共有変数の定義をするには、どうしたらよいでしょうか。具体的には、起動パラメータで、任意の文字列(3~4バイト)を渡して、C#アプリケーションを、起動し、プログラムの任意の場所で、そのパラメータを参照したいと考えています。起動パラメータの受け取りは、できるのですが、そのパラメータを、プログラムのどこからも参照できる領域(ここの定義方法が不明)に格納するには、どうしたらよいでしょうか。(2重起動を許す前提です。実行時に1つの目のプログラムにはパラメータ"XYZ"を渡し、2つ目のプログラムを起動時にはパラメータ"ABCD"を渡し、その値により、プログラムの動作を制御したいと思っています)
Windows-xp visual-studio2008 C#でwindowsアプリケーションを作成しています。

Aベストアンサー

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }
    // ここに記述
    static public string strArg = null;
  }
}

メインクラスのメンバーとしてスコープが有効な場所に記述します

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(n...続きを読む

Qファイルから読み込んだデータを構造体に格納できますか?

1レコード19バイトのファイルを
読み込む処理を行っています。

地区名10バイト
県名8バイト
改行1バイト

このデータをdouken(構造体)に格納したいのですが
>while (fgets(dou,19,fp) != NULL){
で、エラーになってしまいます。

どのようにしたら
ファイルから読み込んだデータを
構造体に格納できますか?


#include<stdio.h>
#include <stdlib.h>

struct douken {
char tiku[10];
char ken[8];
}

main(void){

FILE *fp;
struct douken dou[100];
int i;

fp = fopen("ex3.fil","rb");

if ( fp == 0 ){
printf("can't open\n");
exit(1);
}

while (fgets(dou,19,fp) != NULL){



1レコード19バイトのファイルを
読み込む処理を行っています。

地区名10バイト
県名8バイト
改行1バイト

このデータをdouken(構造体)に格納したいのですが
>while (fgets(dou,19,fp) != NULL){
で、エラーになってしまいます。

どのようにしたら
ファイルから読み込んだデータを
構造体に格納できますか?


#include<stdio.h>
#include <stdlib.h>

struct douken {
char tiku[10];
char ken[8];
}

main(void){

FILE *fp;
struct douken dou[100];
int i;

...続きを読む

Aベストアンサー

>>while (fgets(buffer,20,fp) != NULL){
>と、するということですか?
>その場合、
>ここのサイズは必ず4の倍数になるということですよね?
構造体を直接扱うと、アーキテクスチャやコンパイラ依存してしまいます。
32bit機なら4byteですし、16bit機なら2byte。64bit機なら8byteです。
また、コンパイラの設定によってもどのように確保されるかまったく分からないのです。
一度バッファに蓄えてからmemcpyでコピーする方が安全ですし、可搬性があります。
C言語では\0を文字列の終端文字として使用しているので、10文字格納したいなら11byte確保する必要もあります。
簡単に修正してみました。

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef struct douken_ {
char tiku[11];
char ken[9];
} douken;

int main(void){
FILE *fp;
douken dou [100];
char buff [18 /* douken */ + 1 /* LF(\n) */ + 1 /* \0 */];
int i;
i = 0;

fp = fopen("ex3.fil","rb");

if ( fp == 0 ){
printf("can't open\n");
exit(1);
}

// douを\0で埋める
memset (dou , '\0' , sizeof dou);

// 一度バッファに格納
while (fgets(buff,sizeof buff,fp) != NULL){
// memcpy関数でコピー
memcpy(&dou[i],buff,10);
memcpy(&dou[i],buff+10,8);

// 構造体配列より大きなファイルを開いたときの配慮
if (i == 99) break;
i++;
}

return 0;
}

>>while (fgets(buffer,20,fp) != NULL){
>と、するということですか?
>その場合、
>ここのサイズは必ず4の倍数になるということですよね?
構造体を直接扱うと、アーキテクスチャやコンパイラ依存してしまいます。
32bit機なら4byteですし、16bit機なら2byte。64bit機なら8byteです。
また、コンパイラの設定によってもどのように確保されるかまったく分からないのです。
一度バッファに蓄えてからmemcpyでコピーする方が安全ですし、可搬性があります。
C言語では\0を文字列の終端文字として使用して...続きを読む

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC#.net Define文

C#.net でプログラムを作成中です。

C++では定数等を#defineで定義していましたが、C#ではDefineは無いとの事です。

C#でC++の#Define に相当する事は出来ないのでしょうか。
やりたい事は 長い同じコマンドを別の文字で代替する事です。

もしC#に#Define文があったとして、以下の様な事を行いたいのです。

#Define NL printf("\n");

NL

このコーディングが展開した時、
 pritf("\n");
と展開される。

この様な事が出来る文をご存知の方、若しくはこの様な事は出来ないと言う事をご存知の方、よろしく御回答下さい。

よろしくお願い致します。

Aベストアンサー

定数の定義では無く、どちらかというと「マクロ」としての機能をC#で使いたいと言うことですね。

結論から言うと、C++の#defineを使ったマクロは、C#では利用できません。
このようなマクロはバグの元になりやすいため、意図的にC#から削られています。

もし、汎用的に使えるような引数を渡したい…という事であれば、ジェネリックなどを使うと良いですよ。


ちなみに、単純な定数の定義であればconst、列挙体であればenumを使って定義できます。

Q複数桁10進数の*桁目だけを抽出したい

タイトルがすべてと言えてしまうのですが、
例えば、int宣言された"4287"(この値は変動します)という数値があったとして、1桁目の"7"だけを別の変数へ引き抜きたいのですが、その場合にはANDによるマスク処理による演算で処理可能なのでしょうか?
また、他に良い方法などありましたら教えていただけますでしょうか?

Aベストアンサー

★10進数ですので AND は使えませんね。
・簡単なサンプルを載せますので読み取って下さい。

サンプル1:
int value = 4287;
int a[ 4 ];

a[0] = (value % 10); value /= 10; // 1桁目を取り出す
a[1] = (value % 10); value /= 10; // 2桁目を取り出す
a[2] = (value % 10); value /= 10; // 3桁目を取り出す
a[3] = (value % 10); value /= 10; // 4桁目を取り出す

サンプル2:
int value = 4287;
int a;

a = (value % 10);
value -= a;

value → 4280
a → 7
になります。

QC#でフォームのオブジェクト名を変数名で指定

C#でフォームのオブジェクトを変数名で指定するにはどうしたらよいでしょうか?

例えば、フォームにラジオボタンrdo0~rdo9と、
それぞれに対応するテキストボックスtxt0~txt9が用意されている状態で、
rdo1がチェックされていたらtxt1に"OK"と表示、
rdo2がチェックされていたらtxt2に"OK"と表示・・・
といったことをfor文で実現する場合どのようにしたらよいでしょうか?
変数をオブジェクト名として認識させるための方法がわかりません。

どなたかご教授願います。


*********************************************
for(int i=0;i<10;i++)
{
 rdoname = "rdo" + i;
 txtname = "txt" + i;

 if((何らかの処理?)(rdoname).checked)
  (何らかの処理?)(txtname).txt = "OK";
}

****************************************
↑この、オブジェクトとして認識する為の「何らかの処理」部がわかりません。

C#でフォームのオブジェクトを変数名で指定するにはどうしたらよいでしょうか?

例えば、フォームにラジオボタンrdo0~rdo9と、
それぞれに対応するテキストボックスtxt0~txt9が用意されている状態で、
rdo1がチェックされていたらtxt1に"OK"と表示、
rdo2がチェックされていたらtxt2に"OK"と表示・・・
といったことをfor文で実現する場合どのようにしたらよいでしょうか?
変数をオブジェクト名として認識させるための方法がわかりません。

どなたかご教授願います。


************************...続きを読む

Aベストアンサー

参考URL参照。

参考URL:http://dobon.net/vb/dotnet/control/findcontrolbyname.html


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報