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 格式之間自由自在地變來變去,相信當您看完這篇文章之後,對處理中文應該不再煩惱了吧! |