以下のような半角スペース区切りデータをファイルから読み込みたいのですが、
DATA=0 0 10 100 101 ...(1~3桁の数字)
ReadStringでまるごと読み込むと容量オーバー(データは数万個あります)になってし
まいます。
順に0,0,10,100,101というふうにデータを格納していきたいのですが方法がわかりませ
ん。(数字でも文字列でも構いません)
うまく伝わったかどうか不安ですが、皆さんの知恵をお貸し下さい。
開発環境はVC++6.0ダイアログベースです。
宜しくお願い致します。
自分で4KBなり8KBなりのバッファを確保して、
そこに分割して読み込んでいけばいいと思います。
この場合には、最後の項目が切れる可能性がありますので、
ラストのスペース記号までを取り込んでから、余りのデータを
先頭にシフトしてから、その続きをのデータを読み込む・・・
みたいな感じになるのではないでしょうか?
バッファに読み込んだスペース区切りのデータを1個ずつ読み込む関数は
ご存知ですよね?
>でまるごと読み込むと容量オーバー...
メモリマップトファイルもあるかもしれません。
CreateFileMapping
MapViewOfFile
この辺りを使うと思います。
ReadString()ってCStdioFile::ReadString()のことかな?
これは1行づつ読み込むものなので今回のケースでは使えません。
代わりに、Read()関数を使用します。
Read()関数はCStdioFileの親クラスであるCFileクラスにあります。
親クラスなので、そのまま呼べるよ。
Read()関数はバッファを自分で用意してから呼ばないといけないので、
MistyGreenさんのおっしゃっているとおりの話になります。
> 自分で4KBなり8KBなりのバッファを確保して、
注意点は、Read()関数の場合、読み込んだ文字列が改行位置で終わ
るとは限らないため、もしデータファイルが改行文字を含んでいる
のなら、その点を考慮した実装に修正せねばなりません。
ちょいと補足
>これは1行づつ読み込むものなので今回のケースでは使えません。
1行づつ読み込むから、1行の長さが長すぎるとバッファオーバーフローして
使えない。
ですね。
CStdioFile::ReadString()でもバッファとサイズを渡すやつを使えばいいのでは?
http://msdn.microsoft.com/ja-jp/library/x5t0zfyf%28VS.80%29.aspx
確認
1.読み込むファイルのサイズはどのくらい?
2.「データは数万個あります」とあるが、
DATA= ~ この後ろが数万個か?
DATA=・・
DATA=・・・・・
と、DATA=が数万個か?
(その際、一個のDATA=はどのくらいか?またDATA=ごとの区切りはなにか?)
3.容量オーバーになってしまう読み込み方法のソースがあれば見せられますでしょう
か?
4.「データを格納していきたいのですが」 のデータの格納先とは?
Blueさん
> CStdioFile::ReadString()でもバッファとサイズを渡すやつを使えばいいのでは?
失礼しました、確かにそうですね。
1.
> ReadStringでまるごと読み込むと容量オーバー(データは数万個あります)に
> なってしまいます。
データ提供元と最大データ数を決めた方がいいと思います。
ソフト側は最大データ数によって格納変数を決めることになると思います。
2.
>DATA=0 0 10 100 101 ...(1~3桁の数字)
これでは、フォーマットがまだだめだと思います。
ヘッダーは「DATA=」?
1桁/2桁/3桁の区別は0埋め? スペース?
データーの一区切りは?
改行はあり?
ソフトで読込めるように
分からないようなところがないようにした方がいいですね。
うーむ、VC++6.0で開発ですか。
新規で作成するのであれば、新しい環境で作った方が
良いような気もしますけれど。
VC++6.0のコンパイラは実装が古いのでこれでないと
いけない理由が無いのであれば、新しい環境に移行された方が
良いと思います。それでなくても古い環境からの移行は
結構骨になる事が多いですし。
クラス任せに出来るケースと言うのは色々条件付けが必要になります。
少なくともフォーマット上の不明点はない状態にした方が良いと
思いますけれど、複数のパターンにも対応してくれとか色々ありますからねぇ。
条件付けに合わないケースの場合は、自分でお膳立てして組み合わせるしか
無いので、同じクラスでも他の関数で対応できないかとか、同じ関数の
別の引数のバージョンで対応できないかとか考えて見た方が良いです。
>1.読み込むファイルのサイズはどのくらい?
2~300KBです。
>2.「データは数万個あります」とあるが、
DATA= ~ この後ろが数万個です。
>3.容量オーバーになってしまう読み込み方法のソースがあれば見せられますでしょ
うか?
CStdioFile fin( filename, CFile:modeRead );
fin.ReadString( str );
str.Delete( 0, 5 ); //DATA=をDelete
for( i = 0; i < x; i ++ ){
AfxExtractString( Result, str, i, _T( ' ' ) );
}
fin.Close();
正確には、strに入れるときではなく、TRACEやstrを操作するときにオーバーフローして
いるみたいです。
>4.「データを格納していきたいのですが」 のデータの格納先とは?
int型の配列を準備し、読み込んだデータが0ならData[i]=1、100ならData[i]=2・・など
というふうにしたいです。
>ヘッダーは「DATA=」?
そうです。
>1桁/2桁/3桁の区別は0埋め? スペース?
>データーの一区切りは?
桁数の区別はないです。ただ、半角スペースで区切られているだけです。
>改行はあり?
途中改行はありません。
>バッファに読み込んだスペース区切りのデータを1個ずつ読み込む関数は
>ご存知ですよね?
いまいち理解してませんのでお手数ですがご教示いただけますでしょうか?(汗)
ちょっと気になったんですが、
オーバーフローって関数の返り値でエラーが出ているんですか?
それともスタックオーバーフローみたいにメッセージが直接でている?
なんかその辺の話まで正確に書いた方が良いような気がします。
総論的には読み込みデータ量の最大値が確実に押さえられているのであれば、
その上限までで処理出来ればよいのですけれど、最大値が抑えられていない
場合は、既に話に出ているように一定サイズ毎にファイルの終端まで処理する
ようにしておかないとファイルの容量で処理できる出来ないが左右されてしまいます。
これ以上のファイルは処理できませんという仕様でOKならそれはそれなんですけれど。
あと、使い捨てなら良いのですが、
後々メンテナンスを伴うようなプログラムなのであれば、
既に私が書いている開発環境に関する内容も一考された方が良いと思います。
>>バッファに読み込んだスペース区切りのデータを1個ずつ読み込む関数は
>>ご存知ですよね?
>>いまいち理解してませんのでお手数ですがご教示いただけますでしょうか?(汗)
CStringにもそんな事が出来た関数があったような気もします。
但し、2バイト文字に対応していたかは疑問ですけれど。
2バイト文字に対応していない関数を使っていて2バイト文字が混ざったファイルを使って
しまった場合には動きがおかしくなる可能性があるかもです。
2バイト文字は使用禁止と既定されているなら話は別ですけれど。
PATIOさん
いろいろとアドバイスいただきありがとうございます。
内容としては、Debag Assertion Failed!というメッセージが出てきております。
Dumpout.cppというファイルです。
ファイル内は1バイト文字のみで構成されております。
>>2.「データは数万個あります」とあるが、
> DATA= ~ この後ろが数万個です。
最大データ数は決めといた方がいいです。
たとえば、ざっと5万個というような具合に決めといた方がいいです。
>1.読み込むファイルのサイズはどのくらい?
2~300KBです。
ん?
500Kbyteサイズぐらいの変数を念のためnew等を使ってを作る。
CFile,ReadFile,CStdioFile(試したことないです。)等で
一気に読み込めるのではないでしょうか。
>桁数の区別はないです。ただ、半角スペースで区切られているだけです。
ぜひ区別した方がいいですね。
DATA=を探して1バイト読み飛ばして3バイト読む。
0埋めかスペース埋めならそのままatoi()で数値に変換できる。