C言語関係掲示板

過去ログ

No.1229 バイナリファイルを全て読み込む

[戻る] [ホームページ]
No.16242

バイナリファイル読み込み
投稿者---AI(2004/08/19 11:31:48)


お世話になります。AIです。
今バイナリファイルについて学習しています。

ftell()で求めるレコード数とはどう言う意味なのでしょうか?

また、fread()の引数のデータサイズでバイナリファイル全てのデータを読み込むことができるのでしょうか?

よろしくお願いします。



No.16243

Re:バイナリファイル読み込み
投稿者---Sciggepy(2004/08/19 12:16:48)


>ftell()で求めるレコード数とはどう言う意味なのでしょうか?
ftellが返す値は、ファイル内のその時点での読み取り位置です。バイナリファイルでは、先頭からのバイト数が返ります。

>また、fread()の引数のデータサイズでバイナリファイル全てのデータを読み込むことができるのでしょうか?
freadは実際に読み取った要素の数を返します。

fread(buf,1,n,pf);

は、nバイトのデータをpfが示すファイルから読み取り、bufに格納しますが、nよりも少ない値が返されたときは、ファイルの最後に達したと判断してよいでしょう。(エラーの場合もあります。)



No.16244

Re:バイナリファイル読み込み
投稿者---AI(2004/08/19 13:34:02)


バイナリファイルを全て読み込みたい場合は
どのようにしたらよいのでしょうか?
while分でファイルの最後までと指定するのでしょうか?
よろしくお願いします。


No.16245

Re:バイナリファイル読み込み
投稿者---AI(2004/08/19 13:55:17)


>バイナリファイルを全て読み込みたい場合は
>どのようにしたらよいのでしょうか?
>while分でファイルの最後までと指定するのでしょうか?
>よろしくお願いします。

ファイルの文字列を配列に格納したいです。
読み込むファイルは、NULL文字が付加
されているので、fgetsでは無理なのではないかと
考えています。
EOFまで読むことを指定すると
読み込めるのでしょうか?


No.16246

Re:バイナリファイル読み込み
投稿者---Sciggepy(2004/08/19 15:30:47)


ファイルをすべて読み込む場合は、次のようにします。
#include <stdio.h>

#define BYTESRD 1024

size_t readfile(FILE *pf,void **ppb) {
    char *buf,*nbuf;
    size_t s,p=0;

    buf=(char *)malloc(BYTESRD);
    if(!buf) return (size_t)-1;
    while((s=fread(buf+p,1,BYTESRD,pf))==BYTESRD) {
        s=0;
        p+=BYTESRD;
        nbuf=(char *)realloc(buf,p+BYTESRD);
        if(!nbuf) break;
        buf=nbuf;
    }
    *ppb=(void *)buf;
    return p+s;
}

int main(int argc,char **argv)
{
    FILE *pf;
    char *buf;
    size_t s;

    if(argc<3) return 0;
    pf=fopen(argv[1],"rb");
    s=readfile(pf,(void **)&buf);
    fclose(pf);
    pf=fopen(argv[2],"wb");
    fwrite(buf,1,s,pf);
    fclose(pf);
    free(buf);
    printf("%d\n",s);
    return 0;
}
読み込みエラーの判定はしていません。(できない?)

一度ですべてのデータを読み込むには、低水準入出力など、環境依存のコードを書く必要があります。


No.16247

Re:バイナリファイル読み込み
投稿者---かずま(2004/08/19 17:32:54)


> ファイルをすべて読み込む場合は、次のようにします。

ちょうど 1KB のファイルを読み込むとき、2KB のメモリを確保しますね。
realloc は、メモリのコピーを伴う場合があります。
大量のデータに対して、realloc を頻繁に呼び出すのは効率が悪くないですか?


> 一度ですべてのデータを読み込むには、低水準入出力など、環境依存の
> コードを書く必要があります。

次のプログラムは、一度ですべてのデータを読み込んでいますが、
どの部分が環境依存でしょうか?
#include <stdio.h>
#include <stdlib.h>

void dump(void *buf, int size)
{
    unsigned char *p = buf;  int i = 0;

    while (i < size) {
        printf(" %02x", p[i]);
        if ((++i & 15) == 0) printf("\n");
    }
    if (i & 15) printf("\n");
}

int main(int argc, char *argv[])
{
    FILE *fp;  long size, n;  char *buf;

    if (argc != 2) return 1;

    fp = fopen(argv[1], "rb");
    if (fp == NULL) return 1;

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    printf("size=%ld\n", size);

    buf = malloc(size);
    if (buf == NULL) return 1;

    rewind(fp);
    n = fread(buf, 1, size, fp);

    if (n > 256) n = 256;
    dump(buf, n);

    return 0;
}



No.16248

Re:バイナリファイル読み込み
投稿者---Ban(2004/08/19 18:02:25)


> fread(buf, 1, size, fp);

元質問の「ftell()で求めるレコード数」あたりから推測するに、
byte 単位での読み出しではなく、固定レコード長のバイナリを前提に
ftell のオフセットからレコード数を算出し、それを引数に
fread することを想定した問題な気もします。



No.16249

Re:バイナリファイル読み込み
投稿者---Sciggepy(2004/08/19 18:35:20)


毎度ご指摘ありがとうございます。

> fseek(fp, 0, SEEK_END);
> size = ftell(fp);
その手がありましたね。
APIばかり使っているので、すっかり忘れていました。

#私のCの知識は、本を買って勉強したわけでもなく、
#誰かに教えてもらったということもないので、基本的に穴だらけです。
#標準Cでまともなプログラムを書いたことは、数えるほどもありません。
#fseekやftellに関しては、使ったこともありませんでした。



No.16317

Re:バイナリファイル読み込み
投稿者---AI(2004/08/23 19:06:08)


返答ありがとうございます。
追加ですが、
テキストファイルで文字列処理を行う場合、
例えば、あるテキストファイルデータを配列に格納し、
その配列で、検索文字で検索をして文字を分離させることは
strchr()などでできますが、
バイナリファイルにおいて、そのようなことは出来るのでしょうか?

文字列処理において、テキストファイルで行っていた処理が
バイナリファイルになるとこのように変わるなど、
何かあれば教えていただければ助かります。
よろしくお願いします。



No.16318

Re:バイナリファイル読み込み
投稿者---REE(2004/08/23 20:10:24)


まず、テキストファイル/バイナリファイルの処理と
文字列・バイナリデータ処理は別の物として考えるようにして下さい。

ここでは、文字列とバイナリデータの違いを考えて見ます。

文字列とバイナリデータの一番の違いはヌル文字の扱いです。

文字列:必ず'\0'で終わる。
バイナリデータ:'\0'を特別視しない、そのためデータだけでは長さが分からない。

そのため、通常は同じ関数での処理は出来ません。

ライブラリ関数も、strで始まる文字列用と、memで始まるバイナリデータ用に分かれています。