
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- Access(アクセス) CSVファイルの「0落ち」にVBA 6 2023/02/02 15:27
- その他(プログラミング・Web制作) 【python】Excelファイルを読み込む際の日付の表示形式を任意にする 2 2022/11/24 14:21
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
可変引数について。
-
const char* s1とただのchar s1...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
char型にint型の数値を代入する。
-
構造体が戻り値の関数について...
-
char*を初期化したいのですが
-
System.IO.Directory.GetFiles...
-
配列の要素数に変数を入れたい...
-
関数から配列を返すには?
-
C# DataGridView のヘッダーセ...
-
EXCEL VBAのソートについて
-
VBA基本構文の作り方 2列の...
-
銀行ATMの数字キーの配列
-
連結リスト 要素の入れ替え
-
Linked List(線形リスト)を使...
-
init関数の意味
-
C#で構造体の配列を持った構造...
-
C# Listを使わずに2次元配列の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
DWORDとcharの変換
-
C++17で、unsigned char * 配列...
-
char 文字列型 の表現範囲が-12...
-
new charとnew char[N]の違いは?
-
char型にint型の数値を代入する。
-
動的メモリの初期化方法について。
-
小数点入りの文字列をfloat型に...
-
文字型配列に格納した空白の切捨て
-
fstream型オブジェクトを関数の...
-
C++Builder 2009 テキスト...
-
文字列の途中から途中までを抽出
-
C言語の文字リテラル中の16進文...
-
エクセルのMID関数は、C言語では?
-
文字列のswap
-
void型へのポインタ
-
VC++ char[10]へのCString値の代入
おすすめ情報