こちらの掲示板には久しぶりに書込みをする魚武です。
以下のようなプログラムを入力してファイルの容量を表示させるプログラムを作成しました。
Private Sub START_Click()
Dim MySize As Long
MySize = FileLen(Text1.Text)
Label1.Caption = MySize
End Sub
しかし、ファイルによってはFileLenで読み込んだファイルの容量が直接ファイルの容量を確認した時と全く違う数値になってしまう場合があります。
例を挙げれば、本来ならば「3019302912」と表示されなければならないファイルが「-1275664384」と表示されてしまうというものです。
このような現象はなぜ発生するのでしょうか? どこか設定の漏れがあるのでしょうか?
回答のほどよろしくお願いします。
すみません、後から調べたらVisualBasic 6.0のLong関数は
「-2147483648 〜 2147483647」の間の値しか読み込まないため、
それ以上の数値はマイナス表示されるということが分かりました。
VB6.0では32ビットより大きな数値を表現することは不可能なのでしょうか?
VB6ですね?
Long型の範囲は -2,147,483,648 〜 2,147,483,647 です。
で最上位ビットを符号ビットとして扱っているため、
2,147,483,648(&H80000000) 〜 4,294,967,295(&HFFFFFFFF)
の値はマイナスで表示されてしまいます。
魚武 さん こんにちは。
> 例を挙げれば、本来ならば「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型にしています。
訂正
> 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)
です。
http://www.geocities.co.jp/SilkRoad/4511/vb/kowaza.htm#unsigned
が参考になるかも。
皆さんありがとうございます。
>大吉末吉
教えていただいたソースを試してみたところ、「3019302912」が正常に
表示されました。
しかし、あまり容量が大きすぎる数値(例:「7448363008」)では
> MySize = IIf(MySize < 0, MySize + CCur(&H40000000) * 4, MySize)
の「4」を「8」に変換しないと正確な値が表示されませんでした。
表示させるファイルの容量によってはIf文やCase文を使って値を変更するようにプログラムを組めばよいのですが値を変更する境目が分からなくて
困惑しています・・・
7448363008の場合、符号Bitを使用しても、
Long型のサイズ(8バイト=32Bit)に納まりきれませんから、根本的に無理がありそうですね。
「3019302912」は、同じ「B3F6E800」と言うバイト配置をもつ「-1275664384」で代用できましたが、
「7448363008」は、「1BBF50000」と33Bit必要ですので・・・
FileSystemObjectのFileオブジェクトのsizeプロパティとかなら何とかなるんでしょうかね・・・
#申し訳ありませんが、私の環境では、7Gのファイルは作成できないので、
#実際には試せないので・・・
>Long型のサイズ(8バイト=32Bit)に納まりきれませんから、根本的に無理がありそうですね。
FileLenで直接Currncy型に代入すればIIf()の式は必要ないでしょう。
私はCurrncy型よりもDouble型の方がスッキリすると思います。
そもそもFile容量を表示させるだけなら文字列型でもかまいませんし。
> FileLenで直接Currncy型に代入すればIIf()の式は必要ないでしょう。
VB6(否定されなかったので、その前提で)のFileLen関数の戻り値はLong型ですから、
戻り値を、何のデータ型に代入しようと、
Long型の範囲の値(-2,147,483,648 〜 2,147,483,647 )にしかならないですよね?
ですから、補正は必要だと思いますけど・・・
VB6(否定されなかったので、その前提で)のFileLen関数の戻り値はLong型ですから、
こちらで詳しく調べた結果4GB(4294967295バイト)以下のファイルでは正常な値が
表示されますが、それ以上のファイルや2GBジャスト(2147483648バイト)では正常に
値が表示されないようです。
(最も2147483648バイトのファイルなんてそうそうあるものではないのですが・・・)
更に2GB増える毎にプログラムを更新しなければならないため、
検索するファイルの容量が2GBを超える度にプログラムを変更する必要が出てきます。
FileLen関数の許容範囲ではプログラムの容量毎に処理を変更するのは厳しいので読み込む
ファイルの名前毎に処理を変更するしか方法は無いのでしょうか・・・
>FileSystemObjectのFileオブジェクトのsizeプロパティとかなら何とかなるんでしょうかね・・・
こちらは調べてみましたか?
戻り値はVariantになっているけどどうなるのか試せないので。
(んな、でかいファイルをつくるのメンドイので)
> こちらで詳しく調べた結果4GB(4294967295バイト)以下のファイルでは
> 正常な値が表示されますが、それ以上のファイルや2GBジャスト(2147483648バイト)では
> 正常に値が表示されないようです。
> 最も2147483648バイトのファイルなんてそうそうあるものではないのですが・・・
動画ファイルとかだと、2GBぐらいは、簡単に超えそうですけど・・・
> FileLen関数の許容範囲ではプログラムの容量毎に処理を変更するのは厳しいので
FileLen関数でなければ駄目なんでしょうか?
> FileSystemObjectのFileオブジェクトのsizeプロパティとかなら
PCを探したら7Gのファイルがあったので、試してみました。
補正不要で、きちんとファイルサイズを参照できるようですよ。
> 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) & " バイト"
申し訳ありません。FileLen関数の型のことを失念していました。
ツイート | ![]() |