• 主页
  • VBS
  • .NET技术
  • VBA
  • VB网络编程
  • VB多媒体
  • VB数据库
  • VB控件
  • VB COM/DCOM
  • VB基础类
  • VB API

【原】Byte()数组的合成和还原。

华芸智森 ESSA 项目总监  2016-12-06 06:39:19


#Region "ConcatBytes"

''' <summary>
''' 数组合成。
''' 合并的数组要用 ConcatBytesDe 还原。
''' *注:还原后数组中原值为 Null/Nothing 的数组会被还原为一个长度为0的数组。
''' </summary>
''' <param name="SourByte"></param>
''' <returns></returns>
Public Function ConcatBytes(ParamArray SourByte()() As Byte) As Byte()

Dim SourLength As Int32 = SourByte.Length

Dim DataBegIndex As Int32 = 4 + (SourLength << 2)
Dim OutLength As Int32 = DataBegIndex

Dim BlockLength((SourLength << 2) - 1) As Byte
Dim DL As Int32
For I As Int32 = 0 To SourLength - 1
If Not SourByte(I) Is Nothing Then
DL = SourByte(I).Length
Buffer.BlockCopy(BitConverter.GetBytes(DL), 0, BlockLength, (I << 2), 4) '//每块的长度。
OutLength += DL
End If
Next

'//*固定数组方式。[比流高 10% ]
Dim OutBytes(OutLength - 1) As Byte
Buffer.BlockCopy(BitConverter.GetBytes(SourLength), 0, OutBytes, 0, 4)
Buffer.BlockCopy(BlockLength, 0, OutBytes, 4, BlockLength.Length)

Dim DXL As Int32 = DataBegIndex
Dim CDL As Int32 = 0
For I As Int32 = 0 To (SourLength - 1)
If Not SourByte(I) Is Nothing Then
CDL = SourByte(I).Length
Buffer.BlockCopy(SourByte(I), 0, OutBytes, DXL, CDL)
DXL += CDL
End If
Next
Return OutBytes

End Function


''' <summary>
''' 数组合成。
''' 合并的数组要用 ConcatBytesDe 还原。
''' *注:还原后数组中原值为 Null/Nothing 的数组会被还原为一个长度为0的数组。
''' 【主要用于对象序列化传输】
''' </summary>
''' <param name="SourByte"></param>
''' <returns></returns>
Public Function ConcatBytes(ByRef SourByte As List(Of Byte())) As Byte()
Return ConcatBytes(SourByte.ToArray)
End Function

''' <summary>
''' 还原 ConcatBytes 合并的 Byte 数组。
''' 添加一个方法。取序列中的第几个值。
''' </summary>
''' <param name="sourByte"></param>
''' <returns></returns>
Public Function ConcatBytesDe(sourByte() As Byte) As Byte()()

If sourByte Is Nothing OrElse sourByte.Length = 0 Then Return {}

Dim sourMaxIndex As Int32 = sourByte.Length - 1

Dim SumBlockByte(3) As Byte
Buffer.BlockCopy(sourByte, 0, SumBlockByte, 0, 4)
Dim SumBlock As Int32 = BitConverter.ToInt32(SumBlockByte, 0) '//数组的个数。

Dim restBytes(SumBlock - 1)() As Byte '//返回值
Dim BlockLengthByte(3) As Byte '//分割的每个数组的长度[二进制值]。
Dim BlockLength As Int32 '//分割的每个数组的长度。
Dim DxBegLength As Int32 = ((SumBlock + 1) << 2) '//数据开始位置 = 块总数*4 + 4
For BlockId As Int32 = 0 To (SumBlock - 1)
'//读块长度。
Buffer.BlockCopy(sourByte, 4 + (BlockId << 2), BlockLengthByte, 0, 4)
BlockLength = BitConverter.ToInt32(BlockLengthByte, 0)
If BlockLength > 0 Then
'//读值
Dim TempByte(BlockLength - 1) As Byte
Buffer.BlockCopy(sourByte, DxBegLength, TempByte, 0, BlockLength)
restBytes(BlockId) = TempByte
'//计算下一个数据开始位置。
DxBegLength += BlockLength
Else
restBytes(BlockId) = {}
End If
Next

Return restBytes

End Function

''' <summary>
''' 取 ConcatBytes [合并数组]的指定下标的值。
''' 注:下标是从0开始。
''' </summary>
''' <param name="sourByte"></param>
''' <param name="Index"></param>
''' <returns></returns>
Public Function ConcatBytesIndexDe(sourByte() As Byte, Index As Int32) As Byte()

If sourByte Is Nothing OrElse sourByte.Length = 0 Then Return Nothing

Dim sourMaxIndex As Int32 = sourByte.Length - 1

Dim SumBlockByte(3) As Byte
Buffer.BlockCopy(sourByte, 0, SumBlockByte, 0, 4)
Dim SumBlock As Int32 = BitConverter.ToInt32(SumBlockByte, 0) '//数组的个数。

Dim restBytes() As Byte = Nothing '//返回值
Dim BlockLengthByte(3) As Byte '//每块的长度[二进制值]。
Dim BlockLength As Int32 '//每块的长度。
Dim DxBegLength As Int32 = ((SumBlock + 1) << 2)
For BlockId As Int32 = 0 To SumBlock - 1
Buffer.BlockCopy(sourByte, 4 + (BlockId << 2), BlockLengthByte, 0, 4)
BlockLength = BitConverter.ToInt32(BlockLengthByte, 0)
If BlockId = Index Then
ReDim restBytes(BlockLength - 1)
Buffer.BlockCopy(sourByte, DxBegLength, restBytes, 0, BlockLength)
End If
DxBegLength += BlockLength
Next

Return restBytes

End Function

#End Region

#Region "ByteMergeIndex"

''' <summary>
''' 带索引编号的二进制块。
''' 主要用于 WCF 的参数传输。
''' 例如合成:{ {用户名Has256} {时效密钥} {TOKEN} {AESPACK} {RSAPACK} } {MD5}
''' [ 每线程约 850万-950万/S ]
''' </summary>
''' <param name="SourByte"></param>
''' <returns></returns>
Public Function MergeIndexBytes(ParamArray SourByte()() As Byte) As Byte()

'//输出 = {总块数},{ 块开始位置,块长度 },{数据}
Dim SourLength As Int32 = SourByte.Length
Dim BlockLengthBytes((SourLength << 3) - 1) As Byte '//每一个块的位置 = 开始 + 长度 = 8 Byte
Dim ItemBegIndex As Int32 = 4 + (SourLength << 3) '// 4 = 总长度占的BYTE数。
Dim DXL As Int32 = ItemBegIndex '//正式数据的起始位置
Dim DL As Int32
For I As Int32 = 0 To SourLength - 1
If Not SourByte(I) Is Nothing Then
DL = SourByte(I).Length
Buffer.BlockCopy(BitConverter.GetBytes(ItemBegIndex), 0, BlockLengthBytes, (I << 3), 4) '//块 开始位置
Buffer.BlockCopy(BitConverter.GetBytes(DL), 0, BlockLengthBytes, (I << 3) + 4, 4) '//块 长度。
ItemBegIndex += DL
End If
Next

'//使用数组。比流方式快 10% 左右。
Dim OutBytes(ItemBegIndex - 1) As Byte
Buffer.BlockCopy(BitConverter.GetBytes(SourLength), 0, OutBytes, 0, 4)
Buffer.BlockCopy(BlockLengthBytes, 0, OutBytes, 4, BlockLengthBytes.Length)

Dim CDL As Int32 = 0
For I As Int32 = 0 To (SourLength - 1)
If Not SourByte(I) Is Nothing Then
CDL = SourByte(I).Length
Buffer.BlockCopy(SourByte(I), 0, OutBytes, DXL, CDL)
DXL += CDL
End If
Next
Return OutBytes

End Function

''' <summary>
''' 取 MergeIndexBytes 合并的数组的块的数量。
''' </summary>
''' <param name="ValBytes"></param>
''' <returns></returns>
Public Function MergeIndexBytesBlockCount(ByRef ValBytes() As Byte) As Int32

If ValBytes Is Nothing OrElse ValBytes.Length <= 4 Then Return 0

Dim SumBlockByte(3) As Byte
Buffer.BlockCopy(ValBytes, 0, SumBlockByte, 0, 4)
Return BitConverter.ToInt32(SumBlockByte, 0)

End Function

''' <summary>
''' 根据 MergeIndexBytes 合并的数组,用下标取值。
''' 注:下标是从0开始。【 取值速度每线程约 500万-600万/S 】
''' </summary>
''' <param name="ValBytes">要合成的数组。</param>
''' <param name="Index">值的下标。注:下标是从0开始。这个下标不是指Byte中的下标,是指原始值的下标。</param>
''' <returns> 相应下标的 Byte() 。</returns>
Public Function MergeIndexBytesDe(ByRef ValBytes() As Byte, Index As Int32) As Byte()

If ValBytes Is Nothing OrElse ValBytes.Length = 0 Then
Return Nothing
End If

Dim VL As Int32 = ValBytes.Length

'//总块数
Dim SumBlockByte(3) As Byte
Buffer.BlockCopy(ValBytes, 0, SumBlockByte, 0, 4)
Dim SumBlock As Int32 = BitConverter.ToInt32(SumBlockByte, 0)
If Index >= SumBlock OrElse SumBlock >= VL OrElse SumBlock <= 0 Then
Return Nothing
End If

'//块位置。左4位。
Dim BlockBegIndexByte(3) As Byte
'// + 4 是因为总数据的第一个位置是总块数。(Index << 3) = Index * 8
Buffer.BlockCopy(ValBytes, (Index << 3) + 4, BlockBegIndexByte, 0, 4)
Dim BlockBegIndex As Int32 = BitConverter.ToInt32(BlockBegIndexByte, 0)
If BlockBegIndex < 0 OrElse BlockBegIndex > VL Then
Return Nothing
End If

'//块长度。右4位。
Dim BlockLengthByte(3) As Byte
Buffer.BlockCopy(ValBytes, (Index << 3) + 8, BlockLengthByte, 0, 4)
Dim BlockLength As Int32 = BitConverter.ToInt32(BlockLengthByte, 0)
If (BlockBegIndex + BlockLength) > VL Then
Return Nothing
End If

'//读块数据。
Dim restBytes(BlockLength - 1) As Byte
Buffer.BlockCopy(ValBytes, BlockBegIndex, restBytes, 0, BlockLength)

Return restBytes

End Function

#End Region
...全文
585 点赞 收藏 5
写回复
5 条回复
by_封爱 2017年07月05日
回复 点赞
AlanCookies 2017年06月17日
这么好的函数 收下了
回复 点赞
华芸智森 2016年12月06日
上在有个函数写少了一句。
    ''' <summary>
    ''' 取 ConcatBytes [合并数组]的指定下标的值。
    ''' 注:下标是从0开始。
    ''' </summary>
    ''' <param name="sourByte"></param>
    ''' <param name="Index"></param>
    ''' <returns></returns>
    Public Function ConcatBytesIndexDe(sourByte() As Byte, Index As Int32) As Byte()

        If sourByte Is Nothing OrElse sourByte.Length = 0 Then Return Nothing

        Dim sourMaxIndex As Int32 = sourByte.Length - 1

        Dim SumBlockByte(3) As Byte
        Buffer.BlockCopy(sourByte, 0, SumBlockByte, 0, 4)
        Dim SumBlock As Int32 = BitConverter.ToInt32(SumBlockByte, 0) '//数组的个数。

        Dim restBytes() As Byte = Nothing   '//返回值
        Dim BlockLengthByte(3) As Byte      '//每块的长度[二进制值]。
        Dim BlockLength As Int32            '//每块的长度。
        Dim DxBegLength As Int32 = ((SumBlock + 1) << 2)
        For BlockId As Int32 = 0 To SumBlock - 1
            Buffer.BlockCopy(sourByte, 4 + (BlockId << 2), BlockLengthByte, 0, 4)
            BlockLength = BitConverter.ToInt32(BlockLengthByte, 0)
            If BlockId = Index Then
                ReDim restBytes(BlockLength - 1)
                Buffer.BlockCopy(sourByte, DxBegLength, restBytes, 0, BlockLength)
                Exit For
            End If
            DxBegLength += BlockLength
        Next

        Return restBytes

    End Function
回复 点赞
华芸智森 2016年12月06日
BYTE数组的合成与分解在数据序列化,反列列化,保存,缓存 等场合用得很多。 这几个函数是我一直在用的。速度和效率还是不错。 你还可以派生出自己的WCF格式。例如:


    ''' <summary>
    ''' 登录前-透明包。
    ''' </summary>
    Public Class SendToServerTranPack

        Public AppCode() As Byte
        Public UserNameHas256 As String
        Public PwsTime() As Byte
        Public BlnSuccess As Boolean = False

        Sub New()
            '//
        End Sub

        Sub New(MeByte() As Byte)
            FromBytes(MeByte)
        End Sub

        Public Function ToBytes() As Byte()
            Try
                Dim Val(2)() As Byte
                With Me
                    ValToByte(.AppCode, Val(0))
                    ValToByte(.UserNameHas256, Val(1))
                    ValToByte(.PwsTime, Val(2))
                End With
                BlnSuccess = True
                Return BaseDBHelper.MyConvert.ConcatBytes(Val)
            Catch ex As Exception
                BlnSuccess = False
            End Try

        End Function

        Public Sub FromBytes(MeByte() As Byte)
            Try
                Dim Val()() As Byte = BaseDBHelper.MyConvert.ConcatBytesDe(MeByte)
                With Me
                    ValToByteDe(.AppCode, Val(0))
                    ValToByteDe(.UserNameHas256, Val(1))
                    ValToByteDe(.PwsTime, Val(2))
                End With
                BlnSuccess = True
            Catch ex As Exception
                BlnSuccess = False
            End Try
        End Sub

    End Class
也可以改定NET本身的序列化。例如用得最多的 DataTable . 使用自己定义的序列化。速度比NET二进制快7倍左右。数据量只有NET二进制序列化的一半。
回复 点赞
发动态
发帖子
VB
创建于2007-09-28

1.1w+

社区成员

11.0w+

社区内容

VB技术相关讨论,主要为经典vb,即VB6.0
社区公告
暂无公告