VB编程中的Unicode vs Ansi

本文详细介绍了在Visual Basic中Unicode和Ansi字串的区别及其处理方式。针对初学者在中文处理上的困扰,重点讲解了StrConv函数的使用,以及如何在Unicode和Ansi之间转换,确保正确进行字串处理。通过实例展示了如何读取含中文的文件,处理固定位元组资料档,并解释了为何在某些情况下需要使用byte array。熟悉这些技巧将有助于解决VB中的中文处理问题。
摘要由CSDN通过智能技术生成

Unicode vs Ansi
Visual Basic 32-bit 版本的字串处理采用 Unicode,也就是说字串在 VB 内部是以
Unicode 的格式来存放。

何谓 Unicode?简单的说,就是每一个字元都是以 2-byte 的型式表示,而每个「实
体字元」就是一个「字元」。因此,

Len("大家好")
Len("abc")

所传回的值都是 3,因为「大」和「a」都是一个字元。

但是这对一些中文字串处理,例如纯文字的资料档,却是一个大灾难,因为你必须以
byte 来定位每个字元,可是 Unicode 却把一切的处理全搞砸了。例如:

Len("Good Morning") 传回 12,而
Len("今天天气很好") 传回 6

对初学者而言,好不容易能使用 VB 来写程式已经是件了不起的事了,却马上在中文
处理上挨了一记闷棍,所受到的打击实在不小。但是不要怕,事实上只要再多了解一
些指令,就可以把中文处理的问题解决了。

是什麽指令呢?最重要的莫过於 StrConv 了。StrConv 函式的语法为:

StrConv(待转换字串, 转换格式)

其中转换格式在这里用到的是:

vbUnicode 将 Ansi 字串转换为 Unicode
vbFromUnicode 将 Unicode 字串转换为 Ansi

将字串转成 Ansi 之後,所有的字串处理指令都要加个 B,例如:LeftB, RightB,
MidB, ChrB, InstrB, LenB, InputB 等。例用这些指令来处理就行了。

当你处理完毕之後,你可以再将它再转回 Unicode,这样就可以使用一般的字串处理
指令了。

这样讲看得懂吗?如果还是不了解,看看下面的实例说明:

[●] 简易使用范例

看看下面的基本范例您应该就会对 VB 的字串处理方式有些概念。
Private Sub Command1_Click()
    Dim sUnicode As String
    Dim sAnsi As String

    ' Unicode 运算
    sUnicode = "王小明,A123456789,651023,台北市中山路100号,(02)2345678"
    Debug.Print Len(sUnicode) ' 传回 44
    Debug.Print Mid$(sUnicode, 5, 10) ' 传回 A123456789
    Debug.Print InStr(sUnicode, "台北市") ' 传回 23

    ' 将 Unicode 字串转成 Ansi
    sAnsi = StrConv(sUnicode, vbFromUnicode)
    ' Ansi 运算
    Debug.Print LenB(sAnsi) ' 传回 54
    Debug.Print MidB$(sAnsi, 8, 10) ' 传回 ?????,因为忘了转回 Unicode
    Debug.Print StrConv(MidB$(sAnsi, 8, 10), vbUnicode) ' 传回 A123456789,请注意转回 Unicode 的动作一定要做
    Debug.Print InStrB(sAnsi, StrConv("台北市", vbFromUnicode)) ' 传回 23, 不要忘了要把"台北市"也转成 Ansi,否则会找不到
End Sub


[●] 读入文字档

在 VB 的小技巧中,有一个是快速读档法:
Private Sub Command1_Click()
    Dim sFile As String

    Open "C:\filename.txt" For Input As #1
    sFile = Input$(LOF(1), #1)
    Close #1
End Sub

但是很不幸地,如果你读取的档案内含中文字,那上面这段程式会出现 Input past
end of file 的错误。因为 LOF 传回的是档案的 byte 数,而 Input 函式读取的是
字元数,由於档案内含中文,因此档案中的字元数将会小於 byte 数,於是就发生错
误了。

要解决这个问题,我们就要用到 StrConv 和 InputB 这两个函式了:
Private Sub Command1_Click()
    Dim sFile As String

    Open "C:\filename.txt" For Input As #1
    sFile = StrConv(InputB$(LOF(1), #1), vbUnicode)
    Close #1
End Sub

上面修正程式先用 InputB 将档案读进来,不过使用 InputB 所读入的档案是 Ansi
格式的,所以要再用 StrConv 转成 Unicode 才行。

[●] 随机资料档

许多文字资料档是以固定位元组的位置来加以区格,例如下面的资料格式:

王小民650110台北市中山路100号 (02)1234567
张大呆660824花莲县大甲镇广东街23号(03)9876543
......

像这种类型的档案要如何处理呢?这是就必须用到 Type 以及 byte array 了。
Private Type tagRecord
    Username(5) As Byte ' 姓名 6 bytes
    Birthday(5) As Byte ' 生日 6 bytes
    Address(21) As Byte ' 地址 22 bytes
    TEL(11) As Byte ' 电话 12 bytes
    CrLf(1) As Byte ' 换列字元 2 bytes
End Type

Private Sub Command1_Click()
    Dim uRecord As tagRecord

    Open "C:\filename.dat" For Random As #1 Len = LenB(uRecord)
    Get #1, 2, uRecord ' 取第二笔资料

    With uRecord ' With ... End With 应该会用吧
        Debug.Print .Username ' 传回 ???
        Debug.Print StrConv(.Username, vbUnicode) ' 传回 "张大呆"
    End With

    Close #1
End Sub
在这个例子中,一定要用到 byte array,因为只有 byte array 才能正确地定位到每
个 byte 的位置。以前使用字串来定位的方法已经不适用了,千万要记住!但是使用
byte array 所读入的资料是 Ansi 格式,若要处理或是做运算的话,记得还要转成
Unicode 格式才行。

[●] 使用 Byte Array

除了上面必须使用 byte 精确定位的例子之外,纯文字的处理基本上是用不到 byte
array 的。byte array 通常是用在处理 binary 资料。这方面的问题我们将另文讨
论。

看吧!只要熟悉使用 StrConv,你就可以在 Unicode 及 Ansi 格式之间自由自在地变
来变去,相信当您看完这篇文章之後,对处理中文应该不再烦恼了吧!
返回

字符串中文的问题
字串中文的问题,起於vb的字串是使用UniCode,而我们一般是使用Ascii Code。
这差别在何处呢?UniCode的每个字元长度是2个byte,而Ascii是一个byte,如果说,我将们将VB的字串写入档案,有时会有意想不到的结果。例如:
Text1.Text = "这是一个abc" len5 = Len(str5)
如果我们的Access资料库有一栏位的长度是10个Byte,所以我们在TextBox中设定
MaxLength = 10,但是上面的例子得到的len5是7,而不是我们认为的11,因为不管
是中文或英文,vb一律以UniCode来存,所以str5的长度是7个"字元",而text1最大
的长度限制是10,7没有超过10,故使用者仍可输入,但存档时,11个byte超过10个byte,所以会有错。
可是或许有人发现,使用RS232来传资料时,另一端主机是Ascii编码的机器,在vb中
我们若使用String来传,一样可以通啊,其实那是vb在传送与接收data时,会做转换
,使我们的程式设计较方便,但如果传的资料是Binary时,就头大啦。例如说,以字
串的方式来传送资料,当想传Ascii 大於128时,常有些问题,因为ASC(Chr(129))=0
,使我们不能用Chr()的指令来放资料。(事实上,您可以使用ChrW(129)来存资料,
和使用AscW()来取得值,加个W代表是Word的运算),这时候,就只有使用Byte Array来做了。

1.UniCode转成ByteAry

Dim byteAry() As Byte
Dim str5 As String
Dim i As Long
str5 = "这abc"
byteAry = str5
For i = LBound(byteAry) To UBound(byteAry)
    Debug.Print byteAry(i) '得 25 144 97 0 98 0 99 0 Next i
    Debug.Print Len(str5), LenB(str5) '得4 8
Next i

'所以了,可看出UniCode 的特性,程式应改一下,使用Strconv()来转换

Dim byteAry() As Byte
Dim str5 As String
Dim i As Long
str5 = "这abc"
byteAry = StrConv(str5, vbFromUnicode)
For i = LBound(byteAry) To UBound(byteAry)
    Debug.Print byteAry(i) '得 25 144 97 98 99 Next i
    Debug.Print LenB(StrConv(str5, vbFromUnicode)) '得5
Next i


2.ByteAry转回UniCode

使用Strconv()转换

Dim byteAry(10) As Byte
Dim Str5 As String
byteAry(0) = 25
byteAry(1) = 144
byteAry(2) = 97
byteAry(3) = 98
byteAry(4) = 99
Str5 = StrConv(byteAry, vbUnicode)


3.一些有用的函式
SubStr() 中文化取子字串,相对Mid()
Strlen() 中文化字串长度,相对Len()
StrLeft() 中文化取左字串,相对Left()
StrRight() 中文化取右字串,相对Right()
isChinese() Check某个字是否中文字

Public Function SubStr(ByVal tstr As String, start As Integer, Optional leng As Variant) As String
    Dim tmpstr As String
    If IsMissing(leng) Then
        tmpstr = StrConv(MidB$(StrConv(tstr, vbFromUnicode), start), vbUnicode)
    Else
        tmpstr = StrConv(MidB$(StrConv(tstr, vbFromUnicode), start, leng), vbUnicode)
    End If
    SubStr = tmpstr
End Function

Public Function Strlen(ByVal tstr As String) As Integer
    Strlen = LenB(StrConv(tstr, vbFromUnicode))
End Function

Public Function StrLeft(ByVal Str5 As String, ByVal len5 As Long) As String
    Dim tmpstr As String
    tmpstr = StrConv(Str5, vbFromUnicode)
    tmpstr = LeftB$(tmpstr, len5)
    StrLeft = StrConv(tmpstr, vbUnicode)
End Function

Public Function StrRight(ByVal Str5 As String, ByVal len5 As Long) As String
    Dim tmpstr As String
    tmpstr = StrConv(Str5, vbFromUnicode)
    tmpstr = RightB$(tmpstr, len5)
    StrLeft = StrConv(tmpstr, vbUnicode)
End Function

Public Function isChinese(ByVal asciiv As Integer) As Boolean
    If Len(Hex$(asciiv)) > 2 Then
        isChinese = True
    Else
        isChinese = False
    End If
End Function

混合字符串的长度
在中文环境下,每个字被当做两个 Byte :
Len("汉1") = 2
LenB("汉1") = 4
但在许多情况下,我们希望中文字长度为 2,英文字符为 1。可用以下的函数:
LenB(StrConv("汉1"), vbFormUnicode))
 

清除字符串中指定的字符
该函数在字符串 s 中清除 Sear

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值