お世話になります。
データ構造をバイナリデータで書き込む場合シリアライズをする必要がありますが、
C++やC#で解説しているホームページは見つかるんですが、C言語での解説しているホームページが見つからずに困っています。
"、、、"というサイトがあるようですが、見つかりませんでした。
C言語での解説サイトがなければ、Cでシリアライズを行う上での考え方や手順を、もしよろしければご教授お願い致します。
C言語でのシリアライズ
Re: C言語でのシリアライズ
具体的に何がしたいかというと、構造体(int,char *文字列など)を書き込んだファイルからその構造体を読みこんで表示したいのです。
古いファイルから読み込むということです。
ポインタなどの関係で、うまく表示できないのはわかってるんですが、具体的にどうしたらいいのかがわかりません。
説明不足すみませんでした。
古いファイルから読み込むということです。
ポインタなどの関係で、うまく表示できないのはわかってるんですが、具体的にどうしたらいいのかがわかりません。
説明不足すみませんでした。
Re: C言語でのシリアライズ
一つの方法としては、bmpやwavのようなファイルフォーマットを自分で決めることです。
例えば、intなら下位のバイトから順に4バイト(自分の環境・目的に合った値)を書き込む、
文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む、
などです。
例えば、intなら下位のバイトから順に4バイト(自分の環境・目的に合った値)を書き込む、
文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む、
などです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: C言語でのシリアライズ
この間はお世話になりました。ありがとうございました。みけCAT さんが書きました:一つの方法としては、bmpやwavのようなファイルフォーマットを自分で決めることです。
例えば、intなら下位のバイトから順に4バイト(自分の環境・目的に合った値)を書き込む、
文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む、
などです。
具体的にコードにしてみようと思ったんですが、てんでイメージが湧きませんでした・・・
そこで質問が2つあります。
1.下位のバイトから書き込む
2. 文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む
1. 下位のバイトっていうのは、メモリ上の・・・ですか・・・?
2. 長さを書きこむというのは、文字列の長さを書き込むという認識であってますか?
それと長さを書き込んだあとに、文字列を書き込むんですよね?
bmpやwavのようなファイルフォーマットについて調べてみます。
Re: C言語でのシリアライズ
サンプルを作ってみました。
エラー処理をしていないので、適宜追加してください。
特に、readStr関数にバッファオーバーランの危険があります。
#include <stdio.h>
#include <string.h>
#include <limits.h>
/*
FIXED_INT_SIZEを定義する場合(例: #define FIXED_INT_SIZE 4)
ファイルに書き込むintのサイズが固定になり、
環境依存しにくくなる
FIXED_INT_SIZEを定義しない場合
ファイルに書き込むintのサイズを自動調節するが、
環境依存しやすくなる
*/
/**
* int型の数値を1個ファイルに書き込む
* @param fp 対象のファイルポインタ
* @param val 書き込む数値
*/
void writeInt(FILE* fp,int val) {
int counter;
#ifdef FIXED_INT_SIZE
for(counter=0;counter<FIXED_INT_SIZE;counter++) {
#else
for(counter=INT_MAX;counter>0;counter>>=8) {
#endif
unsigned char nowData=val&0xFF;
val>>=8;
fwrite(&nowData,sizeof(unsigned char),1,fp);
}
}
/**
* NIL文字で終わる文字列を1個ファイルに書き込む
* @param fp 対象のファイルポインタ
* @param str 書き込む文字列
*/
void writeStr(FILE* fp,const char* str) {
int length=strlen(str);
writeInt(fp,length);
fwrite(str,sizeof(char),length,fp);
}
/**
* int型の数値を1個ファイルから読み込む
* @param fp 対象のファイルポインタ
*/
int readInt(FILE* fp) {
int counter;
int result=0;
int shiftLen=0;
#ifdef FIXED_INT_SIZE
for(counter=0;counter<FIXED_INT_SIZE;counter++) {
#else
for(counter=INT_MAX;counter>0;counter>>=8) {
#endif
unsigned char nowData=0;
fread(&nowData,sizeof(unsigned char),1,fp);
result|=(int)nowData<<shiftLen;
shiftLen+=8;
}
return result;
}
/**
* 文字列を1個ファイルから読み込む
* @param fp 対象のファイルポインタ
* @param strOut 読み込んだ文字列を格納するポインタ
*/
void readStr(FILE* fp,char* strOut) {
int length=readInt(fp);
fread(strOut,sizeof(char),length,fp);
strOut[length]='\0';
}
int main(int argc,char* argv[]) {
int testInt=65537;
char testStr[]="OpenMP is god! OpenMPI is evil!";
int testInt2=12345701;
int intRead=0;
char strRead[1024]={};
int intRead2=0;
FILE* fp;
fp=fopen("data.bin","wb");
if(fp==NULL)return 1;
writeInt(fp,testInt);
writeStr(fp,testStr);
writeInt(fp,testInt2);
fclose(fp);
puts("Data written");
printf("%d\n%s\n%d\n\n",testInt,testStr,testInt2);
fp=fopen("data.bin","rb");
if(fp==NULL)return 1;
intRead=readInt(fp);
readStr(fp,strRead);
intRead2=readInt(fp);
fclose(fp);
puts("Data read");
printf("%d\n%s\n%d\n",intRead,strRead,intRead2);
return 0;
}
特に、readStr関数にバッファオーバーランの危険があります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: C言語でのシリアライズ
うおおお!わざわざめちゃめちゃありがとうございます!!!みけCAT さんが書きました:サンプルを作ってみました。
エラー処理をしていないので、適宜追加してください。
特に、readStr関数にバッファオーバーランの危険があります。
これで勉強させていただきます!!
ありがとうございました!!!!