VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 1354|回复: 17

GetFileSize取大文件时私吞字节,有bug?

[复制链接]
发表于 2020-5-23 10:59:25 | 显示全部楼层 |阅读模式
本帖最后由 业余的业余 于 2020-5-23 17:49 编辑

我用API的GetFileSize函数和知名软件Filezilla,对同一个文件获取其大小,发现两者有明显差异。按照实际数据逻辑推算,Filezilla获得的文件大小是正确的。GetFileSize函数存在严重的BUG,不知其具体实现过程,特来请教各位大咖。
贴图有真相:

Getfilesize

Getfilesize

Filezilla

Filezilla
发表于 2020-5-24 00:09:27 | 显示全部楼层
就差9个字节,我知道问题的所在,不是API的问题,是你调用的,还是好好看一下GetFileSize的说明和低双字节+高双字节的运算,就能解决问题
回复 支持 反对

使用道具 举报

发表于 2020-5-24 00:11:54 | 显示全部楼层
不要别人封装了一个API_OpenFile就一直用,也不去检查作者设计时BUG,那你必然找不出问题,要完全理解代码才行
回复 支持 反对

使用道具 举报

发表于 2020-5-24 00:48:00 | 显示全部楼层
处理64位数据,你需要实现个大数计算
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-24 09:47:38 | 显示全部楼层
jy4977596491 发表于 2020-5-24 00:09
就差9个字节,我知道问题的所在,不是API的问题,是你调用的,还是好好看一下GetFileSize的说明和低双字节+ ...

你说的对,我也先尝试去理解了下,就是不太懂。我不是科班出生,遇到问题首先找度娘,可是能把GetFileSize说的比较透的,实在难找。网上看到的基本就是概念性的描述。我估计问题在如下模块中:
Private Sub Long2Size(ByVal LongLow As Long, ByVal LongHigh As Long, ByRef FileSize As Currency)
Dim Cutoff As Currency
Cutoff = 2147483647
Cutoff = Cutoff + 2147483647
Cutoff = Cutoff + 1
FileSize = Cutoff * LongHigh
If LongLow < 0 Then
    FileSize = FileSize + (Cutoff + (LongLow + 1))
Else
    FileSize = FileSize + LongLow
End If
End Sub
你能稍微进一步指点下吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-24 09:57:49 | 显示全部楼层
jy4977596491 发表于 2020-5-24 00:09
就差9个字节,我知道问题的所在,不是API的问题,是你调用的,还是好好看一下GetFileSize的说明和低双字节+ ...

是将Cutoff = Cutoff + 2147483647==〉Cutoff = Cutoff + 2147483648,刚好差一个数的区别。但是我不明白其中的道理,能指点下吗?
回复 支持 反对

使用道具 举报

发表于 2020-5-24 10:10:19 | 显示全部楼层
本帖最后由 jy4977596491 于 2020-5-24 10:15 编辑

大数一般很少人搞,因为VB的长整型一般情况下足矣,而VB中的长整型是有符号的取值在-2147483648~2147483647之间,像C++可以无符号取值0~4294967295,而这个是32位长整型的最大取值,所以32位的Long不支持超过4G,而VB的Long不支持超过2G。所以对于GetFileSize的高双字和低双字运算可以高双字的值*4294967296#+低高字的值,VB采用的Currency类型来处理64位数据

你的代码 2147483648+ 2147483647不是正好4294967295,就是作者设计的BUG,因为他可能没办法测试大文件,超过4G的文件很少,所以有BUG也正常,作者没有完整测试

点评

受益了,非常感谢!还有一点,你说:高双字的值*4294967296#+低双字的值,为什么不是 *4294967295呢  发表于 2020-5-24 10:24
回复 支持 反对

使用道具 举报

发表于 2020-5-24 16:46:34 | 显示全部楼层
每32位最大4294967295(刚好32个二进制1,11111111111111111111111111111111)
如果要超过32位,那必须要乘4294967296(100000000000000000000000000000000,1个1和32个0),将后32个0保留给低双字做加法用

点评

哦,二进制的算法好复杂啊。看来我的补课去了。谢谢你!  发表于 2020-5-24 18:10
回复 支持 反对

使用道具 举报

发表于 2020-5-24 16:50:29 | 显示全部楼层
看来楼主还得学下基础,不是懂高级编程就好了,低层的也要懂一点的,这个不懂你现在就遇到问题了,如果要移位,你就更不懂了,VB虽然不像C++那样移位很方便,VB用 * 和  \ 也可以左右移位

点评

大咖说的好,必须要懂一些底层的知识啊!谢谢指点!  发表于 2020-5-24 18:12
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-25 09:04:38 | 显示全部楼层
JuncoJet 发表于 2020-5-24 00:48
处理64位数据,你需要实现个大数计算

大咖,我还有几个问题一直想问:VB6已经有20多年了,其编译的32位程序,为什么也能在64位机子上运行,有什么隐患存在吗?有谁尝试过把vb6的编译器提升到64位吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2020-10-20 14:22

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表