C言語関係掲示板

過去ログ

No.1008 ファイルサイズを表示したい

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

ファイルサイズを表示したいのですが
投稿者---sayaka(2004/01/16 17:10:37)


GetFileSizeを使ってファイルサイズを取ろうと思ったのですが、
ビット操作がだめなのか・・・どうファイルのサイズにしていいのかわかりません。

最終的にbyteになおして表示したかったんですけど・・・
ほぼsampleとしてあったもののままなんですが、こんな感じで
作ってみました(実際はファイルはすでにあるのでGetFileSizeの辺りだけ使ってます)

void DispFileSize()
{
    HANDLE hFile;
        char wc_message[200];
    DWORD FileSizeLow, FileSizeHigh;

    hFile = CreateFile(
        "\\command.com",
        0,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
    sprintf(wc_message,"ファイルサイズ: %ud*2^32 + %ud\n", FileSizeHigh, FileSizeLow);
        MessageBox( NULL, wc_message, title, MB_OK );

    CloseHandle(hFile);
}

単純にこのソースのまま動かすと
ファイルサイズ:0d*2^32+140288d
って表示されちゃいます・・・。当然か・・・。

どこを直したらいいのでしょうか?
アドバイスお願いします。


No.1010

Re:ファイルサイズを表示したいのですが
投稿者---かずま(2004/01/16 18:09:02)


    double size;

    size = FileSizeHigh * 4294967296.0 + FileSizeLow;
    sprintf(wc_message, "ファイルサイズ: %g\n", size);


No.1012

Re:ファイルサイズを表示したいのですが
投稿者---かずま(2004/01/16 18:25:28)


>   sprintf(wc_message, "ファイルサイズ: %g\n", size);

%g を %.16g に訂正。


No.1011

Re:ファイルサイズを表示したいのですが
投稿者---YuO(2004/01/16 18:10:28)


環境を書いて下さい。
とりあえず,Visual C++/Borland C++をWindowsで使っていることを前提に記述していきます。

本当はコンパイラ制限を取っ払いたかったのですが,64bitの数値を文字列化するAPIが見つからなかったので……。
#私の環境(WinNT 4.0)ではFormatMessageも対応していない……。


>GetFileSizeを使ってファイルサイズを取ろうと思ったのですが、
>ビット操作がだめなのか・・・どうファイルのサイズにしていいのかわかりません。

ULARGE_INTEGERを使って32bit値二つを64bit値一つにまとめて,
sprintfで文字列化する,という方法を採る事になると思います。

断片を書くと,
ULARGE_INTEGER ui;
ui.LowPart = FileSizeLow;
ui.HighPart = FileSizeHigh;

sprintf(wc_message, "ファイルサイズ: %I64u\n", ui.QuadPart);

となります。

FileSizeLowとHigh自体をULARGE_INTEGER型にしてしまってもよいと思います。


ちなみに,Digital Mars C++のようなC99対応のコンパイラでは,I64のかわりにllを使います。


No.1029

Re:ファイルサイズを表示したいのですが
投稿者---sayaka(2004/01/19 09:50:06)


>環境を書いて下さい。
スミマセン。環境はwindows2000でC言語を使っています。コンパイラは普通にコマンドプロンプトを使ってコンパイルをしています。

ちなみにすごく馬鹿な質問でごめんなさい。
これファイルサイズはbitですよね??


No.1031

Re:ファイルサイズを表示したいのですが
投稿者---YuO(2004/01/19 12:39:39)


>>環境を書いて下さい。
>スミマセン。環境はwindows2000でC言語を使っています。コンパイラは普通にコマンドプロンプトを使ってコンパイルをしています。

コンパイラの名前は何ですか?


>これファイルサイズはbitですよね??

当然「byte」です。
コンピュータで操作する最小の単位は基本的に「byte」ですから。


No.1036

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---sayaka(2004/01/19 16:43:59)


>コンパイラの名前は何ですか?

コンパイラの名前とは・・・・。
Cコマンドラインコンパイラでいいのでしょうか?

windowsのエクスプローラでは137KBと表示されているファイルが、
下記のソースで動かすとFileSizeHigh=4291084 FileSizeLow=-1
でFileSizeHigh * 4294967296.0 + FileSizeLow=1.84300697395616e+016
の値が戻ってくるので、ん〜私がちゃんと理解できてないからおかしい
のですよね・・・。
ソースは
void GetFSize581()
{
    HANDLE hFile;
    DWORD FileSizeLow, FileSizeHigh;
    double size;

    hFile = CreateFile(
        "soushin.dat",
        0,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
    sprintf(wc_message, "FileSizeHigh=%d, FileSizeLow=%d\n"
            ,FileSizeHigh, FileSizeLow);
    MessageBox( NULL, wc_message, title, MB_OK );
    size  =FileSizeHigh * 4294967296.0 + FileSizeLow;
    sprintf( wc_message, "ファイルサイズ:%.16g",
            size);
    MessageBox( NULL, wc_message, title, MB_OK );
    CloseHandle(hFile);

}


というのも、FTPで送受信したbyte数をInternetSetStatusCallback
を使って送受信したバイト数(lpdwByte)を%表示に直したいのですが
そのフォルダ全てのファイルの情報は必要なかったので、GetFileSize
を使ったのですが、そもそもこれが間違いなのでしょうか?

No.1037

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---三毛猫(2004/01/19 16:47:28)


GetFileSizeの説明より
> This handle must have been created with either the GENERIC_READ or GENERIC_WRITE access right.

ということでCreateFileの第2引数にGENERIC_READを指定してみてはいかがでしょ。

# 返事を書いてる最中に投稿が消えてビックリ


No.1038

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---三毛猫(2004/01/19 17:04:44)


手元の環境で試してみたら、どうやら0でも動くようで。
ファイルオープンの時点で失敗していませんか?

FileSizeLowに-1が入っている場合は
GetFileSizeでエラーが発生しているという事です。


No.1039

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---YuO(2004/01/19 18:11:33)


>コンパイラの名前とは・・・・。
>Cコマンドラインコンパイラでいいのでしょうか?

そんなコンパイラ,聞いたことがありません。

コンパイラを実行したときに,大抵最初の行にコンパイラの名前とバージョンが出力されます。
例えば,Borland C++ Compiler 5.5.1だと,
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland

のように表示されますし,VIsual C++.Net 2002だと,
Microsoft(R) 32-bit C/C++ Standard Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.

と表示されます。
#後者は実際には.Net Framework SDK 1.0付属のC++コンパイラ。


>windowsのエクスプローラでは137KBと表示されているファイルが、
>下記のソースで動かすとFileSizeHigh=4291084 FileSizeLow=-1
>でFileSizeHigh * 4294967296.0 + FileSizeLow=1.84300697395616e+016
>の値が戻ってくるので、ん〜私がちゃんと理解できてないからおかしい
>のですよね・・・。

エラー処理をちゃんとしてみて下さい。
三毛猫さんの書かれたとおり,CreateFileが一番怪しいですが,
GetFileSizeで失敗しているかもしれません。

hFileがINVALID_HANDLE_VALUEでないかどうか,FileSizeLowがINVALID_FILE_SIZEでないかどうか,
さらにFileSizeLowがINVALID_FILE_SIZEの場合はGetLastErrorがNO_ERRORを返しているかどうか,
そのくらいのチェックは当然していますよね?


No.1050

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---sayaka(2004/01/20 11:25:23)


>そんなコンパイラ,聞いたことがありません。

>
>エラー処理をちゃんとしてみて下さい。
はい。スミマセン。
ちなみにYuOさんの説明で、CreateFileのエラー取得の勘違いが
発覚しました。私にはシンプルでとてもわかりやすかったです。

三毛猫さんやYuOの書かれたとおりCreateFileがエラーでした。
なんとかwindowsのエクスプローラーで表示したファイルサイズ
137KBと140288/1024KB
で両方のファイルサイズが一致しました。ありがとうございました。

なのですが、前回の話とダブりますが、CALLBACK関数で取得した
アップロードのバイト数と一致しないのはなぜなのでしょうか?
アップロードするファイルは基本的に送るファイルよりも小さいもの
なのですか?

↓がコールバックで表示させているところです。
void CALLBACK MyCallback(HINTERNET hInet,
        DWORD dwContx, DWORD dwStatus, LPVOID lpvStatus, DWORD dwLength)
{
    char str[1024];
    LPDWORD lpdwByte;
    static DWORD dwTemp;
    STATUSCALLBACK *lpsc;

    lpsc = (STATUSCALLBACK *)dwContx;
    
    switch (lpsc->dwFrom) {
        case CONTEXT_PUTFILE:
            switch (dwStatus) {
                case INTERNET_STATUS_REQUEST_SENT:
                    lpdwByte = (LPDWORD)lpvStatus;
                    if (dwTemp < *lpdwByte) {
                        memset( str, 0x00, sizeof( str ));
                        sprintf(str, "%dバイトアップロードしました", *lpdwByte);
                        MessageBox( NULL, str, title, MB_OK );
                        dwTemp = *lpdwByte;
                    }
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
    return;
}




No.1053

Re:ファイルサイズを表示したいのですが かずまさんのソースを使ってみたのですが
投稿者---三毛猫(2004/01/20 14:58:35)


INTERNET_STATUS_REQUEST_SENT で通知されるのは、
累計の送信サイズではなくその時送信したサイズのようです。
# うちの環境では4096バイトごとに通知されていました

なので、ここで受け取ったサイズを合計していくことで
実際に送信したサイズを求めることが出来ます。

ただ最初の数回はFTPのコマンドを送信した時のサイズが
通知されるようなので、単純に合計するとサイズがずれてしまいます。
この辺を区別する方法に関しては分かりませんでしたが、
うちの環境では最初の3回がFTPコマンドの送信サイズで
それ以降が実際のデータ送信サイズとなっていました。
# 全ての環境でこうなっているとは限りません


No.1054

以前の質問の続きに質問を移動します。
投稿者---sayaka(2004/01/20 15:04:40)


FTPの進捗状況表示の方の質問の続きに書き換えます。
是非そちらのほうで教えてください。よろしくお願します。