2.1.5 常用的转换函数
1. 字符与数字的转换
Asc函数返回与字符对应的编码数字,Chr函数则反之,根据编码数字返回与之对应的字符。转换的对应关系如图2-2所示。
图2-2 字符与数字的转换关系图
应该注意到,这两个函数只是改变了数据类型,内存存储并没有发生变化,而且转换双方的内存占用的都是两个字节。
这两个函数概括起来就是一句话:字符就是数字,数字就是字符。
2. 字节与数字的转换
AscB和ChrB函数的作用类似,只是它们的作用范围是字节,而不是字符。转换的对应关系如图2-3所示。
图2-3 字节与数字的转换关系图
AscB函数根据字符的第一个字节返回对应的数字,它返回的是一个Byte类型。ChrB函数是根据数字返回对应字符,但是,它返回的是一个单字节字符,它的数据类型是String,但是只有一个字节。
要注意理解Chr和ChrB两个函数的区别,前者返回一个字符,它是Unicode编码的,总是占用两个字节,后者则返回一个字节。Chr函数的参数是在0~65535之间,而ChrB函数的参数只能在0~255之间。
ChrB函数的参数类型可以是Byte、Integer或者Long,这个对结果没有丝毫影响,因为该函数只使用参数的第一个字节。
这两个函数概括起来说,AscB函数是截取字符串的第一个字节,ChrB函数则将一个字节还原为字符串。主要作用还是转换类型,这一个字节的数据存储本身并没有改变。
3. 其他常见函数
其他一些可能用到的函数就是LeftB、MidB、RightB、LenB、InstrB等一些以字节为单位进行操作的函数,都比较好理解,不再细说。
还有两个函数容易让人困惑,就是AscW和ChrW。其实不难理解,在使用这两个函数进行字符和数字转换时,这个数字始终是指字符的Unicode编码数字,而使用Asc和Chr函数时,数字是指GBK、BIG5或SHIFT_JIS等编码数字,具体是哪个编码,取决于程序控制。
举一个例子,如汉字“啊”字的GBK编码是B0A1, Unicode编码是554A,几个函数的转换结果如表2-4所示。
表2-4 转换举例
Asc和AscW函数可能返回负值,如Asc("啊")返回的就是-20319。很多人都知道处理方法是在这个数字上加上65536,下面就来分析一下为何要这样做。
字符“啊”的GBK编码是B0 A1,即十进制的45217。Asc和AscW函数的返回类型是Integer,它最大只能表示32767。
相关数字的二进制形式如表2-5所示。
表2-5 数字为Integer型时的二进制形式
在Integer数据类型中,最高位的1个比特是用来表示正负的,0表示正数,1表示负数。数字45217的二进制形式最高位是1,这个二进制形式单独说说当然是没问题的,但是当把它作为Integer类型处理时,它就成了-20319。
补救方法就是把数据类型转换为Long型,这两个数字为Long型时的二进制形式如表2-6所示。
表2-6 数字为Long型时的二进制形式
要把Long型的-20319变为45217,其实就是要把左边两个字节的1全变为0。其实,首先想到的应该是“位与”操作,即按位进行与操作。
b = CLng(-20319) d = b AND &H0000FFFF& response.write d
前两个字节用0进行与操作,结果一定是0,后两个字节用1进行与操作,结果一定和原数据一致。于是,清晰明了地实现了前两个字节置0的操作。
而给-20319加上65536,其实是有点取巧的方法,在第二个字节的最后一位加上1,结果为0,并向前进位,如此类推,直到最后一个进位溢出,从而实现前两个字节的置0。
还有一种方式,是利用Hex函数,如CLng("&H" & Hex(-20319)),也会得到正确结果。
4. 字节数组与BSTR
在一些编程语言中是有字节数组的这个概念的(如Java中是byte[])。在VBScript中,是无法直接创建字节数组的。各位可能会想,创建一个数组,然后在每个元素中放入一个字节数据不就可以了吗?看一下例子。
Dim x(2) x(0)=Cbyte(60) x(1)=cbyte(61) x(2)=cbyte(62) response.write typename(x) &"<br>" response.write vartype(x) &"<br>"
输出的是 Variant()和8204,说明它只是一个变量数组,而非字节数组。真正的字节数组,应该输出为Byte()和8209。
想要创建字节数组,只能依靠一些组件(如Adodb.Stream)的帮助,使用Request. BinaryRead方法所读取的表单数据也是字节数组。
在很多程序中,会使用多个ChrB()拼接,从而得到一个字符串,它的实际内存存储是对应的字节数据,本书将这种字符串称为二进制字符串,简写为BSTR。
一个ChrB()返回的是一个字节的数据,即使输出也是乱七八糟的字符,但是多个ChrB()的字节连起来就不同了。如下面两行代码效果是一样的:
response.write chrB(&H4A) & chrB(&H55&) &"<br>" response.write "啊" & "<br>"
两个字节的数据连起来,4A 55对应的正是“啊”字。