正文

uft-8格式和unicode编码的互相转换2009-07-29 14:50:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/enc999/45798.html

分享到:

  系统自带的记事本有读写UTF-8文本文件的功能,我想在自编的记事本中也加入这个功能,但在网上查找了一个钟头,竟然找不到用VB编写的代码。于是我在网上找了很多UTF-8的文章,还真的获益非浅,起码对UTF-8略知一二了。

  当我做完最后一次试验时,长长地叹了一口气,美美地伸了一个懒腰,呵呵,真爽啊,一天的时间终于没有白费!这也许就是编程的乐趣吧,当看到程序按照自己的愿望运行时,你们的心情一定也与我是一样的,无比舒畅。

  下面我先简单讲述一下UTF-8编码的有关知识,并且只讲与我编写的读写UTF-8文本代码有关的知识,详细的理论请各位自己找专业文章看看。

  UTF-8 编码字符理论上可以最多到 6个字节长,但目前全世界的所有文字和符号种类加起来也只要编到 4个字节长就够了。UTF-8 是以 8位(即 1个字节)为单元对原始码进行编码(注意一点:这里所讲的原始码都是指Unicode码),并规定:多字节码(2个字节以上才称为多字节)以转换后第1个字节起头的连续“1”的数目(这些连续“1”称为标记位),表示转换成几个字节:“110”连续两个 “1”,表示转换结果为2个字节,“1110”表示3个字节,而“11110” 则表示4个字节……跟随在标记位之后的“0”,其作用是分隔标记位和字符码位。第2~第4个字节的起头两个位固定设置为“10”,也作为标记,剩下的6个位才做为字符码位使用。这样,2字节UTF-8码剩下11个字符码位,可用以转换0080~07FF的原始字符码,3字节剩下16个字符码位,可用以转换0800~FFFF的原始字符码,由此类推。

编码方式的模板如下:

 原始码(16进制) |    UTF-8编码(二进制) 

 0000 - 007F             |     0xxxxxxx

 0080 - 07FF             |    110xxxxx 10xxxxxx

0800 - FFFF              |    1110xxxx 10xxxxxx 10xxxxxx

模板中的“x”表示字符码。

  VB能识别的 Ascii码<007F,所以在VB中,Ascii码都只能编为1个字节的UTF-8码。汉字的 Unicode编码范围为0800-FFFF,所以被编为 3个字节的UTF-8码。例如“汉”字的Unicode编码是6C49,6C49在0800-FFFF之间,所以要用3个字节的模板:1110xxxx 10xxxxxx 10xxxxxx。UTF-8文本文件与Unicode文本文件类似,在文件的头部也有标记字节,Unicode文件的标记是2个字节:&HFF 和 &HFE,UTF-8文件的标记是3个字节:&HEF、&HBB 和 &HBF 。要写入UTF-8编码的文本文件,关键是对汉字编码的处理。

  我们从上述的汉字编码模板就可以看出,对汉字的处理步骤大致为:

第一步:取得汉字的Unicode码。

第二步:将Unicode码分解为两个16进制数据。

第三步:将这两个16进制数据转换成二进制数据并连接。

第四步:将二进制数据分解为三个串,第一个串为4个位,在前面加上标记位“1110”,第二、三个串均为6个位,分别在前面加上“10”标记位。

第五步:将这三个串分别转换为10进制数据并赋值给字节型数组。

第六步:将字节型数组用二进制法写盘,并且要先在文本头存入三个字节的标记(&HEF、&HBB、&HBF),再将转换好的数据写入。

  要读取UTF-8编码的文本文件,对汉字的处理步骤大致为:

第一步:用二进制法读入文本数据,赋值给字节型数组,并判断前3个字节是否UTF-8标记,如果是,才进行以下的处理。

第二步:逐个字节判断是否汉字编码,如果是,就再提取后两个数组元素,共三个数组元素来加以处理。

第三步:将这三个数据都转换成16进制数据。

第四步:将三个16进制数据都转换成二进制数据。

第五步:从第一个二进制数据中去掉前4位,从第二、三个二进制数据中分别去掉前2位,并将这三个处理后的二进制数据依次连接,成为一个16位的字串。

第六步:从这个二进制串中分别提取前8位和后8位转换成两个10进制数据,这两个数据就是汉字的Unicode码了,将它们赋值给一个字符型变量即可。

  由于上述的二进制数字均须进行大量的字符串操作,因此在实际的代码中,笔者采用了逻辑运算(位操作)来代替上述的字符串操作。

  新建一个工程,添加一个文本框,MultiLine 属性设为 True, ScroBars 属性设为2,再添加一个公用对话框,改其名称为CD。再用菜单编辑器建立二个菜单项:一个的标题为“另存为UTF-8文件”,名称为“SaveToUTF8”,另一个用于打开文件,标题为“打开”,名称为 “OpenFile”。代码如下:

Option Explicit

Dim DAT() As Byte, DAT1() As Byte

Dim Z As String

Dim i As Long

Private Sub SaveToUTF8_Click()

On Error GoTo OutError

Dim zAsc As Long 'Ascii码暂存

Dim L As Long '字节计数

CD.Flags = &H200A

CD.DialogTitle = "另存为"

CD.Filter = "UTF-8文本(*.txt)|*.txt"

CD.ShowSave

If CD.FileName = ""

Then Exit Sub

For i = 1 To Len(Text1)

Z = Mid(Text1, i, 1)

zAsc = Asc(Z)

If zAsc > 0 Then '如果不是汉字

ReDim Preserve DAT(L + 1) As Byte

DAT(L) = zAsc: L = L + 1

Else

ReDim Preserve DAT(L + 3) As Byte

DAT1 = Z

DAT(L) = (DAT1(1) And 240) / 16 Or 224

DAT(L + 1) = (DAT1(1) And 15) * 4 + ((DAT1(0) And 192) / 64) Or 128

DAT(L + 2) = DAT1(0) And 63 Or 128 L = L + 3

End If

Next

ReDim DAT1(2) As Byte

DAT1(0) = &HEF: DAT1(1) = &HBB: DAT1(2) = &HBF

Open CD.FileName For Binary As #1

Put #1, , DAT1

Put #1, , DAT

OutError: Close

End Sub

 

Private Sub OpenFile_Click()

On Error GoTo InErr

Dim ST As String

Dim LFile As Long '文件长度

CD.Flags = &H200C

CD.DialogTitle = "打开"

CD.Filter = "文本文件(*.txt)|*.txt"

CD.ShowOpen ST = CD.FileName

If ST = "" Then Exit Sub

LFile = FileLen(ST) - 1

ReDim DAT(LFile) As Byte, DAT1(1) As Byte

Open ST For Binary As #1

Get #1, , DAT

If DAT(0) = &HEF And DAT(1) = &HBB And DAT(2) = &HBF Then

ST = ""

For i = 3 To LFile

If DAT(i) < 128 Then

ST = ST & Chr(DAT(i))

Else

DAT1(1) = ((DAT(i) And 15) * 16 + (DAT(i + 1) And 60) / 4)

DAT1(0) = (DAT(i + 1) And 3) * 64 + (DAT(i + 2) And 63)

Z = DAT1: ST = ST & Z: i = i + 2

End If

Next

Else: ST = StrConv(DAT, vbUnicode)

End If

Text1 = ST: ST = ""

InErr: Close

End Sub

阅读(6678) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册