将字节数组转换为字符串?

时间:2018-05-21 12:31:51

标签: arrays excel vba byte ascii

我有整数数组,每个都是一个ASCII代码,表示字符串的单个字节。

我可以像这样从数组中生成一个字符串:

Sub BytesToString()

    Dim myArr(): myArr = Array(84, 104, 105, 115, 32, _
        105, 115, 32, 97, 32, 116, 101, 115, 116, 33)

    Dim c As Variant, myStr As String

    For Each c In myArr
        myStr = myStr & Chr(c)
    Next c

    MsgBox myStr

End Sub

...但我觉得这不是"正确的方式" 这样做,特别是因为可能需要重复转换。数组长度会有所不同。

是否有内置更高效的方法来生成带有VBA的字符串?

3 个答案:

答案 0 :(得分:4)

结果证明,这是解决方案如此简单以至于被包括我在内的几个人忽视的罕见情况之一。


“字节数组” 字符串 基本可以互换。

  

在VBA中,字节数组是特殊的,因为与其他数据类型的数组不同,可以将字符串直接分配给字节数组。

     

在VBA中,字符串是UNICODE字符串,因此当将字符串分配给字节数组时,它将为每个字符存储两位数字。前一个数字将是字符的ASCII值,下一个将是0。
   (来源: VBA Trick of the Week: Byte Arrays in VBA -有用的Gyaan

一些代码示例可能展示出比我能解释的更好的代码:

Sub Demo1()
    Dim myArr() As Byte, myStr As String
    myStr = "Hi!"
    myArr() = myStr

    Debug.Print "myStr length: " & Len(myStr)                       'returns "3"
    Debug.Print "Arr bounds: " & LBound(myArr) &"to"& UBound(myArr) 'returns "0 to 5"
    myStr = myArr
    Debug.Print myStr                                               'returns "Hi!"
End Sub

在上述情况下,字符串的长度为 3 ,因此数组的大小为 6 。值将以以下方式存储:

myArr(0) = 72 ' ASCII : code for 'H'
myArr(1) = 0 ' ASCII 'null' character
myArr(2) = 105 ' ASCII : code for 'i'
myArr(3) = 0 ' ASCII 'null' character
...etc...

  

如果要删除这些零,可以使用StrConv函数。在这种情况下,它将仅存储ASCII值。

    myByteArr() = StrConv("StackOverflow", vbFromUnicode)
     

就像可以将字符串直接分配给字节数组一样,也可以将字节数组直接分配给字符串。在上面的示例中,如果将myArr分配给字符串,则它将存储已分配给数组的相同值。

在逐个元素地填充数组时-或者就我而言,是通过快速的文件操作(请参见下文)填充的-需要使用StrConv进行转换的额外步骤。

Sub Demo2()
    Dim myArr(0 To 5) As Byte, myStr As String
    myArr(0) = 104: myArr(1) = 101: myArr(2) = 108
    myArr(3) = 108: myArr(4) = 111: myArr(5) = 33

    Debug.Print "myArr bounds: " & LBound(myArr) &"to"& UBound(myArr) 'returns "0 to 5"

    'since the array was loaded byte-by-byte, we can't "just put back":
    myStr = myArr()
    Debug.Print myStr                               'returns "???" (unprintable characters)
    Debug.Print "myStr length: " & Len(myStr)       'returns "3"

    'using `StrConv` to allow for 2-byte unicode character storage
    myStr = StrConv(myArr(), vbUnicode)
    Debug.Print myStr                                'returns "hello!"
    Debug.Print "myStr length: " & Len(myStr)        'returns "6"
End Sub

字节数组如何使我的日子更好一点...

我有想要使用VBA进行解析/分析的大型文本文件,但是找不到一种在加载或逐个字符进行解析时都不会很慢的方法。

作为一个例子,今天我设法在 1 / 10 th 中加载了一个四分之一千兆字节的文件,并对其进行了解析放入 second 字节数组:

Dim bytes() As Byte
Open myFileName For Binary Access Read As #1
ReDim bytes(LOF(1) - 1&)
Get #1, , bytes
Close #1

For x = LBound(arrOut) To UBound(arrOut)
    Select Case bytes(x)

        (..and if I want the character)
            bytes2(y) = bytes(x)
            y = y + 1
    End Select
Next x
ReDim Preserve bytes2(LBound(bytes2) To y - 1)
txtIn = StrConv(bytes2, vbUnicode)

...然后我的完整字符串在不到5秒内。 (万岁!)


更多信息:

答案 1 :(得分:1)

串联是此代码的昂贵部分。这是您可以使用Join处理的内容。我不确定这是正确的方式,但它至少更快:

For i = LBound(myArr) To UBound(myArr)
    myArr(i) = Chr(myArr(i))
Next
MsgBox Join(myArr, "")

答案 2 :(得分:1)

如果您对不同的方式感到好奇,那么您始终可以信赖.NET库!在这种情况下,您必须在VBA编辑器中添加对./config.status --recheck 的引用,然后使用此代码:

mscorlib.dll

由于您正在寻找内置功能,这就是其中之一。但效率低下。在我检查时,大约比自定义解码器长10倍。

<强>更新

但是,当我在.NET(C#)中检查时,它比OP提供的自定义方法快大约20倍。