long类型怎么转成byte型

itcoco 2004-05-08 06:50:37
计算消息体的长度 用long型的变量纪录,考虑倒long型占4个字节,消息头用4个byte放长度 ;我取出消息体的长度转换成字符串然后直接付给一个byte的数组对么?感觉不对,可是应该怎么做?我是这样写的
Dim by1() As Byte
Dim by2() As Byte
Dim i As Long
Dim sStr As String
sStr = "<?xml version='1.0' encoding='gb2312'?> <head><T001>用户登陆</T001></head><body><userName>yutong</userName><password>12345</password></body>"
by1 = sStr
i = UBound(by1) + 1
by2 = CStr(i)
Debug.Print UBound(by2) + 1
我是想用by2存放消息体长度 by1放内容 然后by2与by1连起来
可觉得by2放的就不是正确的消息体的长度
请高手指点一二

ps想知道 例如integer,等数据类型怎么转化成byte类型
...全文
1044 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
KiteGirl 2004-05-10
  • 打赏
  • 举报
回复
这是上面算法的函数和测试代码。
Private Sub Command1_Click()
Dim b() As Byte
b() = BytesGetByLong(-1)
Text1.Text = b(3) & " " & b(2) & " " & b(1) & " " & b(0)
End Sub

Function BytesGetByLong(ByVal pLong As Long) As Byte()
Dim tOutBytes() As Byte
Dim tBytes_Length As Long

Dim tIndex As Long
Dim tIndex_Over As Long

Dim tMinus As Boolean

Dim tLong As Long

tBytes_Length = Len(pLong) - 1
tIndex_Over = tBytes_Length - 1
tMinus = pLong < 0

tLong = tMinus Xor (Abs(pLong) - (tMinus And 1))

ReDim tOutBytes(tBytes_Length)

For tIndex = 0 To tIndex_Over
tOutBytes(tIndex) = (tLong And (&HFF * (16 ^ tIndex))) \ (16 ^ tIndex)
Next

tOutBytes(tBytes_Length) = (tLong And (&H7F * (16 ^ tBytes_Length))) \ (16 ^ tBytes_Length) + (tMinus And &H80)

BytesGetByLong = tOutBytes()
End Function

'将上面函数的pLong和tLong两个变量的long类型直接改为Integer就是Integer版本。

Function BytesGetByInteger(ByVal pLong As Integer) As Byte()
Dim tOutBytes() As Byte
Dim tBytes_Length As Long

Dim tIndex As Long
Dim tIndex_Over As Long

Dim tMinus As Boolean

Dim tLong As Integer

tBytes_Length = Len(pLong) - 1
tIndex_Over = tBytes_Length - 1
tMinus = pLong < 0

tLong = tMinus Xor (Abs(pLong) - (tMinus And 1))

ReDim tOutBytes(tBytes_Length)

For tIndex = 0 To tIndex_Over
tOutBytes(tIndex) = (tLong And (&HFF * (16 ^ tIndex))) \ (16 ^ tIndex)
Next

tOutBytes(tBytes_Length) = (tLong And (&H7F * (16 ^ tBytes_Length))) \ (16 ^ tBytes_Length) + (tMinus And &H80)

BytesGetByInteger = tOutBytes()
End Function


KiteGirl 2004-05-10
  • 打赏
  • 举报
回复
supergreenbean的方法只能处理0和正整数。如果是负值就要溢出。

下面是我将supergreenbean的方法改进了一下。

Private Sub Command1_Click()
Dim a As Long
Dim b(3) As Byte
Dim s As Boolean

a = -1

s = a < 0

If s Then a = Not Abs(a) - 1 '如果是负数,将反补码换算为正整数。

b(0) = a And &HFF&
b(1) = (a And &HFF00&) / &H100&
b(2) = (a And &HFF0000) / &H10000
b(3) = (a And &H7F000000) / &H1000000 + (s And &H80) '如果是负数,则补符号位。
Text1.Text = b(3) & b(2) & b(1) & b(0)
End Sub
itcoco 2004-05-10
  • 打赏
  • 举报
回复
copyMeory和 supergreenbean的方法却是结果都一样
但pigpag建议采用 supergreenbean的方法为什么呢?
我也觉得用 supergreenbean的安全一点,用的放心,不知道大家是怎么想的
呵呵 继续体问
不过贴子马上就可以结了
先谢谢大家了
russule 2004-05-10
  • 打赏
  • 举报
回复
学习
itcoco 2004-05-10
  • 打赏
  • 举报
回复
学倒好多东西
感谢 KiteGirl(小仙妹) supergreenbean(超级绿豆) pigpag(噼里啪啦 - How to prepare for the TOEFL test?)
pigpag 2004-05-10
  • 打赏
  • 举报
回复
另外说一下,因为Win NT严格隔离各个进程的内存空间,所以不会发生由于CopyMemory地址错误导致系统崩溃的情况。一般不考虑偏移量的情况下用CopyMemory不会得到错误的结果,要是偏移量出问题了,结果当然就会不对,也会影响本进城内某些内存数值的错误。这样的错误对于一个进程来说可能是致命的,但是不会影响到全局。
supergreenbean 2004-05-10
  • 打赏
  • 举报
回复
呵呵,我一般都使用copymemory,因为觉得方便~~
pigpag 2004-05-10
  • 打赏
  • 举报
回复
//但pigpag建议采用 supergreenbean的方法为什么呢?

在效果(速度,危险性等等)差不多的情况下,能不用API就不用API是我的选择和建议。
感谢小仙妹提醒,忘记IP的Long是unsigned long,和VB中有符号LONG不兼容,要判断符号问题。用CopyMemory就没有这个问题了。

不好意思,由于符号的问题,我现在支持CopyMemory了 :D
KiteGirl 2004-05-09
  • 打赏
  • 举报
回复
应该如此,将所有关于长度的算式中的2改为4似乎就可以。判断是否正确,可以这样:

1、将一个long数组转换成Byte数组再转换回来,看看所有值是否发生改变。

2、看看Len(tLong())和Len(Bytes())是否一样。

我的方法是将Long以内存存储的形式转换为Byte数组,是存数值。比如,数值305419896保存于long中,以16进制表示为:&H12345678,而内存存储格式为&H78 &H56 &H34 &H12,高位在前,低位在后。不知道这是否是你需要的格式。

另外,我的方法考虑输入数组的上标下标是任意数值,比如-12到+13,因此编写上有些罗嗦。其实,如果假设输入数组下标都是从0开始,上述函数编写起来应该特别简单。
pigpag 2004-05-09
  • 打赏
  • 举报
回复
比较正规的方法是用CopyMemory,不过建议直接用楼上的方法。
supergreenbean 2004-05-09
  • 打赏
  • 举报
回复
你朋友说的办法是这样的么?

Dim a As Long
Dim b(3) As Byte

a = &H12345678
b(0) = a And &HFF&
b(1) = (a And &HFF00&) / &H100&
b(2) = (a And &HFF0000) / &H10000
b(3) = (a And &HFF000000) / &H1000000

这样和CopyMemory的确结果没有什么两样……
itcoco 2004-05-09
  • 打赏
  • 举报
回复
十分感谢 KiteGirl(小仙妹) 你的方法我基本上已领悟
只是今天听另外一个朋友说了种方法 把long型数据转成32位的2进制数据 每8位对应1个字节
我还没试这种方法 不过自以为和copymemory作用是一样的
对么?我的想法?
KiteGirl 2004-05-09
  • 打赏
  • 举报
回复
在Form1里加如下代码:
Private Sub Text2_Change()
priMessageClass.Message = Text2.Text
End Sub

然后将Text1(就是那个多行的文本框)拉宽到容纳16个字符以上。

然后在Text2里输入任意信息,下面就动态输出字节内容。即使字符为空,也不出错。是不是很过瘾……
KiteGirl 2004-05-09
  • 打赏
  • 举报
回复
哈哈!或许下面的程序彻底解决你的问题:

Form1.frm文件:测试窗体。
clsMessageWord.cls文件:MessageWord的类模块(基于modMessageWord)。
modMessageWord.bas文件:MessageWord的公共模块。

Form1.frm文件:

VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3195
ClientLeft = 60
ClientTop = 345
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 '窗口缺省
Begin VB.CommandButton Command2
Caption = "Command2"
Height = 255
Left = 2160
TabIndex = 2
Top = 360
Width = 855
End
Begin VB.CommandButton Command1
Caption = "Command1"
Height = 255
Left = 3720
TabIndex = 1
Top = 480
Width = 855
End
Begin VB.TextBox Text1
Height = 2055
Left = 120
MultiLine = -1 'True
TabIndex = 0
Text = "消息体.frx":0000
Top = 1080
Width = 4455
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private WithEvents priMessageClass As clsMessageWord

Private Sub Command1_Click()
'公共模块测试
Dim tWord As tpMessageWord

Dim tBytes() As Byte

With tWord
.mwMessage = "KiteGirl是个好孩子"
.mwLength = LenB(.mwMessage)
End With

tBytes() = MessageWordCopyToBytes(tWord)

BytesViewToTextBox tBytes(), Text1

'Text1.Text = Len(tWord.mwLength)
End Sub

Private Sub Command2_Click()
'类模块测试
priMessageClass.Message = "KiteGirl是个好孩子"
End Sub

Private Sub Form_Initialize()
Set priMessageClass = New clsMessageWord
End Sub

Private Sub priMessageClass_MessageChange()
BytesViewToTextBox priMessageClass.Bytes, Text1
End Sub




clsMessageWord.cls文件:

VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "clsMessageWord"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private priMessageWord As tpMessageWord

'Message 属性
'Length 属性(只读)
'Bytes 属性(只读)
'MessageChange 事件

Event MessageChange()

Public Property Get Message() As String
Message = priMessageWord.mwMessage
End Property

Public Property Let Message(ByVal vNewValue As String)
priMessageWord.mwMessage = vNewValue
MessageWordChange
End Property

Public Property Get Length() As Long
Length = priMessageWord.mwLength
End Property

Public Property Get Bytes() As Byte()
Dim tBytes() As Byte
tBytes() = MessageWordCopyToBytes(priMessageWord)
Bytes = tBytes()
End Property

Private Sub MessageWordChange()

With priMessageWord
.mwLength = LenB(.mwMessage)
End With

RaiseEvent MessageChange
End Sub





modMessageWord.bas文件

Attribute VB_Name = "modMessageWord"
Type tpMessageWord '消息类型
mwLength As Long
mwMessage As String
End Type

Type tpMessageByteWord '消息字节类型
mwBytes_Length() As Byte
mwBytes_Message() As Byte
End Type

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Function MessageWordCopyToBytes(ByRef pWord As tpMessageWord) As Byte()
'将一个消息类型复制到一个动态Byte数组。
Dim tOutBytes() As Byte

Dim tByteWord As tpMessageByteWord

tByteWord = MessageByteWordGetByMessageWord(pWord)

tOutBytes() = MessageByteWordCopyToBytes(tByteWord)

MessageWordCopyToBytes = tOutBytes()
End Function

Function MessageByteWordGetByMessageWord(ByRef pWord As tpMessageWord) As tpMessageByteWord
'从一个消息类型获得一个消息字节类型。
Dim tOutWord As tpMessageByteWord
Dim tCopyLength As Long

With tOutWord
tCopyLength = Len(pWord.mwLength)
ReDim .mwBytes_Length(0 To tCopyLength - 1)
CopyMemory .mwBytes_Length(0), pWord.mwLength, Len(tCopyLength)

.mwBytes_Message() = pWord.mwMessage
End With

MessageByteWordGetByMessageWord = tOutWord
End Function

Function MessageByteWordCopyToBytes(ByRef pByteWord As tpMessageByteWord) As Byte()
'将一个消息字节类型复制到一个动态Byte数组。
Dim tOutBytes() As Byte

Dim tOutBytes_Lenght As Long

Dim tCopyLenght As Long
Dim tCopyStart As Long

With pByteWord
tOutBytes_Lenght = BytesCount(.mwBytes_Length) + BytesCount(.mwBytes_Message) - 1

ReDim tOutBytes(tOutBytes_Lenght)

tCopyStart = 0
tCopyLenght = BytesCount(.mwBytes_Length)

If CBool(tCopyLenght) Then
CopyMemory tOutBytes(tCopyStart), .mwBytes_Length(0), tCopyLenght
End If

tCopyStart = BytesCount(.mwBytes_Length)
tCopyLenght = BytesCount(.mwBytes_Message)

If CBool(tCopyLenght) Then
CopyMemory tOutBytes(tCopyStart), .mwBytes_Message(0), tCopyLenght
End If

End With


MessageByteWordCopyToBytes = tOutBytes()
End Function

Function BytesCount(ByRef pBytes() As Byte) As Long
'统计字节数组元素数量(空数组容错)。

Dim tOutLong As Long

Err.Clear
On Error Resume Next

tOutLong = UBound(pBytes()) + 1

BytesCount = tOutLong
End Function

Function BytesViewToTextBox(ByRef pBytes() As Byte, ByRef pTextBox As TextBox) As String
'将一个字节数组以16进制字符串表示,如果pTextBox存在则显示到pTextBox。

Dim tOutString As String

Dim tIndex As Long
Dim tByteHex As String

For tIndex = 0 To UBound(pBytes())
tByteHex = Hex(pBytes(tIndex))
If Len(tByteHex) < 2 Then tByteHex = "0" & tByteHex
tOutString = tOutString & " " & tByteHex
If Not CBool((tIndex + 1) Mod 16) Then tOutString = tOutString & vbCrLf
Next

If Not pTextBox Is Nothing Then
pTextBox.Text = tOutString
End If

BytesViewToTextBox = tOutString
End Function
KiteGirl 2004-05-09
  • 打赏
  • 举报
回复
最后提醒你:如果CopyMemory没有得到正确结果,你在做出正式测试结论前最好退出Windows重新启动一下计算机。
我不清楚在Windows下错误拷贝内存会有什么后果,以前在DOS下这样做可能引起一些未知的隐患,导致系统崩溃。因为在DOS下做内存拷贝一旦地址错误,或许你的数据被错误写到其他程序保留的地方,造成未知的后果。
CopyMemory是根据原变量和目的变量来确定地址(有点类似指针的概念),因此使用数组的时候要引用数组的第一个元素。这样比我过去在QB下做类似的事情安全多了,但Length参数如果计算错误,还是比较危险的。
另外,VB里有两个函数在MSDN里没有说明:VarPtr和StrPtr。这两个函数在QB时代就存在(QB下以段地址和偏移量表示内存地址),是用来取变量的内存地址。早期在QB下编程,做不同类型变量转换就是用利用它们来编写类似CopyMenory的函数。但VB中,一些变量的地址是动态的。
所以,使用CopyMemory一般被我戏称为做“脑外科手术”。在编写相关函数前,都反复检查各项参数。
或许Windows下有保护机制,但如果你不确定,在处理完相关函数代码去做别的事情前,一定要重新启动一下机器。

最后,我觉得你编写的程序好象是用来以链表保存不定长数据的。或许你要一段不确定长度的字符串以byte数组存储在某种文件里,而用一个Long类型的头来表示它。如果真是这样,推荐你这样做。

Type tpRecordWord
rwStrLen As Long
rwString As String
End Type

1、先将所有的消息体以tpRecordWord类型保存。

2、将tpRecordWord转换成Byte数组:
(1)确定Byte数组长度:tBytes_Length=Len(tWord.rwStrLen)+LenB(tWord.rwString)-1

(2)ReDim tBytes(tBytes_Length)

(3)CopyMenory tBytes(0),tWord.rwStrLen,Len(tWord.rwStrLen)
将消息体长度拷贝到地址0。

(4)CopyMenory tBytes(Len(tWord.rwStrLen)),tWord.rwString,LenB(tWord.rwString)
将消息体内容拷贝到地址tWord.rwStrLen之后。

3、将每个tpRecordWord拷贝得到的Byte数组拷贝到总数组的地址上。
tMasterAdd相当于链表的指针,是顺序前面的地址累加得到的。
CopyMenory tMasterBytes(tMasterAdd),tSubBytes(0),tSubBytes_Count

以上代码未必准确,仅仅说明原理。
broown 2004-05-09
  • 打赏
  • 举报
回复
up
ryuginka 2004-05-08
  • 打赏
  • 举报
回复
up
itcoco 2004-05-08
  • 打赏
  • 举报
回复
按照KiteGirl(小仙妹)的方法用 CopyMemory函数,我只需要改Public Function BytesCopyByIntegers中 tBytes_Length = ((tIntegers_Length + 1) * 2) - 1
为 tBytes_Length = ((tIntegers_Length + 1) * 4) - 1
//tCopyLength = (tIntegers_Length + 1) * 2为tCopyLength = (tIntegers_Length + 1) * 4
对么?而且觉得这样copy是 yjplus(漠狼)说的传数值还是传数字?
itcoco 2004-05-08
  • 打赏
  • 举报
回复
up一下
大家继续回贴
我先研究下 KiteGirl(小仙妹) 的方法
KiteGirl 2004-05-08
  • 打赏
  • 举报
回复
利用CopyMemory函数。CopyMemory是个API函数,对变量、数组的内存数据进行复制。

下面是一个演示:(代码没有经过测试,不保证准确)

Dim tLong As Long
Dim tBytes() As Byte
ReDim tBytes(0 To 3)

将tlong复制到tBytes()。记得CopyMemory里一定要以tBytes(0),而不是tBytes()表示数组。因为tBytes(0)表示的是tBytes()的地址。

CopyMemory tBytes(0),tLong,4

以下是我编写的两个函数,是我最近编写的一个软件里用到的。采用类似的算法,可以将Long转换为4个Byte。但需要注意的是:CopyMemory需要你对变量长度的计算绝对精确,差一个字节都不可以。否则,后果无法预料。
下面两个函数在我程序里的用途是为了将16Bit UniCode字符串复制为Integer数组,是针对非常巨大的文本文件进行一种过滤操作的一个部分。

BytesCopyToIntegers 将Byte数组复制到相等字节的Integer数组。

BytesCopyByIntegers 从相等字节的Integer数组获得Byte数组。

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Public Function BytesCopyToIntegers(ByRef pBytes() As Byte, Optional ByVal pIntegersOn As Long = 0) As Integer()

Dim tOutIntegers() As Integer
Dim tOutIntegers_Length As Long
Dim tOutIntegers_IndexOn As Long
Dim tOutIntegers_IndexEnd As Long

Dim tBytes() As Byte
Dim tBytes_Length As Long
Dim tBytes_IndexOn As Long
Dim tBytes_IndexEnd As Long

Dim tCopyLength As Long

tBytes() = pBytes()
tBytes_IndexOn = LBound(tBytes)
tBytes_IndexEnd = UBound(tBytes)
tBytes_Length = Abs(tBytes_IndexEnd - tBytes_IndexOn)

tOutIntegers_Length = ((tBytes_Length + 1) \ 2) - 1
tOutIntegers_IndexOn = pIntegersOn
tOutIntegers_IndexEnd = tOutIntegers_Length + tOutIntegers_IndexOn

ReDim tOutIntegers(tOutIntegers_IndexOn To tOutIntegers_IndexEnd)

tCopyLength = tBytes_Length + 1
CopyMemory tOutIntegers(tOutIntegers_IndexOn), tBytes(tBytes_IndexOn), tCopyLength

BytesCopyToIntegers = tOutIntegers()
End Function

Public Function BytesCopyByIntegers(ByRef pIntegers() As Integer, Optional ByVal pBytesOn As Long = 0) As Byte()
Dim tOutString As String

Dim tBytes() As Byte
Dim tBytes_Length As Long
Dim tBytes_IndexOn As Long
Dim tBytes_IndexEnd As Long

Dim tIntegers() As Integer
Dim tIntegers_Length As Long
Dim tIntegers_IndexOn As Long
Dim tIntegers_IndexEnd As Long

Dim tCopyLength As Long

tIntegers() = pIntegers()

tIntegers_IndexOn = LBound(tIntegers)
tIntegers_IndexEnd = UBound(tIntegers)
tIntegers_Length = Abs(tIntegers_IndexEnd - tIntegers_IndexOn)

tBytes_Length = ((tIntegers_Length + 1) * 2) - 1
tBytes_IndexOn = pBytesOn
tBytes_IndexEnd = tBytes_IndexOn + tBytes_Length

ReDim tBytes(tBytes_IndexOn To tBytes_IndexEnd)

tCopyLength = (tIntegers_Length + 1) * 2

CopyMemory tBytes(tBytes_IndexOn), tIntegers(tIntegers_IndexOn), tCopyLength

BytesCopyByIntegers = tBytes()
End Function

加载更多回复(1)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧