C言語でのシリアライズ

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
NBK

C言語でのシリアライズ

#1

投稿記事 by NBK » 12年前

お世話になります。

データ構造をバイナリデータで書き込む場合シリアライズをする必要がありますが、
C++やC#で解説しているホームページは見つかるんですが、C言語での解説しているホームページが見つからずに困っています。
"、、、"というサイトがあるようですが、見つかりませんでした。

C言語での解説サイトがなければ、Cでシリアライズを行う上での考え方や手順を、もしよろしければご教授お願い致します。

NBK

Re: C言語でのシリアライズ

#2

投稿記事 by NBK » 12年前

具体的に何がしたいかというと、構造体(int,char *文字列など)を書き込んだファイルからその構造体を読みこんで表示したいのです。
古いファイルから読み込むということです。
ポインタなどの関係で、うまく表示できないのはわかってるんですが、具体的にどうしたらいいのかがわかりません。
説明不足すみませんでした。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語でのシリアライズ

#3

投稿記事 by みけCAT » 12年前

一つの方法としては、bmpやwavのようなファイルフォーマットを自分で決めることです。
例えば、intなら下位のバイトから順に4バイト(自分の環境・目的に合った値)を書き込む、
文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む、
などです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

NBK

Re: C言語でのシリアライズ

#4

投稿記事 by NBK » 12年前

みけCAT さんが書きました:一つの方法としては、bmpやwavのようなファイルフォーマットを自分で決めることです。
例えば、intなら下位のバイトから順に4バイト(自分の環境・目的に合った値)を書き込む、
文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む、
などです。
この間はお世話になりました。ありがとうございました。

具体的にコードにしてみようと思ったんですが、てんでイメージが湧きませんでした・・・
そこで質問が2つあります。

1.下位のバイトから書き込む
2. 文字列なら最初に長さをintの方法で書き込み、その後に普通に書き込む

1. 下位のバイトっていうのは、メモリ上の・・・ですか・・・?
2. 長さを書きこむというのは、文字列の長さを書き込むという認識であってますか?
  それと長さを書き込んだあとに、文字列を書き込むんですよね?

bmpやwavのようなファイルフォーマットについて調べてみます。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語でのシリアライズ

#5

投稿記事 by みけCAT » 12年前

サンプルを作ってみました。

コード:

#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で殴ればいい!(死亡フラグ)

NBK

Re: C言語でのシリアライズ

#6

投稿記事 by NBK » 12年前

みけCAT さんが書きました:サンプルを作ってみました。
エラー処理をしていないので、適宜追加してください。
特に、readStr関数にバッファオーバーランの危険があります。
うおおお!わざわざめちゃめちゃありがとうございます!!!
これで勉強させていただきます!!
ありがとうございました!!!!

NBK

Re: C言語でのシリアライズ

#7

投稿記事 by NBK » 12年前

解決にチェック入れるの忘れてました・・・

閉鎖

“C言語何でも質問掲示板” へ戻る