- ベストアンサー
C言語でテキストファイルへのランダムアクセス
- C言語を使い、CSVファイルの特定の通し番号が振られたレコードの値を変数に格納する方法について教えてください。
- CSVファイルではバイナリファイルとは異なり、ランダムアクセスは難しいです。すべてのデータを変数に読み込んで検索する方法が一般的です。
- ファイルが可変長のデータを含んでいる場合、fseek関数を使ったランダムアクセスは使えません。アドバイスをお願いします。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
特定の通し番号までファイルを読み込んでいけば可能です。 > いろいろな参考書を確認するとバイナリファイルならランダムアクセスという方法で > 任意の場所に直接アクセスできるらしいですが > CSVなどのテキストファイルの場合、 > 一度ファイルの内容をすべて変数に読み込んで > 変数内で検索するしかないのでしょうか? 何の参考書を見たか知りませんが、バイナリファイルにしかランダムアクセスがないと書いてあるなら、その参考書は捨てたほうがいいです。 バイナリファイルもテキストファイルもほぼ同じです。そこに書いてあるデータをfscanfで読むか読まないかという違いくらいしかありません。MS-DOSにはfopenに'b'というフラグがあったと思いますが、Unixにはそんなフラグありません。 内部のデータ構造もほとんど同じです。もちろん、どちらもランダム・アクセスできますし、シークもできます。 > ランダムアクセスで使うfseek関数はサイズで移動するらしいので > 可変長のデータが含まれているとこの関数は使えないんじゃないかと思っています。 はい。可変長データがある場合、fseek関数で飛ばすことはできません。 そもそも、プログラムから見たファイルの見え方とあなたがテキストエディタで見た場合のファイルの見え方は違います。プログラムからファイルを見た場合、全ては連続したバイナリデータに見えます。fscanfやfreadは今指しているところから所定の方法でデータを読み込むだけです。 CSV形式のファイルで特定の通し番号が振られたレコード1行の値を読み込むには、特定の通し番号が出てくるまでずっとファイルを呼んでいく以外に方法はありません。もちろん、ほしいもの以外を変数に格納する必要はありません。改行文字の次に入っている数字が欲しい通し番号かだけをチェックして、そうでない場合は飛ばせば良いです。 自分だったら、fgetsで各行を読み込み、strncmpで先頭が所定の通し番号かチェックし、所定の通し番号でなければcontinue、所定の通し番号の場合は変数に格納してbreakという動きをさせます。 Unixだとmmapを使っても良いかもしれません。連番で飛ばした行がないなら、strncmpすら不要かもしれません。 更にいうと、なにか特殊な理由がない限りはテキストファイルに対する処理をC言語で書くことはしないようにします。Perl Python Rubyなどのスクリプト言語を使って書いたほうがライブラリーもありますし、圧倒的に楽です。それにこの程度の大きさで1000レコードくらいなら、今時のPCを使っていたらライブラリーで全部呼んでもそんなに時間かからないです。
お礼
素晴らしい回答ありがとうございます。 バイナリファイルと一緒に書かれていたのでバイナリにしか使えないと思い込んでいました。 >バイナリファイルもテキストファイルもほぼ同じです。そこに書いてあるデータをfscanfで読むか読まないかという違いくらいしかありません。 バイナリファイルはfscanfを使うと(文字に変換してしまうから)おかしなことになるということですね。 >CSV形式のファイルで特定の通し番号が振られたレコード1行の値を読み込むには、特定の通し番号が出てくるまでずっとファイルを呼んでいく以外に方法はありません。 やはり可変長だとシーケンシャルに上から検索していくしかないんですね。 >更にいうと、なにか特殊な理由がない限りはテキストファイルに対する処理をC言語で書くことはしないようにします。Perl Python Rubyなどのスクリプト言語を使って書いたほうがライブラリーもありますし、圧倒的に楽です。 言語の違いでファイルの読み書きに差が出るのは知りませんでした。 名前はよく聞きますが、中身を見たことはないので調べてみようと思います。C言語はテキストファイルに対する処理は苦手なんですね。 助言ありがとうございました。