No.5ベストアンサー
- 回答日時:
>mallocで取れるだけ領域を取ってそこからその
処理系や環境によりますがWindowsやLinuxの場合100Mぐらいは余裕でとれてしまいます。
>構造体の途中からfreadすることって可能でしょうか?
可能です。
memcpy( (char*)s+読み込んだバイト , pBuf , structSize - (読み込んだバイト) );
みたいな感じになります。
sizeを読み込んでから切れる場合と、sizeの前で切れる場合があるので
sizeの前で切れた場合は次のバッファを読み込んでから構造体のサイズを確定する処理
をする必要があるでしょう。
ただ構造体のalignmentには注意してください。
例えば
typedef struct _S{
char a;
short b;
}S;
の場合3バイトとは限りません。コンパイラの設定によっては
paddingの部分で切れる可能性も考慮する必要があります。
No.7
- 回答日時:
実装例: #3のソースを改良したバージョン(解説は省略します、実際のテストは行っていません)
/* 1つの可変長・構造体データの最大バイト数(最低でも構造体サイズ+文字配列サイズ以上) */
#define MAX_SIZE (1024 * 1024) ←可能な限り大きいサイズで読み込む回数を減らせます
/* 可変長構造体のファイルからcsv形式のファイルへ出力 */
void FuncRead( FILE *fp, FILE *fo )
{
size_t size; /* 読み込んだバイト数 */
char *buff; /* 読み込むバッファ領域(先頭位置) */
char *last; /* 読み込むバッファ領域(最終位置) */
char *seek; /* 参照したバッファ位置(現在位置) */
構造体(仮) *data; /* 参照する構造体へのポインタ */
if ( (buff = malloc(MAX_SIZE)) != NULL ){
while ( (size = fread(buff,1,MAX_SIZE,fp)) != 0 ){
last = (buff + size);
seek = (buff);
data = (構造体(仮) *)seek;
while ( (data->str + data->size - 1) < last ){
FuncWrite( data, fo ); ←構造体(仮)のデータを出力させる関数
seek += (sizeof(構造体(仮)) + data->size - 1);
data = (構造体(仮) *)seek;
}
if ( feof(fp) ){
break;
}
fseek( fp, -(size_t)(last - seek), SEEK_CUR ); ←ファイルポインタを戻る
}
free( buff );
}
}
/*
●引数
(1)入力ファイルのポインタを fp で指定
(2)出力ファイルのポインタを fo で指定
●その他
void FuncWrite( 構造体(仮) *data, FILE fo );
●注意
・1つの可変長・構造体データは、構造体サイズ+data->size-1ですよ。
・文字配列が文字列ならば、NULL文字分を考えて上記ソースの-1は削除しましょう。
*/
改良版ありがとうございます。
とりあえず内容を見てみました。
このソースの処理は、
> while ( (data->str + data->size - 1) < last ){
> fseek( fp, -(size_t)(last - seek), SEEK_CUR ); ←ファイルポインタを戻る
のところを見る限り構造体全体が読めなかったら
ファイルポインタを読めなかった構造体の最初に戻って読み直すという
処理をしているみたいですね。
構造体の途中から読むということもしないので無難かもしれませんね。
No.6
- 回答日時:
#5です。
追記です。例えば1024バイトのバッファで何回も読み込んでいくような方式を考えた場合に
構造体のsizeが5000バイトを超えるようなパターンもありますね。
この回答への補足
あ、多分これは大丈夫です。
10Mぐらいのバッファで構造体もバッファより大きいものは存在しない予定なので・・・
それとついでの質問なのですが、
mallocで取れるバッファのサイズを調べる関数とかあるのでしょうか?
No.3
- 回答日時:
最初にftellでファイルサイズを取得しmallocで領域を確保し
freadで全部メモリーに読み込めばいいのでは?
そうすれな読み込み回数は1回で済みますから。
ファイルサイズが大きくmallocで確保できないような連続領域が必要なら
無理ですが。
簡単に書くとこんなかんじでしょうか。(なんのエラー処理もしていません)
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct _STRUCT
{
char c1,c2;
float f1,f2;
double d;
int size;
char str[1];
}STRUCT;
int main()
{
size_t structSize;
STRUCT* s;
char* pBuf;
size_t FileSize;
size_t ReadSize = 0;
FILE* fp = fopen("hoge.dat","rb");
fseek(fp,0,SEEK_END);
FileSize = ftell(fp);
printf("FileSize=%u\n",FileSize);
fseek(fp,0,SEEK_SET);
pBuf = (char*)malloc(FileSize);
fread(pBuf,FileSize,1,fp);
fclose(fp);
while( ReadSize < FileSize ){
structSize = sizeof(STRUCT) - sizeof(char) + ((STRUCT*)pBuf)->size;
s = (STRUCT*)malloc(structSize);
memcpy( s , pBuf , structSize );
printf("%s\n",s->str);
free( s );
ReadSize += structSize;
pBuf+=structSize;
}
free(pBuf);
}
この回答への補足
ありがとうです。
自分のしたかったことに近いです。
ですがファイルサイズがでかくなることも想定しているので
mallocで取れるだけ領域を取ってそこからその処理をして、
領域の最後に達したらファイルから読み直すという処理をつけたいと思ってます。
ですがそうした場合、構造体の途中までしか読めていない状況が発生すると思っています。
その場合欠けた部分より後はfreadで読み込む処理を入れなくてはいけない気がします。
ですが構造体の途中からfreadすることって可能でしょうか?
No.2
- 回答日時:
typedef struct 構造体(仮) {
char c1, c2;
float f1, f2;
double d;
int size;
chear str[1];
} 構造体(仮);
の形だと (構造体タグって必要?), 実際に使うにはこの構造体に対して malloc しないといけないんだけどその辺は OK? まあいいとして, 基本的には
0.仮にデータを保存しておく構造体を用意する
1.size まで fread
2.その size に従って構造体を malloc する
3.size のところまで memcpy
4,size の分だけ fread
の順. 今の ISO C なら str を
char str[];
で宣言できて, この場合には
{
構造体(仮) dummy, *data;
fread(&dummy, sizeof dummy, 1, fp);
data = malloc(sizeof *data + dummy.size);
memcpy(&dummy, data, sizeof dummy);
fread(data->str, 1, data->size, fp);
}
くらいになるかと.
1の方の方法をソースで書いてくれたのですね。
ありがとうです。
・・・ですが1の方のところで書いたとおりその方法は考えてはいました。
もう少し詳しく書いておくべきでしたね、すみません。
No.1
- 回答日時:
私だったら、
void hoge( int fd ) {
構造体(仮) kari;
int sz, cc;
char *str;
sz = (int) ( (void*) &kari - (void*) &kari.str );
cc = read( fd, &kari, sz );
/* cc をチェック */
str = (char*) malloc( kari.size );
/* str をチェック */
cc = read( fd, str, kari.size );
/* cc をチェック */
}
てな感じでしょうか。要は構造体(仮)のsizeまで最初に読みこんでから、size を見て、文字列を読むだけです。
ファイルを読み込む回数ですが、Linux とか最近のOSではメモリにキャッシュされるので、回数は昔ほど気にしなくても大丈夫です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
これまでで一番「情けなかったとき」はいつですか?
これまでの人生で一番「情けない」と感じていたときはいつですか? そこからどう変化していきましたか?
-
【大喜利】【投稿~1/31】『寿司』がテーマの本のタイトル
【お題】 『寿司』がテーマの本のタイトルを考えてください
-
みんなの【マイ・ベスト積読2024】を教えてください。
積読、ついついしちゃいませんか?そこでみなさんの 「2024年に買ったベスト積読」を聞きたいです。
-
あなたの人生で一番ピンチに陥った瞬間は?
これまでの人生で今振り返ると「あの時、1番ピンチだったなぁ...」という瞬間はありますか?
-
今から楽しみな予定はありますか?
いよいよ2025年が始まりました。皆さんには、今から楽しみにしている予定はありますか?
-
ファイルから読み込んだデータを構造体に格納できますか?
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・【大喜利】【投稿~1/31】『寿司』がテーマの本のタイトル
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・【大喜利】【投稿~1/20】 追い込まれた犯人が咄嗟に言った一言とは?
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・【大喜利】【投稿~1/9】 忍者がやってるYouTubeが炎上してしまった理由
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
動的メモリの初期化方法について。
-
c言語でポインタ変数を用いた配...
-
文字列str内の全ての数字を...
-
const char* s1とただのchar s1...
-
csvファイルを構造体に格納した...
-
文字型配列に格納した空白の切捨て
-
C++17で、unsigned char * 配列...
-
SubStringの使い方について
-
ASCIIコードへの変換方法
-
szとlpszの違い
-
コマンドライン引数 *argv[]は...
-
char型にint型の数値を代入する。
-
構造体のメンバーの静的なサイ...
-
メモリを0クリアする方法について
-
fgetc( )の戻り値はなぜ整数??
-
入力された文字列の中の数字を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
小数点入りの文字列をfloat型に...
-
C言語にて構造体のメンバがNULL...
-
char型にint型の数値を代入する。
-
csvファイルをfscanfで読み込む...
-
new charとnew char[N]の違いは?
-
文字型配列に格納した空白の切捨て
-
C++17で、unsigned char * 配列...
-
2次元配列の文字"列"の初期化方法
-
DWORDとcharの変換
-
入力された文字列の中の数字を...
-
char 文字列型 の表現範囲が-12...
-
fgetc( )の戻り値はなぜ整数??
-
fstream型オブジェクトを関数の...
-
C言語の文字リテラル中の16進文...
-
動的メモリの初期化方法について。
-
const char* s1とただのchar s1...
-
strcat関数を自作したいです
おすすめ情報