`

VB 字节数组和字符串的转换问题 (String<>Byte)

    博客分类:
  • vb
阅读更多

一、 前言

   数据类型转换在编程中经常用到,VB6提供了一整套类型转换的函数。但是,在进行类型转换时,有时候仅仅依靠VB提供的函数是不能达到自己的目的的。因此,需要考虑用其他的方法来完成数据类型转换。本文仅谈VB6中字节数组和字符串的相互转换过程中应注意的问题及其解决办法。

   在Visual Basic中使用Byte数组主要是为了32位API函数的参数传递和函数的返回。在32位的Visual Basic版本中,字符串被假定为Unicode字符,其中每个字符占用两个字节。系统自动地将Unicode的两个连续字节转换成1个字节的ANSI字符。但是,如果该字符串包含二进制数据,其内容将变得很难理解。例如,一个汉字是两个字节,在Visual Basic 6.0中的长度就只是1,这将给我们计算单个汉字的国标码带来一些麻烦。有了Byte数组,这些问题就将迎刃而解。

   另外,Visual Basic中的字符串和C语言中的字符串有一些不同,本文将给出一个函数,把C字符串转换成Visual Basic字符串。

二、 用Byte数组代替字符串

   Byte数组包含的是0-255之间的ASCII码字符,它不会象字符串那样被系统作预处理。你可以在很多API函数中用来Byte数组代替字符串。

   例如,下面的代码中用GetSystemDirectory这个Windows API函数来取得Windows的系统路径。一共有两段代码,一段代码是传递一个字符串来存储函数返回的系统路径,另一段代码是传递一个Byte数组来代替字符串。

   为了更好地比较,两段代码的不同部分都用黑体标出。读者可以仔细比较这两段代码的差异,这样您会更深入地理解Byte数组和字符串的差别。

   把这两段代码的任何一段放入一个窗体中运行,但击窗体的空白区域,你将会在窗体中看到Windows的系统路径。

   下面是使用字符串的代码:

Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long

Private Sub
Form_Click()
 
Dim n As Integer
  Dim str As String

  str = Space$(256)
  n = GetSystemDirectory(str,
256)
  str = Left$(str, n)
  Print str
End Sub


   在上面这段代码中,字符串参数lpBuffer返回Windows的系统路径。在函数调用之前,将变量预定义成256个字符,并在函数返回时清除多余的字符。

注意:
   在调用API函数之前,通常都需要预先定义一个字符串或者Byte数组以供API函数存储数据。应该养成这种良好的编程习惯。否则,你的程序有可能崩溃,甚至导致你的系统崩溃。

   下面是使用Byte数组的代码:

Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByRef lpBuffer As Byte, ByVal nSize As Long) As Long

Private Sub
Form_Click()
 
Dim n As Integer
  Dim Buffer() As Byte
  Dim strA as String

  Buffer=Space$(256)
  n = GetSystemDirectory(Buffer(
0), 256)
  strA=StrConv(Buffer,vbUnicode)
  strA = Left$(strA, n)
  Print strA
End Sub


   不知道读者注意到没有,第二段代码中的GetSystemDirectory API函数的声明已经改变了。第一个参数的声明由一个ByVal字符串变成了一个ByRef的Byte数组,即由声明: ByVal lpBuffer As String 变成了 ByRef lpBuffer As Byte

   传递字符串时,需要一个ByVal修饰符来把字符串缓冲区传递到API函数中,因为字符串变量实际上指示了字符串内容所在的内存地址。在C语言术语中,这代表了一个指向指针的指针。ByVal意味着被传递的是一个指向实际字符串内容的内存地址。而在传递Byte数组Buffer(0)时,使用ByRef修饰符来传递变量,它相当于传递了数组中第一个字节内容的地址。事实上,这两种结果是一样的。

strA=StrConv(Buffer,vbUnicode)

   这行代码把Byte数组的二进制数据转换成一个合法的Visual Basic字符串。

三、 Byte数组和字符串之间的赋值

   为了简化Byte数组和字符串之间的数据传递,允许你在任何动态Byte数组和任何字符串之间直接互相赋值。例如:
Buffer=strA 和 StrA=Buffer

注意:
   当且仅当Byte数组是动态的,而不是固定大小时,你才可以把一个字符串直接赋给一个Byte数组。

   声明一个动态的Byte数组最简单的方法是在Dim语句中使用空参数,例如: Dim Buffer() as Byte

   当你把一个字符串赋给一个动态Byte数组时,数组中的字符数将是字符串的字符数目的两倍。这是因为Visual Basic中字符串使用Unicode,并且每个Unicode字符的实际大小是两个字节。当把一个ASCII字符转换成一个Byte数组时,数组中的另一个字节将是0。

   向Unicode的转换是将每个在缓冲区中的字符转换成2个字节,从而实际上加倍了存储在结果字符串的中字节数目,当你认为函数Len(strA)得到的尺寸大小和Unicode转换后的Ubound(Buffer)函数所返回的尺寸大小相同时,上述特点就不很明显了。但是,函数LenB(strA)确实返回一个2倍于Len(strA)返回值的数值。这是因为Len函数返回的是字符串中字符的数目,而LenB函数返回的是字符串中字节的数目。一个Unicode串的字符长度仅仅是该串中实际字节数目的一半,这是因为每个Unicode字符2个字节。

四、 字符串转换成VB字符串

   当我们在VB中调用Win32 API函数时,如果函数的返回值是一个字符串,那一般有如下三种情况:

   1. 函数预先要求你提供一个有固定空间的字符串,以供存储函数的返回值。

   2. 函数的返回是一个以Null结尾的C字符串,而不是正规的VB字符串。

   3. Win32 API函数有时候会返回另一种类型的字符串。这种类型的字符串在单个缓冲区内保存了多个字符串值,每个值之间用Null隔开,结尾的是两个Null,一个Null是最后一个字符串值的结尾符,另一个Null是整个字符串的结尾符。这其实就是我们通常在C中遇到的字符串数组。

   第一种情况很好办,只无原则预先定义好一个空间足够大的字符串,然后把API函数的返回值赋于这个字符串就可以了。例如,如果你已经知道函数返回值最多不会走过256个字符,可以这样编码如下:

Dim sAPIReturn as string
SAPIReturn=Space$(256)
SAPIReturn=API_Function(…)


   对于第二和第三种情况,就必须把返回的C字符串成标准的VB字符串。下面这个函数CStringToVBString把一个以Null结尾的C字符串成VB字符串。

Public Function CStringToVBString(psCString As String) As string
  '参数psCString是一个待转换的C字符串
  '函数返回Null左边所有的字符

  dim sReturn as string
  dim iNullCharPos As Integer

  iNullCharPos=InStr(psCString,vbNullChar)
 
if iNullCharPos >0 then
   sReturn =left(psCString, iNullCharPos -1)
 
else
   sReturn =pscstring
 
end if
  CStringToVBString=sReturn
End function


   下面这个过程把一个含有多个C字符串的缓冲区转换成一个字符串数组。

Public Sub MultiCStringToStringArray(psMultiCString As String, psaStrings() As String)
 
'参数psMultiCString是待转换的多个C字符串
  '参数psaStrings是返回的VB字符串数组,调用之前它必须是一个动态的空数组

  Dim iNullPos As Integer
  Dim iPrevPos As Integer
  Dim iIdx As Integer

  '初始化字符串数组
  iIdx = 0
  ReDim psaStrings(0 To iIdx 1)
  psaStrings(iIdx
1) = ""
  Do
   iNullPos = InStr(iPrevPos 1, psMultiCString, vbNullChar)
  
If iNullPos > iPrevPos 1 Then
    '把找到的C字符串赋值给字符串数组
    psaStrings(iIdx) = Mid$(psMultiCString, (iPrevPos 1), ((iNullPos - 1) - iPrevPos))
    iIdx = iIdx
1
    ReDim Preserve psaStrings(0 To iIdx)
    iPrevPos = iNullPos
  
Else
    '找到了两个Null字符,去掉最后一个,然后退出
    ReDim Preserve psaStrings(0 To iIdx - 1)
   
Exit Do
   End If
  Loop
End Sub


   当调用Win32 API函数时,使用这两个简单的函数,你可以消除很多冗余的代码,加快开发步伐。

注意:
   当你为API的返回值预先分配字符串的空间时,一定不要忘了空间内必须包含Null结束符。另外,建议你在使用API时,最好对每个变量都进行声明,加上下面这句代码: Option Explicit

五、小结

   VB6中字节数组和字符串的相互转换是编程中,尤其是新手使用中最为头疼的问题。本文归纳了软件开发过程中使用二者的典型情况及其应该注意的问题,供参考。不当之处还请读者批评指正。

分享到:
评论

相关推荐

    vb6.0 字节数组和字符串的相互转换.rar

    将字节数组转换回字符串,同样使用`StrConv`函数,但这次将`Conversion`设置为`vbUnicode`(对于非ASCII字符)或`vbFromUnicode`(对于ASCII字符)。由于VB6.0默认使用Unicode编码,因此通常使用`vbUnicode`。 示例...

    VB.NET 字符串与二进制间的转换

    例如,`BitConverter.ToString(bytes)`可以将字节数组转换为十六进制字符串,而`BitConverter.ToInt32(bytes, startIndex)`将字节数组的一部分转换为整数。 3. **BinaryWriter 和 BinaryReader** 这两个类提供了...

    实现字节数组同c中的字符数组一样好用(6KB)...

    在这个场景下,它可能详细介绍了如何将VB的字节数组与C的字符数组等效操作,例如如何进行字符串的编码和解码,以及如何处理字符串边界条件。 `strtest.vbp`和`strtest.vbw`是Visual Basic项目文件和工作空间文件。`...

    vb.rar_resolution_vb string byte

    在VB.NET编程环境中,将字符串(String)与字节数组(Byte())相互转换是常见...通过学习和理解这个压缩包提供的内容,开发者可以提升他们在VB.NET中处理字符串和字节数组转换的能力,从而编写出更高效、更健壮的代码。

    VB将二进制图片文件转换为Base64字符串文本

    在VB中,我们可以使用System.Text.Encoding类的GetBytes方法将字符串转换为字节数组,然后使用Convert.ToBase64String方法将字节数组转换为Base64字符串。相反,如果你想从Base64字符串恢复原始的二进制数据,可以...

    获取中文字符串长度的函数(VB6.0代码编写)

    在VB6.0编程环境中,处理中文字符串时,我们经常会遇到一个问题:如何准确地计算一个包含中文字符的字符串的长度。由于中文字符占用的字节数不同于英文字符(每个中文字符通常占用2个字节,而英文字符占用1个字节)...

    VB 将二进制图片文件转换为Base64字符串文本.rar

    之后,`Convert.ToBase64String`方法可以将这个字节数组转换为Base64字符串。反向操作,即从Base64字符串还原图片,也是类似的步骤,但需要使用`Convert.FromBase64String`来解码,然后再将字节数组写入到新的二进制...

    VB获取字符串的字节总数

    在VB(Visual Basic)编程环境中,我们经常需要处理字符串数据,并且在某些情况下,了解字符串的字节总数是非常重要的。字节总数可以帮助我们计算存储需求、传输数据的大小或者进行编码转换等操作。本篇文章将深入...

    vb.net编码解码例子form字符集转换

    `System.Text.Encoding`类同样提供了解码方法,如`GetString()`方法,用于将字节数组转换回字符串。 4. **VB.NET中的编码解码**:在VB.NET中,我们可以创建`Encoding`对象来处理特定的字符集。例如,`Dim utf8 As ...

    VB6.0 UTF-8转换GB2312函数

    ' 将转换后的字节数组转换回字符串 Utf8ToGb2312 = StrConv(gb2312Bytes, vbUnicode) End Function ``` 这个函数通过遍历UTF-8字节序列,对每个字符进行判断和转换。对于单字节字符,直接复制;对于双字节UTF-8...

    VB 将二进制图片文件转换为Base64字符串文本

    2. **编码为Base64字符串**:VB.NET提供了`Convert.ToBase64String`方法,将字节数组转换为Base64字符串。 ```vb Dim base64String As String = Convert.ToBase64String(imageData) ``` 3. **处理结果**:转换后...

    VB字符串处理

    通过以上介绍,我们可以看到VB提供了丰富的工具来进行字符串处理,包括类型转换、字符串与数字之间的转换、日期时间的格式化以及字符串的检验和比较等功能。掌握这些技术对于提高VB应用程序的质量和性能至关重要。

    字节数组中的SID到VB.NET中的字符串版本

    在VB.NET中,我们可以利用内置的类和方法,将字节数组形式的SID转换为易于理解和使用的字符串格式。通过这个过程,开发者可以更方便地进行权限检查、权限赋值等操作,提升程序的安全性和功能性。

    VB模块_MD5字符串与文件加密

    这段代码中,`GetMD5Hash`函数接收一个字符串,将其转换为字节数组,然后使用MD5类计算哈希值。最后,将哈希值转换为16进制字符串并返回。 对于文件加密,MD5通常用于生成文件的数字指纹,而不是实际的加密过程。你...

    vb-字符串md5码生成器

    5. 将字节转换为字符串:最后,将MD5哈希值的字节数组转换为16进制字符串。 ```vb Dim sb As New StringBuilder(hashBytes.Length * 2) For Each byte As Byte In hashBytes sb.Append(byte.ToString("x2")) Next...

    字符串加密vb

    在IT领域,字符串加密是一种常见的安全措施,用于保护数据的隐私和安全性。VB(Visual Basic)作为Microsoft开发的一种编程语言,提供了多种方法来实现字符串的加密。本篇将深入探讨字符串加密的基本概念、简单加密...

    VB.NET《MD5加密字符串(Excel加密字符串+字符串验证).zip

    这段代码首先将输入的字符串转为ASCII字节数组,然后通过MD5CryptoServiceProvider计算哈希值,最后将哈希值转为Base64编码的字符串。注意,实际应用中,通常会将Base64编码替换为直接显示16进制字符串,这可以通过...

    获取字符串MD5&获取文件MD5(vb.net)

    - 最后,为了得到32位的十六进制字符串,我们需要将字节数组转换为对应的字符串形式,可以使用循环遍历数组并转换每个字节为十六进制字符。 3. **计算文件的MD5**: - 对于文件,我们可以直接使用`ComputeHash`...

    16进制与10进制浮点数相互转换

    这个函数通过`CopyMemory` API函数将浮点数的二进制表示复制到字节数组,然后再将字节数组转换为16进制字符串。反向转换,即16进制到10进制浮点数,同样需要自定义函数: ```vb Function HexToFloat(ByVal hexStr ...

    将字符串传递到 DLL 过程

    在编程领域,尤其是在涉及到跨进程通信或调用外部动态链接库(DLL)时,字符串的传递是一个关键且需要注意的问题。本文将深入探讨如何在DLL过程中有效地传递字符串,特别是在使用Visual Basic进行开发时。 首先,我们...

Global site tag (gtag.js) - Google Analytics