C言語関係掲示板

過去ログ

No.972 オープンしたファイルのファイルサイズ取得法

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

オープンしたファイルのファイルサイズ取得法
投稿者---はしもと(2004/02/06 19:13:00)



はじめまして。
Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
ファイルサイズを取得する方法を知りたいです。

私のほうでは
・EOFまでgetc()を使ってその呼び出し回数をカウント
という力技しか思い浮かびません。

もっとスマートな方法をご存知の方、どうかご教授ください。
よろしくお願いします。

以下適当に書いた関数。
long getFileSize(FILE * fin )
{
    long num = 0 ; //読み込んだバイト数
    
    getc( fin )  ;
    while( !feof( fin ) )
    {
        getc( fin ) , num++ ;
    }
    return num ;
}


No.12531

Re:オープンしたファイルのファイルサイズ取得法
投稿者---YuO(2004/02/06 19:23:17)


>Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
>ファイルサイズを取得する方法を知りたいです。

基本的には存在しない,と思って下さい。
ref) C FAQ 19.12


No.12533

Re:オープンしたファイルのファイルサイズ取得法
投稿者---ナスカJ(2004/02/06 19:24:41)


惜しいなあ。
freadで巨大サイズの読み込みして、
戻り値を見れば実際に読めたサイズがわかるよ。

No.12534

Re:オープンしたファイルのファイルサイズ取得法
投稿者---はしもと(2004/02/06 19:38:03)


>基本的には存在しない,と思って下さい。
>ref) C FAQ 19.12
そうなのですか。
勉強になります。

>freadで巨大サイズの読み込みして、
>戻り値を見れば実際に読めたサイズがわかるよ。
なるほど!
万能ではないですが使えますね。

ご回答ありがとうございました。


No.12535

Re:オープンしたファイルのファイルサイズ取得法
投稿者---namani(2004/02/06 21:34:48)


>はじめまして。
>Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
>ファイルサイズを取得する方法を知りたいです。

こんばんは、すごく無理やりな方法ですが、
Solarisでプログラムを書いたときこんな手をつかってみました。

struct stat st;
FILE *f;

f = fopen("xxx.txt","r");
fstat(fileno(f),&st);



これでst.st_sizeにファイルサイズがはいりますが、
ちょっと怪しげです。

No.12536

Re:オープンしたファイルのファイルサイズ取得法
投稿者---YuO(2004/02/06 21:51:01)


>Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
fstat(fileno(f),&st);


fstatの使用は「Cの標準ライブラリ関数のみを使って」という前提条件に反します。

No.12537

Re:オープンしたファイルのファイルサイズ取得法
投稿者---namani(2004/02/06 21:59:09)


><blockquote>>Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
<pre>fstat(fileno(f),&st);</pre></blockquote>
>
>fstatの使用は「Cの標準ライブラリ関数のみを使って」という前提条件に反します。

やっぱり標準じゃなかったですかー。
確認不足でしたね

No.12538

Re:オープンしたファイルのファイルサイズ取得法
投稿者---おでん(2004/02/06 22:40:10)


>
>はじめまして。
>Cの標準ライブラリ関数のみを使ってfopen() で開いたファイルの
>ファイルサイズを取得する方法を知りたいです。
>
>私のほうでは
>・EOFまでgetc()を使ってその呼び出し回数をカウント
>という力技しか思い浮かびません。
>
>もっとスマートな方法をご存知の方、どうかご教授ください。
>よろしくお願いします。
>

かなり怪しいですが、

FILE * fp ;
long siz ;
fp= fopen("aaa.txt","a");
siz= ftell(fp);

じゃダメなのかな?



No.12573

Re:オープンしたファイルのファイルサイズ取得法
投稿者---はしもと(2004/02/09 11:19:56)


>かなり怪しいですが、
>
>FILE * fp ;
>long siz ;
>fp= fopen("aaa.txt","a");
>siz= ftell(fp);
>
>じゃダメなのかな?
>
ソースではいきなりftell()してますが、
fseek()を使って、ファイルの最後まで進んでからftell()で取得。
ということですよね?

YuOさんに提示してもらった資料によると
「ftell()はバイナリーファイルを除いては正しく
 バイト数を返すとは限らない。」
ということですので、これも万能ではないけど使える
方法ですね。

回答ありがとうございました。

No.12574

Re:オープンしたファイルのファイルサイズ取得法
投稿者---おでん(2004/02/09 11:25:29)


>>かなり怪しいですが、
>>
>>FILE * fp ;
>>long siz ;
>>fp= fopen("aaa.txt","a");
>>siz= ftell(fp);
>>
>>じゃダメなのかな?
>>
>ソースではいきなりftell()してますが、
>fseek()を使って、ファイルの最後まで進んでからftell()で取得。
>ということですよね?
>
>YuOさんに提示してもらった資料によると
>「ftell()はバイナリーファイルを除いては正しく
> バイト数を返すとは限らない。」
>ということですので、これも万能ではないけど使える
>方法ですね。
>
>回答ありがとうございました。

アペンドモード("a")でオープンしてるので、
ファイルポインタはファイルの最後にいると思いますが?
・・・ちょっと自信なし (^^;

No.12575

Re:オープンしたファイルのファイルサイズ取得法
投稿者---YuO(2004/02/09 12:07:06)


>>ソースではいきなりftell()してますが、
>>fseek()を使って、ファイルの最後まで進んでからftell()で取得。
>>ということですよね?

fseekをバイナリファイルに対して使ったとき,
whenceにSEEK_ENDを指定した呼び出しは意味のない場合があり得ます。
#と,標準に書いてある。


>アペンドモード("a")でオープンしてるので、
>ファイルポインタはファイルの最後にいると思いますが?

ファイルポインタは確かにファイルの末尾にいますが,
テキストモードで開いていると,ftell関数の呼び出して得られた値が,
読み取ることのできるバイト数とは限りません。
#ファイルサイズという保証もない。

さらに,"ab"又は"a+b"又は"ab+"で開くと,
その時点でのファイル指示子がファイルのデータ長より後ろにある場合があります。
#と,標準に書いてある。


結局のところ,fgetcなりfreadなりでとにかく読み込んでバイト数を調べる以外に,
「読み込み可能な」バイト数を調べる方法はありません。


No.12581

Re:オープンしたファイルのファイルサイズ取得法
投稿者---はしもと(2004/02/09 15:35:30)


>結局のところ,fgetcなりfreadなりでとにかく読み込んでバイト数を調べる以外に,
>「読み込み可能な」バイト数を調べる方法はありません。

結論的には最初に挙げた方法が最も単純にして確実といった感じですね。
勉強になりました、ありがとうございました。

以下まじめに組んだ関数(動作未確認)。

// ファイルサイズ取得関数(2GB迄)
long getFileSize( FILE * fin )
{
    long num = 0 ; //読み込んだバイト数
    long pos     ;

    // ファイルポインタの現在位置を記憶
    pos = ftell( fin ) ;

    // ファイルポインタを先頭へ
    fseek( fin , 0L , SEEK_SET ) ;

    // ファイルサイズをカウント
    getc( fin )  ;
    while( !feof( fin ) )
    {
        getc( fin ) , num++ ;
        if( num < 0 )
        {
            num = -1 ; // error
            break;
        }
    }

    // ファイルポインタを関数呼び出し前の位置へ戻す
    fseek( fin , pos , SEEK_SET ) ;

    return num ;
}