代码之家  ›  专栏  ›  技术社区  ›  ashleedawg

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

  •  2
  • ashleedawg  · 技术社区  · 6 年前

    我有整数数组,每一个都是一个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 回复  |  直到 6 年前
        1
  •  4
  •   ashleedawg    6 年前

    事实证明,这是一个罕见的时代,在那里解决方案是如此简单,它被忽视了几个人,包括我自己。


    __ “字节数组” 基本上可以互换。

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

    在VBA中,字符串是 UNICODE 字符串,所以当一个给字节数组分配一个字符串时,它为每个字符存储两位数字。第一个数字是 ASCII 字符和next的值将为0。
    (资料来源: VBA Trick of the Week: VBA中的字节数组- 有用的吉安 )

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

    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
    

    在上述情况下,字符串的长度为 所以数组的大小是 . 值的存储方式如下:

    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 对于字符串,它将存储分配给数组的相同值。

    当数组按元素填充时——或者,在我的例子中,从一个快速的文件操作(见下文)填充时——使用 斯特康夫 是必需的。

    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进行解析/分析,但是找不到一种方法,它在加载或逐字符解析中都不会非常慢。

    举个例子,今天我成功地加载了一个四分之一千兆字节的文件 / 一秒钟,然后把它解析成 第二 字节数组:

    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秒以下 合计。 (万岁!)


    更多信息:

        2
  •  1
  •   Sam    6 年前

    连接是这段代码的昂贵部分。这是你能处理的事情 Join . 我不确定这是 适当的 这样做的方式,但至少更快:

    For i = LBound(myArr) To UBound(myArr)
        myArr(i) = Chr(myArr(i))
    Next
    MsgBox Join(myArr, "")
    
        3
  •  1
  •   Michał Turczyn    6 年前

    如果你对不同的方法很好奇,你总是可以依靠.NET库!在这种情况下,必须添加对 mscorlib.dll 在VBA编辑器中,然后使用以下代码:

    Option Explicit
    Sub BytesToString()
        Dim en As ASCIIEncoding
        Set en = New ASCIIEncoding
    
        Dim myArr(0 To 2) As Byte
        myArr(0) = 72
        myArr(1) = 105
        myArr(2) = 33
    
        MsgBox en.GetString(myArr)
    End Sub
    

    既然你在找 内置 功能,就是一个。但是效率很低。大约比我检查的自定义解码器长10倍。

    更新

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