回 帖 发 新 帖 刷新版面

主题:如何在VB中处理64位整形数据?

    VB中的整型数据是16位或者32位的,现在文件中有一个64位的整形数据,要用读出它,用什么处理方法呢?

回复列表 (共22个回复)

11 楼

[em2]

12 楼

[em2]

13 楼

很不幸,俺真没亲自试过。不过俺也算科班出身,学过编译原理、操作系统、汇编语言、组成原理、C/C++、VB、Delphi,关于数据长度这点,俺心里还是很清晰的。(指令+操作数编码为不等长二进制,执行时读到内存由CPU译码执行,也就是我前面说的“固化”)

然后又很不幸,俺现在用的是Vista x64 With SP1,也就是你传说中的“64位系统”,所以在你的提示下,俺现在可以写代码亲自试一下。

[code=c]
Option Explicit

Private Const TEMP_FILE As String = "D:\temp.bin"

Private Sub WriteFile()
    Dim byt(15) As Byte
    Dim i As Long
    For i = 1 To 16
        byt(i - 1) = &H10 + i
    Next
    
    Open TEMP_FILE For Binary Access Write As #1
        Put #1, , byt
    Close #1
End Sub
[/code]
对于这段,你没有异议吧?我写入的是Byte,不论在哪都一样,最张文件十六进制形式是这样的:
11 12 13 14 15 16 17 18 ...,一共16字节,足够了吧?

[code=c]
Private Sub Read1Long()
    Dim ret As Long
    
    Open TEMP_FILE For Binary Access Read As #1
        Get #1, , ret
    Close #1
    MsgBox (Hex(ret))
End Sub
[/code]
很明显,这段是读取一个Long值并用对话框显示的。

OK,让我们调用一下:
[code=c]
Private Sub Form_Load()
    WriteFile
    
    Read1Long
    
    Kill TEMP_FILE
    
    End
End Sub
[/code]
写入文件,读取,删除

编译后,在我x64上结果为“14131211”,也就是一个4字节的整数,因为x86兼容的CPU是低位在前的,结果也符合我们事先的预期。
然后,我把这个程序压缩发给使用32位XP的朋友,叫他运行一下发回结果给我。很不幸,结果一样还是“14131211”

如果结果与我事先预期的不一致,那我这么多年真是白学了。

另外要说一下的就是我对VB6的一些理解:VB6已经算是编译型的语言了(除非你特意到编译选项里选择P-Code),它编译的最终结果为Native Code(本地/原生代码),只是很多函数要跳到msvbvm60.dll里面去执行而已。

对于.net,俺自问不熟,不过俺听说.net里的数据类型不论在32位还是64位,其数据长度都是一样的,并不是你传说中的在32位/64位系统就不同。

[quote]
我都说了.不是指令是64位.是读文件的时候读出的是64位.
就是说在VB6中.你使用GET从一个2进制文件中读一个LONG出来.则在32位系统中读出4个字节.在64位系统中读出8个字节.并不是指令变了.是读出的数据变了.VB6毕竟是解释型 的.GET函数的底层实现可能是使用了系统的API.在32-64两个系统中的API的数据类型字长是不一样的.我已经试过.如果你有任何疑问.请装一个64位操作系统验证后说明.
[/quote]
VB编译的EXE是PE格式的二进制文件,主要内容是指令+操作数让CPU来执行。如果VB6编译器根本不支持64位,它怎么能生成64位的操作数呢?指令的操作数是严格定义好的,怎么可以同一条指令,一下输入32位操作数,一下输入64位操作数让CPU执行呢?
如果“64位系统中读出8个字节”,那为什么在我的x64上还是显示“14131211”呢?
你说的调用API的事,如果我传个32位的数,叫API帮我加1,API怎么会返回一个64位的结果给我呢?如果你还是要坚持,我可以把"Get #1, , ret"的最张实现C代码写给你看:
int ret;      //缓冲区,用来接收API返回的读取到的数据
DWORD dwLen;  //用来接收API返回的实际读取的字节数
ReadFile(hFile, &ret, sizeof(ret), &dwLen, NULL);
hFile就是文件句柄,在VB里与#1 #2之类的组成一个表,根据VB里的文件号能找到对应的文件句柄。
ret是读取出来的结果,VB编译时已经确定好是32位整数了,所以接下来的sizeof(ret)就是4,也就是告诉API,我只要读4个字节的数据,API怎么会笨到读了8个数据返回给你呢?如果它这样做,肯定是写内存越界了,把ret后面的4字节也写掉了,那软件很可能会出现传说中的“0x040xxxx内存写入读取错误”之类的东西。

实践是很重要,但当你的实践号称推翻“1+1=2”的理论,那只能请你自己检查下“实践”的问题所在。

等你懂点编译原理、懂点汇编语言、懂点组成原理,你再来看下自己说的话,你会觉得很可笑。一辆自行车开到高速公路怎么就变成了大卡车?
[em4][em4][em4]

14 楼

[quote]很不幸,俺真没亲自试过。不过俺也算科班出身,学过编译原理、操作系统、汇编语言、组成原理、C/C++、VB、Delphi,关于数据长度这点,俺心里还是很清晰的。(指令+操作数编码为不等长二进制,执行时读到内存由CPU译码执行,也就是我前面说的“固化”)

然后又很不幸,俺现在用的是Vista x64 With SP1,也就是你传说中的“64位系统”,所以在你的提示下,俺现在可以写代码亲自试一下。

[code=c]
Option Explicit

Private Const TEMP_FILE As String = "D:\temp.bin"

Private Sub WriteFile()
    Dim byt(15) As Byte
    Dim i As Long
    For i = 1 To 16
        byt(i - 1) = &H10 + i
    Next
    
    Open TEMP_FILE For Binary Access Write As #1
        Put #1, , byt
    Close #1
End Sub
[/code]
对于这段,你没有异议吧?我写入的是Byte,不论在哪都一样,最张文件十六进制形式是这样的:
11 12 13 14 15 16 17 18 ...,一共16字节,足够了吧?

[code=c]
Private Sub Read1Long()
    Dim ret As Long
    
    Open TEMP_FILE For Binary Access Read As #1
        Get #1, , ret
    Close #1
    MsgBox (Hex(ret))
End Sub
[/code]
很明显,这段是读取一个Long值并用对话框显示的。

OK,让我们调用一下:
[code=c]
Private Sub Form_Load()
    WriteFile
    
    Read1Long
    
    Kill TEMP_FILE
    
    End
End Sub
[/code]
写入文件,读取,删除

编译后,在我x64上结果为“14131211”,也就是一个4字节的整数,因为x86兼容的CPU是高位在前的,结果也符合我们事先的预期。
然后,我把这个程序压缩发给使用32位XP的朋友,叫他运行一下发回结果给我。很不幸,结果一样还是“14131211”

如果结果与我事先预期的不一致,那我这么多年真是白学了。

另外要说一下的就是我对VB6的一些理解:VB6已经算是编译型的语言了(除非你特意到编译选项里选择P-Code),它编译的最终结果为Native Code(本地/原生代码),只是很多函数要跳到msvbvm60.dll里面去执行而已。

对于.net,俺自问不熟,不过俺听说.net里的数据类型不论在32位还是64位,其数据长度都是一样的,并不是你传说中的在32位/64位系统就不同。

[quote]
我都说了.不是指令是64位.是读文件的时候读出的是64位.
就是说在VB6中.你使用GET从一个2进制文件中读一个LONG出来.则在32位系统中读出4个字节.在64位系统中读出8个字节.并不是指令变了.是读出的数据变了.VB6毕竟是解释型 的.GET函数的底层实现可能是使用了系统的API.在32-64两个系统中的API的数据类型字长是不一样的.我已经试过.如果你有任何疑问.请装一个64位操作系统验证后说明.
[/quote]
VB编译的EXE是PE格式的二进制文件,主要内容是指令+操作数让CPU来执行。如果VB6编译器根本不支持64位,它怎么能生成64位的操作数呢?指令的操作数是严格定义好的,怎么可以同一条指令,一下输入32位操作数,一下输入64位操作数让CPU执行呢?
如果“64位系统中读出8个字节”,那为什么在我的x64上还是显示“14131211”呢?
你说的调用API的事,如果我传个32位的数,叫API帮我加1,API怎么会返回一个64位的结果给我呢?如果你还是要坚持,我可以把"Get #1, , ret"的最张实现C代码写给你看:
int ret;      //缓冲区,用来接收API返回的读取到的数据
DWORD dwLen;  //用来接收API返回的实际读取的字节数
ReadFile(hFile, &ret, sizeof(ret), &dwLen, NULL);
hFile就是文件句柄,在VB里与#1 #2之类的组成一个表,根据VB里的文件号能找到对应的文件句柄。
ret是读取出来的结果,VB编译时已经确定好是32位整数了,所以接下来的sizeof(ret)就是4,也就是告诉API,我只要读4个字节的数据,API怎么会笨到读了8个数据返回给你呢?如果它这样做,肯定是写内存越界了,把ret后面的4字节也写掉了,那软件很可能会出现传说中的“0x040xxxx内存写入读取错误”之类的东西。

实践是很重要,但当你的实践号称推翻“1+1=2”的理论,那只能请你自己检查下“实践”的问题所在。

等你懂点编译原理、懂点汇编语言、懂点组成原理,你再来看下自己说的话,你会觉得很可笑。一辆自行车开到高速公路怎么就变成了大卡车?
[em4][em4][em4][/quote]

那我再试一下.有结果了告诉你.至少我上次试的时候读的数据不是你那样的.
呵呵.

15 楼

如果可以.希望加你QQ一起研究.我有一个程序在两个位宽不同的系统中运行结果不一样.
我现在没有64位系统.希望能帮忙测试.

16 楼

你打包上传,我看下。

17 楼

刚才我又装了一个XP-64EDITION.
试了一下.你是对的.

不过.我上次装的时候真的是读出来8个字节.
我是一个一个数据弹出来看的.跟踪后发现每次读的都不是我想要的数据.

但这回装了以后又读的是4字节了....
嗷嗷郁闷中.

我说的那个程序就是网上我发的那个劲舞团舞步提示软件.
那个舞步数据文件就是二进制的.每个步子都是一个LONG值.
以前测试的时候.在32位下运行正确.
但在64位下数据文件加载不了.后来发现是里面的数据读的时候都不对.

但这次我弄过以后又可以加载了.你试试那个软件吧.

感谢"广告专业户"指正错误.我已经把我说错的都删除了.省得误导新手.
64位还有待研究呀.呵呵.

18 楼


谢谢各位大侠指点和讨论!

VB里好像没有int64或_int64数据类型。

我的问题已经解决了,就是定义一个“货币”数据类型(64位)把数据读出,再对小数点位置进行处理就可以了。

19 楼

用C做个动态库不行吗?
还是想做个绿色软件?

20 楼

其实VB.NET能定义INT64并不能说它就是编译为64位代码了,变量可以放内存的,连续8个字节.毕竟寄存器数量有限,所以寄存器变量还是很少的,可能编译器会把一些循环变量优先用寄存器.在32位系统,你不可能把64位的数据放进32位的寄存器中.

我来回复

您尚未登录,请登录后再回复。点此登录或注册