浅议VB6字节数组和字符串的相互转换

2016-02-19 14:20 14 1 收藏

图老师设计创意栏目是一个分享最好最实用的教程的社区,我们拥有最用心的各种教程,今天就给大家分享浅议VB6字节数组和字符串的相互转换的教程,热爱PS的朋友们快点看过来吧!

【 tulaoshi.com - 编程语言 】

一、前言
  
  数据类型转换在编程中经常用到,VB6提供了一整套类型转换的函数。但是,在进行类型转换时,有时候仅仅依靠VB提供的函数是不能达到自己的目的的。因此,需要考虑用其他的方法来完成数据类型转换。本文仅谈VB6中字节数组和字符串的相互转换过程中应注意的问题及其解决办法。
  
  在VisualBasic中使用Byte数组主要是为了32位API函数的参数传递和函数的返回。在32位的VisualBasic版本中,字符串被假定为Unicode字符,其中每个字符占用两个字节。系统自动地将Unicode的两个连续字节转换成1个字节的ANSI字符。但是,如果该字符串包含二进制数据,其内容将变得很难理解。例如,一个汉字是两个字节,在VisualBasic6.0中的长度就只是1,这将给我们计算单个汉字的国标码带来一些麻烦。有了Byte数组,这些问题就将迎刃而解。
  
  另外,VisualBasic中的字符串和C语言中的字符串有一些不同,本文将给出一个函数,把C字符串转换成VisualBasic字符串。
  
  二、用Byte数组代替字符串
  
  Byte数组包含的是0-255之间的ASCII码字符,它不会象字符串那样被系统作预处理。你可以在很多API函数中用来Byte数组代替字符串。
  
  例如,下面的代码中用GetSystemDirectory这个WindowsAPI函数来取得Windows的系统路径。一共有两段代码,一段代码是传递一个字符串来存储函数返回的系统路径,另一段代码是传递一个Byte数组来代替字符串。
  
  为了更好地比较,两段代码的不同部分都用黑体标出。读者可以仔细比较这两段代码的差异,这样您会更深入地理解Byte数组和字符串的差别。
  
  把这两段代码的任何一段放入一个窗体中运行,但击窗体的空白区域,你将会在窗体中看到Windows的系统路径。
  
  下面是使用字符串的代码:
  
  ->PrivateDeclareFunctionGetSystemDirectoryLib"kernel32"Alias_
  
  "GetSystemDirectoryA"(ByVallpBufferAsString,ByValnSizeAsLong)AsLong
  
  PrivateSubForm_Click()
  
   DimnAsInteger
   DimstrAsString
  
   str=Space$(256)
   n=GetSystemDirectory(str,256)
   str=Left$(str,n)
   Printstr
  EndSub->
  在上面这段代码中,字符串参数lpBuffer返回Windows的系统路径。在函数调用之前,将变量预定义成256个字符,并在函数返回时清除多余的字符。
  
  注意:
  
  在调用API函数之前,通常都需要预先定义一个字符串或者Byte数组以供API函数存储数据。应该养成这种良好的编程习惯。否则,你的程序有可能崩溃,甚至导致你的系统崩溃。
  
  下面是使用Byte数组的代码:
  
  ->PrivateDeclareFunctionGetSystemDirectoryLib"kernel32"Alias_
  
  "GetSystemDirectoryA"(ByReflpBufferAsByte,ByValnSizeAsLong)AsLong
  
  PrivateSubForm_Click()
   DimnAsInteger
   DimBuffer()AsByte
   DimstrAasString
  
   Buffer=Space$(256)
   n=GetSystemDirectory(Buffer(0),256)
   strA=StrConv(Buffer,vbUnicode)
   strA=Left$(strA,n)
   PrintstrA
  EndSub->
  不知道读者注意到没有,第二段代码中的GetSystemDirectoryAPI函数的声明已经改变了。第一个参数的声明由一个ByVal字符串变成了一个ByRef的Byte数组,即由声明:
  
  ->ByVallpBufferAsString->
  变成了:
  
  ->ByReflpBufferAsByte->
  传递字符串时,需要一个ByVal修饰符来把字符串缓冲区传递到API函数中,因为字符串变量实际上指示了字符串内容所在的内存地址。在C语言术语中,这代表了一个指向指针的指针。ByVal意味着被传递的是一个指向实际字符串内容的内存地址。而在传递Byte数组Buffer(0)时,使用ByRef修饰符来传递变量,它相当于传递了数组中第一个字节内容的地址。事实上,这两种结果是一样的。
  
  ->strA=StrConv(Buffer,vbUnicode)->
  这行代码把Byte数组的二进制数据转换成一个合法的VisualBasic字符串。
  
  三、Byte数组和字符串之间的赋值
  
  为了简化Byte数组和字符串之间的数据传递,允许你在任何动态Byte数组和任何字符串之间直接互相赋值。例如:
  
  ->Buffer=strA
  
  StrA=Buffer->
  注意:
  
  当且仅当Byte数组是动态的,而不是固定大小时,你才可以把一个字符串直接赋给一个Byte数组。
  
  声明一个动态的Byte数组最简单的方法是在Dim语句中使用空参数,例如:
  
  ->DimBuffer()asByte->
  当你把一个字符串赋给一个动态Byte数组时,数组中的字符数将是字符串的字符数目的两倍。这是因为VisualBasic中字符串使用Unicode,并且每个Unicode字符的实际大小是两个字节。当把一个ASCII字符转换成一个Byte数组时,数组中的另一个字节将是0。
  
  向Unicode的转换是将每个在缓冲区中的字符转换成2个字节,从而实际上加倍了存储在结果字符串的中字节数目,当你认为函数Len(strA)得到的尺寸大小和Unicode转换后的Ubound(Buffer)函数所返回的尺寸大小相同时,上述特点就不很明显了。但是,函数LenB(strA)确实返回一个2倍于Len(strA)返回值的数值。这是因为Len函数返回的是字符串中字符的数目,而LenB函数返回的是字符串中字节的数目。一个Unicode串的字符长度仅仅是该串中实际字节数目的一半,这是因为每个Unicode字符2个字节。
  
  四、字符串转换成VB字符串
  
  当我们在VB中调用Win32API函数时,如果函数的返回值是一个字符串,那一般有如下三种情况:
  
  1.函数预先要求你提供一个有固定空间的字符串,以供存储函数的返回值。
  
  2.函数的返回是一个以Null结尾的C字符串,而不是正规的VB字符串。
  
  3.Win32API函数有时候会返回另一种类型的字符串。这种类型的字符串在单个缓冲区内保存了多个字符串值,每个值之间用Null隔开,结尾的是两个Null,一个Null是最后一个字符串值的结尾符,另一个Null是整个字符串的结尾符。这其实就是我们通常在C中遇到的字符串数组。
  
  第一种情况很好办,只无原则预先定义好一个空间足够大的字符串,然后把API函数的返回值赋于这个字符串就可以了。例如,如果你已经知道函数返回值最多不会走过256个字符,可以这样编码如下:
  
  ->DimsAPIReturnasstring
  
  SAPIReturn=Space$(256)
  
  SAPIReturn=API_Function(…)->
  对于第二和第三种情况,就必须把返回的C字符串成标准的VB字符串。下面这个函数CStringToVBString把一个以Null结尾的C字符串成VB字符串。
  
  ->PublicFunctionCStringToVBString(psCStringAsString)Asstring
  
   ‘参数psCString是一个待转换的C字符串
  
   ‘函数返回Null左边所有的字符
  
   dimsReturnasstring
   dimiNullCharPosAsInteger
  
   iNullCharPos=InStr(psCString,vbNullChar)
   ifiNullCharPos0then
  sReturn=left(psCString,iNullCharPos-1)
   else
  sReturn=pscstring
   endif
   CStringToVBString=sReturn
  Endfunction->
  下面这个过程把一个含有多个C字符串的缓冲区转换成一个字符串数组。
  
  ->PublicSubMultiCStringToStringArray(psMultiCStringAsString,psaStrings()AsString)
  
   '参数psMultiCString是待转换的多个C字符串
   '参数psaStrings是返回的VB字符串数组,调用之前它必须是一个动态的空数组
   '
  
   DimiNullPosAsInteger
   DimiPrevPosAsInteger
   DimiIdxAsInteger
  
   '初始化字符串数组
  
   iIdx=0
   ReDimpsaStrings(0ToiIdx 1)
   psaStrings(iIdx 1)=""
   Do
  '
  iNullPos=InStr(iPrevPos 1,psMultiCString,vbNullChar)
  IfiNullPosiPrevPos 1Then
   '把找到的C字符串赋值给字符串数组
   psaStrings(iIdx)=Mid$(psMultiCString,(iPrevPos 1),((iNullPos-1)-iPrevPos))
   iIdx=iIdx 1
   ReDimPreservepsaStrings(0ToiIdx)
   iPrevPos=iNullPos
  Else
   '找到了两个Null字符,去掉最后一个,然后退出
   ReDimPreservepsaStrings(0ToiIdx-1)
   ExitDo
  EndIf
   Loop
  EndSub->
  当调用Win32API函数时,使用这两个简单的函数,你可以消除很多冗余的代码,加快开发步伐。
  
  注意:
  
  当你为API的返回值预先分配字符串的空间时,一定不要忘了空间内必须包含Null结束符。另外,建议你在使用API时,最好对每个变量都进行声明,加上下面这句代码:
  
  ->OptionExplicit->
  五、小结
  
  VB6中字节数组和字符串的相互转换是编程中,尤其是新手使用中最为头疼的问题。本文归纳了软件开发过程中使用二者的典型情况及其应该注意的问题,供参考。不当之处还请读者批评指正。->

来源:https://www.tulaoshi.com/n/20160219/1606788.html

延伸阅读
标签: Web开发
script function evil(){ var toint=parseInt("123"); var intvalue=123; var tostr=intvalue.toString(); var my_friends ="trixie,moxie,sven,guido,hermes";var friend_array =my_friends.split(",");for (loop=0; loop friend_array.length;loop++){document.writeln(friend_array[loop] + &q...
标签: Web开发
js字符串转换成数字 将字符串转换成数字,得用到 parseInt 函数。 parseInt(string) : 函数从string的开始解析,返回一个整数。 举例:parseInt('123') : 返回 123(int); parseInt('1234xxx') : 返回 1234(int); 如果解析不到数字,则将返回一个NaN的值,可以用isNaN()函数来检测; 举例 : var...
在datagrid中,数据绑定时,怎么把数据库中的字符串按照自己设定的方式进行输出是个比较麻烦的事 这个问题困扰了我很久,也试着使用了很多方法: 1。 浏览器可以根据 的属性自动把回车符进行换行,但没有回车的段落就成了长长长长的一大行了,n久也没有解决这个矛盾,因为在 中浏览器强制把字符串同行输出,而没有自动换行。 2。用控件来装...
标签: Web开发
做项目时自己写一段js给大家。关于文本限制字数的问题,在实际开发中经常用到;主要问题出现在对中文的限制,下面代码就解决关于限制字节数的校验问题;只要将此下代码保存到一个js文件中并引入到校验的页面中,便可使用!同时希望大家给与大力支持和宝贵意见,本人会在今后闲余之际,发表更多的好文章,谢谢!! 以下是引用片段: /*  v...
嘿嘿,看到这个题目,想必吓了一大跳吧,或者是摆出一副不相信的表情?不用着急,请听我慢慢道来。 话说这个VB6,很是无耻,居然内置了支持Unicode的功能,也就是说,当你读入一个字符串时,它根据本地缺省语言的对应关系将之转换为Unicode,输出时,再从Unicode转换为本地编码。一方面,它当然方便啦,随便出个什么语言的版本都好方便的,...

经验教程

782

收藏

7
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部