FileLenでマイナスが出ないようにするには?

解決


魚武  2006-11-30 00:43:36  No: 134365

こちらの掲示板には久しぶりに書込みをする魚武です。

以下のようなプログラムを入力してファイルの容量を表示させるプログラムを作成しました。
Private Sub START_Click()
    
    Dim MySize As Long
    
    MySize = FileLen(Text1.Text)
    Label1.Caption = MySize
    
End Sub

しかし、ファイルによってはFileLenで読み込んだファイルの容量が直接ファイルの容量を確認した時と全く違う数値になってしまう場合があります。
例を挙げれば、本来ならば「3019302912」と表示されなければならないファイルが「-1275664384」と表示されてしまうというものです。

このような現象はなぜ発生するのでしょうか?  どこか設定の漏れがあるのでしょうか?

回答のほどよろしくお願いします。


魚武  2006-11-30 01:01:41  No: 134366

すみません、後から調べたらVisualBasic 6.0のLong関数は
「-2147483648 〜 2147483647」の間の値しか読み込まないため、
それ以上の数値はマイナス表示されるということが分かりました。

VB6.0では32ビットより大きな数値を表現することは不可能なのでしょうか?


Blue  2006-11-30 01:05:25  No: 134367

VB6ですね?

Long型の範囲は -2,147,483,648 〜 2,147,483,647 です。
で最上位ビットを符号ビットとして扱っているため、
2,147,483,648(&H80000000) 〜 4,294,967,295(&HFFFFFFFF)
の値はマイナスで表示されてしまいます。


大吉末吉  2006-11-30 01:06:13  No: 134368

魚武  さん  こんにちは。

> 例を挙げれば、本来ならば「3019302912」と表示されなければならない
> ファイルが「-1275664384」と表示されてしまうというものです

VB6とかでしょうか?
「3019302912」は、Long型の最大値である
「2147483647」を越えてしまっていますね。
その為、VB6のLong型では、誤動作します。
#最上位の符号Bitが設定されてしまい、負の値と看做される。

符号部分を補正する必要がありますね。例えば、
---------------------------------------------------------
    Dim MySize  As Long

    MySize = -1275664384
    
    MySize = IIf(MySize < 0, CCur(i) + CCur(&H40000000) * 4, MySize)
---------------------------------------------------------
とか・・・
#Long型では表せないので、Currncy型にしています。


大吉末吉  2006-11-30 01:08:27  No: 134369

訂正

> Dim MySize  As Long
は、
> Dim MySize  As Currency

で、
> MySize = IIf(MySize < 0, CCur(i) + CCur(&H40000000) * 4, MySize)
は、
> MySize = IIf(MySize < 0, MySize + CCur(&H40000000) * 4, MySize)

です。


Blue  2006-11-30 01:12:03  No: 134370

http://www.geocities.co.jp/SilkRoad/4511/vb/kowaza.htm#unsigned
が参考になるかも。


魚武  2006-11-30 02:54:53  No: 134371

皆さんありがとうございます。

>大吉末吉
教えていただいたソースを試してみたところ、「3019302912」が正常に
表示されました。
しかし、あまり容量が大きすぎる数値(例:「7448363008」)では
> MySize = IIf(MySize < 0, MySize + CCur(&H40000000) * 4, MySize)
の「4」を「8」に変換しないと正確な値が表示されませんでした。

表示させるファイルの容量によってはIf文やCase文を使って値を変更するようにプログラムを組めばよいのですが値を変更する境目が分からなくて
困惑しています・・・


大吉末吉  2006-11-30 03:17:05  No: 134372

7448363008の場合、符号Bitを使用しても、
Long型のサイズ(8バイト=32Bit)に納まりきれませんから、根本的に無理がありそうですね。

「3019302912」は、同じ「B3F6E800」と言うバイト配置をもつ「-1275664384」で代用できましたが、
「7448363008」は、「1BBF50000」と33Bit必要ですので・・・

FileSystemObjectのFileオブジェクトのsizeプロパティとかなら何とかなるんでしょうかね・・・

#申し訳ありませんが、私の環境では、7Gのファイルは作成できないので、
#実際には試せないので・・・


K・今川  2006-11-30 19:32:27  No: 134373

>Long型のサイズ(8バイト=32Bit)に納まりきれませんから、根本的に無理がありそうですね。

FileLenで直接Currncy型に代入すればIIf()の式は必要ないでしょう。
私はCurrncy型よりもDouble型の方がスッキリすると思います。
そもそもFile容量を表示させるだけなら文字列型でもかまいませんし。


大吉末吉  2006-11-30 21:04:15  No: 134374

> FileLenで直接Currncy型に代入すればIIf()の式は必要ないでしょう。

VB6(否定されなかったので、その前提で)のFileLen関数の戻り値はLong型ですから、
戻り値を、何のデータ型に代入しようと、
Long型の範囲の値(-2,147,483,648 〜 2,147,483,647 )にしかならないですよね?

ですから、補正は必要だと思いますけど・・・


魚武  2006-12-01 00:37:20  No: 134375

VB6(否定されなかったので、その前提で)のFileLen関数の戻り値はLong型ですから、

こちらで詳しく調べた結果4GB(4294967295バイト)以下のファイルでは正常な値が
表示されますが、それ以上のファイルや2GBジャスト(2147483648バイト)では正常に
値が表示されないようです。
(最も2147483648バイトのファイルなんてそうそうあるものではないのですが・・・)

更に2GB増える毎にプログラムを更新しなければならないため、
検索するファイルの容量が2GBを超える度にプログラムを変更する必要が出てきます。

FileLen関数の許容範囲ではプログラムの容量毎に処理を変更するのは厳しいので読み込む
ファイルの名前毎に処理を変更するしか方法は無いのでしょうか・・・


Blue  2006-12-01 00:45:09  No: 134376

>FileSystemObjectのFileオブジェクトのsizeプロパティとかなら何とかなるんでしょうかね・・・
こちらは調べてみましたか?
戻り値はVariantになっているけどどうなるのか試せないので。
(んな、でかいファイルをつくるのメンドイので)


大吉末吉  2006-12-01 00:59:26  No: 134377

> こちらで詳しく調べた結果4GB(4294967295バイト)以下のファイルでは
> 正常な値が表示されますが、それ以上のファイルや2GBジャスト(2147483648バイト)では
> 正常に値が表示されないようです。
> 最も2147483648バイトのファイルなんてそうそうあるものではないのですが・・・

動画ファイルとかだと、2GBぐらいは、簡単に超えそうですけど・・・

> FileLen関数の許容範囲ではプログラムの容量毎に処理を変更するのは厳しいので

FileLen関数でなければ駄目なんでしょうか?

> FileSystemObjectのFileオブジェクトのsizeプロパティとかなら
PCを探したら7Gのファイルがあったので、試してみました。
補正不要で、きちんとファイルサイズを参照できるようですよ。


魚武  2006-12-01 03:33:03  No: 134378

> FileLen関数でなければ駄目なんでしょうか?
> FileSystemObjectのFileオブジェクトのsizeプロパティとかなら

これをヒントにプログラムを作りないしてみたら上手くいきました。
下にその時作成したプログラムを記します。

    ' FileSystemObject (FSO) の新しいインスタンスを生成する
    Dim hFso        As FileSystemObject
    Dim hFile       As File
    Dim lFileSize   As Currency
    
    Set hFso = New FileSystemObject
    Set hFile = hFso.GetFile(Text1.Text)
    
    Set hFso = Nothing
    
    ' ファイルサイズを取得する
    lFileSize = hFile.Size
    
    ' 不要になった時点で参照を解放する
    Set hFile = Nothing
    
    ' 取得したファイルサイズを表示する
    Label1.Caption = CStr(lFileSize) & " バイト"


K・今川  2006-12-02 01:06:21  No: 134379

申し訳ありません。FileLen関数の型のことを失念していました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加