ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: liucqa

[分享] VBA高级教程之基础篇:文本编码和字符串处理(包括指针),ADODB.Stream转换文本编码

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-3-31 18:01 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖已被收录到知识树中,索引项:文本处理和正则
本帖最后由 liucqa 于 2014-4-20 12:56 编辑

十、网络文本的传输标准(UTF-8)

很多时候,我们不能直接传输Unicode编码的文本字符。因为Unicode编码不是为传输而设计,其编码为硬性规定。对接收方来说,接到了Unicode编码的数据,很难判断这是什么编码格式,会造成识别上的混乱。为了兼容ASCII字符,并避免遇到\0造成字符串中断,以及解决英文传输体积被填零放大一倍的问题,提出了UTF-8编码规范。UTF-8的每一个字符按规则编码为1~4任一字节组合。中文大部分为为3字节长,部分四字节。

为了避免在文本传输中发生混乱,互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。

此外,在 Unix 世界中使用 UCS-2( 或 UCS-4) 会导致非常严重的问题。使用这两种编码方式的字符串,可能会包含诸如 字节 "/0" 或 "/" 作 为很多宽字符的组成部 分,而这样的字节在文件名和其它 C 语言库函数中有特殊的意义。此外,大多数 Unix 工具都被设计用来处理 ASCII 文件的,不进行大 幅 度的修改是无法读取 16-bit 字符的。基于这些原因,在文件名、文本文件、环境变量等地方, UCS-2 ( 或 UCS-4 ) 不是一种合适的 Unicode 外部编码。在 ISO 10646-1:2000 附 录 D 、 RFC3629 以 及 Unicode 4.0 标准的 3.9 节中均有定义的 UTF-8 编码方法则不存在上述问题。所以在类 Unix 风格的操作系统中使用UTF-8来应用 Unicode编码。

UTF-8编码字节含义

    对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
    如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
    如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
    如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
    如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;

因此,对UTF-8编码中的任意字节,  根据第一位,可判断是否为ASCII字符;   根据前二位,可判断该字节是否为一个字符编码的第一个字节;    根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。

UTF-8的设计有以下的多字符组串行的特质:
    单字节字符的最高有效比特永远为0。
    多字节串行中的首个字符组的几个最高有效比特决定了串行的长度。最高有效位为110的是2字节串行,而1110的是三字节串行,如此类推。
    多字节串行中其余的字节中的首两个最高有效比特为10。
    UTF-8的这些特质,保证了一个字符的字节串行不会包含在另一个字符的字节串行中。这确保了数据接收方可以从任意一个位置来判断字符的起始字节,适用于在文字中搜索字或词。
    另一方面,由于其字节串行设计,如果一个疑似为字符串的串行被验证为UTF-8编码,那么我们可以有把握地说它是UTF-8字符串。一段两字节随机串行碰巧为合法的UTF-8而非ASCII的机率为32分1。对于三字节串行的机率为256分1,对更长的串行的机率就更低了。这样从概率上能避免识别的错误。

UCS和 Unicode标准中对UTF-8的定义稍有不同,因为在UCS中,UTF-8字节序列的最大可能长度为6,以表示所有码值不大于U+7FFFFFFF的 字符;而在Unicode中,UTF-8字节序列的最大可能长度为4,以表示所有码值不大于U+0010FFFF的字符。(这一差别在本质上与UCS-4 和UTF-32之间的相同)。

如何识别文本传输的编码:
最标准的途径是检测文本最开头的几个字节(BOM),
    开头字节                 Charset/encoding,
    EF BB BF                    UTF-8                                         
    FF FE                         UTF-16/UCS-2, little endian  -- Windows标准(低位在前),Unicode编码
    FE FF                         UTF-16/UCS-2, big endian
    FF FE 00 00               UTF-32/UCS-4, little endian.
    00 00 FE FF               UTF-32/UCS-4, big-endian.

如果传输的文本没有Bom,那就需要采用正则或者其他方式来遍历文本,判断编码规范了。

这里有个有趣的现象。如果你打开记事本,输入联通两个字,然后把文件保存成ANSI格式。当你再次打开的时候,会发现文本乱码。
这是因为"联通"的ANSI/GB2312编码是:
    c1 1100 0001
    aa 1010 1010
    cd 1100 1101
    a8 1010 1000
恰好符合UTF-8的编码规范,因此造成识别错误。如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码就不出现了。

对于添加UTF-8 BOM( 字节串 :0XFF 0XBB 0XBF) 的做法,不被Unicode组织推荐,特别是是不能在 POSIX 系统中采用这种做法。此外,在文件头部添加 UTF-8 签名会对很多已有惯例产生妨碍,例如处理一个纯文本程序。

正则表达式判断数据是否为UTF-8编码, 参考 http://www.w3.org/International/questions/qa-forms-utf-8,后面有参考代码



最后,总结一下各种文本编码:
ANSI/GB2312/GBK/GB18030   这些都是区域性编码,没有BOM
UNICODE                                目前Windows操作系统使用的内码(低位在前),得到大部分编程语言的支持。标准数据有BOM头。
UTF-8/UTF-16                         通常我们把这个看作传输编码(Unicode的实现方式),用于互联网数据传输。标准数据可能有BOM头。






评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-1 01:21 | 显示全部楼层
本帖最后由 liucqa 于 2013-4-2 11:54 编辑

十一、关于URL编码和Base64编码
      在网页采集的过程中,我们经常会遇到所谓的URL编码(也叫百分号编码)和Base64编码。

      先说一下Bsae64编码。BASE64编码是一种常用的将二进制数据转换为64个可打印字符的编码,常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。例如邮件系统的MIME协议等。这个协议的用途,是确保接收方在只能识别可见文本字符的情况下,能够接受和识别二进制数据。编码后数据长度大约为原长的135.1%。
      Base64编码是一种一对一的映射编码,其编码长度始终是3的倍数,不足3位,用=填充。所以,如果你看到一大堆乱七八糟的数据后面是=结尾的,大部分时候可以判定是Base64编码。由于Base64是映射编码,所以如果人为改变它的映射表,就可以作为一种简单的数据加密手段了。


      再说一下URL编码,这个编码通常用在网页地址(URL)的传递中,在URL解释中,部分字符例如/ +等,有着特定的意义,因此不能直接使用Base64编码来传输地址文本。这个编码也适用于统一资源标志符(URI)的编码。URI所允许的字符分作保留与未保留。保留字符是那些具有特殊含义的字符. 例如, 斜线字符用于URL (或者更一般的, URI)不同部分的分界符,未保留字符没有这些特殊含义。 URL编码把保留字符表示为%开头的特殊字符序列,所以又叫做百分号编码。
      2005年1月发布的RFC 3986,强制所有新的URI必须对未保留字符不加以百分号编码;其它字符要先转换为UTF-8字节序列, 然后对其字节值使用百分号编码。但是在目前的实际应用中,一个URL地址在做百分号编码之前,其未保留的字符序列不一定采用的是UTF-8编码,也有可能是ANSI编码。此外,部分早期的系统将空格编码成+,而不是标准推荐的%20,这是我们在实际应用中应该注意的事项。



      关于URL编码代码可以参考我的帖子 http://club.excelhome.net/forum. ... =894527&pid=6127746,     URL编码方法在此贴中不再涉及。



补充内容 (2013-6-26 22:57):
http://club.excelhome.net/thread-1026277-1-1.html  测试URL编码可以使用这个工具

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-1 01:22 | 显示全部楼层
本帖最后由 liucqa 于 2013-4-3 09:30 编辑

十二、如何处理各种编码转换(ADODB     Active Data Objects database)
      在VBA中,处理编码转换是一件很麻烦的事情,通常我们采用直接编写代码处理字节数组或者通过API函数来转换各种编码,代码冗长难懂。
对初学者来说,我推荐采用ADODB.Stream对象来处理各种编码转换。
      使用Adodb.Stream对象,要求您的机器上要安装有ADO2.5或者更高版本。在安装了office XP或更高版本的机器上,基本都有这个对象。
      没有这个组件,可下载 MDAC 2.5 或更高版本来升级数据访问组件 。

      下面简单列举一下这个对象的方法和属性

关于Adodb.Stream 的使用说明,ProgID:"Adodb.Stream"

有下列方法:
  1. Cancel 方法
  2.      Object.Cancel
  3.      说明:取消执行挂起的异步 Execute 或 Open 方法的调用。
  4. Close  方法
  5.      Object.Close
  6.      :关闭对像
  7. CopyTo 方法
  8.      Object.CopyTo(destStream,[CharNumber])
  9.      说明:将对像的数据复制,destStream指向要复制的对像,CharNumber为可选参数,指要复制的字节数,不选为全部复制。
  10. Flush  方法
  11.      Object.Flush
  12.      说明:
  13. LoadFromFile 方法
  14.      Object.LoadFromFile(FileName)
  15.      说明:将FileName指定的文件装入对像中,参数FileName为指定的用户名。
  16. Open  方法
  17.       Object.Open(Source,[Mode],[Options],[UserName],[Password])
  18.       说明:打开对像,
  19.       参数说明:Sourece 对像源,可不指定
  20.   Mode 指定打开模式,可不指定,可选参数如下:
  21.     adModeRead  =1
  22.     adModeReadWrite =3
  23.     adModeRecursive =4194304
  24.     adModeShareDenyNone =16
  25.     adModeShareDenyRead =4
  26.     adModeShareDenyWrite =8
  27.     adModeShareExclusive =12
  28.     adModeUnknown  =0
  29.     adModeWrite  =2
  30.   Options 指定打开的选项,可不指定,可选参数如下:
  31.     adOpenStreamAsync =1
  32.     adOpenStreamFromRecord =4
  33.     adOpenStreamUnspecified=-1
  34.   UserName 指定用户名,可不指定。
  35.   Password 指定用户名的密码

  36. Read  方法
  37. Object.Read(Numbytes)
  38. 说明:读取指定长度的二进制内容。
  39. 参数说明:Numbytes指定的要读取的找度,不指定则读取全部。

  40. ReadText  方法
  41. Object.ReadText(NumChars)
  42. 说明:读取指定长度的文本
  43. 参数说明:NumChars指定的要读取的找度,不指定则读取全部。

  44. SaveToFile  方法
  45. Object.SaveToFile(FileName,[Options])
  46. 说明:将对像的内容写到FileName指定的文件中
  47. 参数说明:FileName指定的文件
  48.     Options 存取的选项,可不指定,可选参数如下:
  49.       adSaveCreateNotExist  =1
  50.       adSaveCreateOverWrite =2

  51. SetEOS  方法
  52. Object.setEOS()
  53. 说明:

  54. SkipLine  方法
  55. Object.SkipLine()
  56. 说明:

  57. Write  方法
  58. Object.Write(Buffer)
  59. 说明:将指定的数据装入对像中。
  60. 参数说明:Buffer 为指定的要写入的内容。

  61. WriteText  方法
  62. Object.Write(Data,[Options])
  63. 说明:将指定的文本数据装入对像中。
  64. 参数说明:Data 为指定的要写入的内容。
  65.            Options 写入的选项,可不指定,可选参数如下:
  66.     adWriteChar  =0
  67.     adWriteLine  =1
复制代码

有下列属性:
  1. Charset

  2. EOS 返回对像内数据是否为空。

  3. LineSeparator 指定换行格式,可选参数有
  4.   adCR   =13
  5.   adCRLF   =-1
  6.   adLF   =10

  7. Mode 指定或返加模式。

  8. Position 指定或返加对像内数据的当前指针。

  9. Size 返回对像内数据的大小。

  10. State 返加对像状态是否打开。

  11. Type 指定或返回的数据类型,可选参数为:
  12.   adTypeBinary  =1
  13.   adTypeText  =2
复制代码

Word文件
ADO_2.5对象模型.rar (28.08 KB, 下载次数: 380)

CHM文件
ADO2.5.part1.rar (1 MB, 下载次数: 542) ADO2.5.part2.rar (734.37 KB, 下载次数: 359)


TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-1 01:24 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 liucqa 于 2014-4-20 12:59 编辑

十三、ADODB.Stream做编码转换的示例(ANSI/UNICODE/UTF-8/BASE64等编码)

  1. Sub testAdodbStream()
  2.     Dim bg(1) As Byte, bu(1) As Byte, butf(2) As Byte
  3.     bg(0) = &HD6                                         'D6D0是"中"的ANSI/gb2312编码
  4.     bg(1) = &HD0
  5.     MsgBox "转换GB2312字节数组为BSTR字符串:" & BytesToBstr(bg, "GB2312")         '"中"

  6.     bu(0) = &H2D                                         '4E2D是"中"的Unicode编码,低位在前
  7.     bu(1) = &H4E
  8.     MsgBox "转换Unicode字节数组为BSTR字符串:" & BytesToBstr(bu, "Unicode")       '"中"

  9.     butf(0) = &HE4                                       'E4 B8 AD 是"中"的UTF-8编码
  10.     butf(1) = &HB8
  11.     butf(2) = &HAD
  12.     MsgBox "转换UTF-8字节数组为BSTR字符串:" & BytesToBstr(butf, "utf-8")       '"中"

  13.     Dim utfbody() As Byte, str As String, buni() As Byte
  14.     str = "中"
  15.     buni = str
  16.     utfbody = BytesToBytesNoBom(buni, "Unicode", "utf-8")     '转换unicode字节数组为utf-8的字节数组
  17.     utfbody = BytesToBytesNoBom(bg, "gb2312", "utf-8")        '转换gb2312字节数组为utf-8的字节数组
  18.    
  19.     Dim strBase64
  20.     strBase64 = Base64Encode(bg, "gb2312")                                               '转换gb2312字节数组为Base64字符串
  21.     MsgBox "解码Base64字符串为gb2312字符串:" & Base64Decode(strBase64, "gb2312")         '解码Base64字符串为gb2312字符串
  22.    
  23.     strBase64 = Base64Encode(utfbody, "utf-8")                                           '转换uft-8字节数组为Base64字符串
  24.     MsgBox "解码Base64字符串为utf-8字符串:" & Base64Decode(strBase64, "utf-8")           '解码Base64字符串为utf-8字符串
  25. End Sub
复制代码


下面是用到的函数
  1. Function BytesToBstr(ByRef arrBody() As Byte, ByVal CodeBase As String) As String'- ------------------------------------------- -
  2. '  函数说明:字节数组转换成Unicode字符串(BSTR)
  3. '- ------------------------------------------- -
  4.     Dim objStream As Object

  5.     Set objStream = CreateObject("ADODB.Stream")
  6.     objStream.Type = 1     'adTypeBinary=1  adTypeText=2
  7.     objStream.Mode = 3     'adModeRead=1  adModeWrite=2  adModeReadWrit=3  adModeUnknown=0
  8.     objStream.Open
  9.     objStream.Write arrBody
  10.     objStream.Position = 0
  11.     objStream.Type = 2      'adTypeBinary=1  adTypeText=2
  12.     objStream.Charset = CodeBase
  13.     BytesToBstr = objStream.ReadText
  14.     objStream.Close
  15.     Set objStream = Nothing
  16. End Function

  17. Function BytesToBytesNoBom(ByRef arrBody() As Byte, ByVal SCodeBase As String, ByVal DCodeBase As String) As Byte()
  18. '- ------------------------------------------- -
  19. '  函数说明:不同编码的字节数组转换
  20. '- ------------------------------------------- -
  21.     Dim objStream As Object
  22.     Dim SText$, Dtext$

  23.     Set objStream = CreateObject("ADODB.Stream")
  24.     objStream.Type = 1     'adTypeBinary=1  adTypeText=2
  25.     objStream.Mode = 3     'adModeRead=1  adModeWrite=2  adModeReadWrit=3  adModeUnknown=0
  26.     objStream.Open
  27.     objStream.Write arrBody
  28.     objStream.Position = 0

  29.     objStream.Type = 2                  'adTypeText = 2
  30.     objStream.Charset = SCodeBase
  31.     SText = objStream.ReadText          '读取文本到sCode(Unicode)

  32.     objStream.Position = 0              ' 这只是定位到文件头
  33.     objStream.SetEOS                    'Position=0,更新 EOS 属性的值。使EOS的位置为0(也就是把结尾设成开头的位置)
  34.     objStream.Type = 2                  'adTypeText = 2
  35.     objStream.Charset = DCodeBase       '指定输出编码
  36.     objStream.WriteText SText           '写入文本数据到Adodb.Stream
  37.     'objStream.SaveToFile ThisWorkbook.Path & Application.PathSeparator & "out.bin", 2    '输出成文件

  38.     objStream.Position = 0              '切换type之前,要先重置指针为0
  39.     objStream.Type = 1                  'adTypeBinary=1  adTypeText=2
  40.     If InStr(1, DCodeBase, "utf-8", vbTextCompare) > 0 Then                               '去掉BOM
  41.         objStream.Position = 3
  42.     ElseIf InStr(1, DCodeBase, "unicode", vbTextCompare) > 0 Then
  43.         objStream.Position = 2
  44.     End If
  45.     BytesToBytesNoBom = objStream.Read
  46.     objStream.Close
  47.     Set objStream = Nothing
  48. End Function


  49. Public Function Base64Encode(varIn As Variant, CodeBase As String) As String
  50. '- ------------------------------------------- -
  51. '  函数说明:BASE64编码
  52. '- ------------------------------------------- -
  53.     Dim adoStream As Object
  54.     Dim xmlDoc As Object
  55.     Dim xmlNode As Object

  56.     Set adoStream = CreateObject("ADODB.Stream")
  57.     adoStream.Charset = CodeBase   '文本编码
  58.     If VarType(varIn) = vbString Then
  59.         adoStream.Type = 2    'adTypeText
  60.         adoStream.Open
  61.         adoStream.WriteText varIn
  62.     ElseIf VarType(varIn) = vbByte Or vbArray Then
  63.         adoStream.Type = 1    'adTypeBinary
  64.         adoStream.Open
  65.         adoStream.Write varIn
  66.     Else
  67.         Exit Function
  68.     End If
  69.     adoStream.Position = 0
  70.     adoStream.Type = 1        'adTypeBinary

  71.     Set xmlDoc = CreateObject("MSXML2.DOMDocument")
  72.     Set xmlNode = xmlDoc.createElement("MyNode")
  73.     xmlNode.DataType = "bin.base64"
  74.     xmlNode.nodeTypedValue = adoStream.Read
  75.     Base64Encode = xmlNode.Text
  76.     adoStream.Close
  77. End Function

  78. Public Function Base64Decode(varIn As Variant, CodeBase As String, Optional ByVal ReturnValueType As VbVarType = vbString) As Byte()
  79. '- ------------------------------------------- -
  80. '  函数说明:BASE64解码
  81. '- ------------------------------------------- -
  82.     Dim adoStream As Object
  83.     Dim xmlDoc As Object
  84.     Dim xmlNode As Object

  85.     Set xmlDoc = CreateObject("MSXML2.DOMDocument")
  86.     Set xmlNode = xmlDoc.createElement("MyNode")
  87.     xmlNode.DataType = "bin.base64"
  88.     If VarType(varIn) = vbString Then
  89.         xmlNode.Text = Replace(varIn, vbCrLf, "")
  90.     ElseIf VarType(varIn) = vbByte Or vbArray Then
  91.         xmlNode.Text = Replace(StrConv(varIn, vbUnicode), vbCrLf, "")
  92.     Else
  93.         Exit Function
  94.     End If

  95.     Set adoStream = CreateObject("ADODB.Stream")
  96.     adoStream.Charset = CodeBase  '文本的编码
  97.     adoStream.Type = 1            'adTypeBinary
  98.     adoStream.Open
  99.     adoStream.Write xmlNode.nodeTypedValue
  100.     adoStream.Position = 0
  101.     If ReturnValueType = vbString Then
  102.         adoStream.Type = 2       'adTypeText
  103.         Base64Decode = adoStream.ReadText
  104.     Else
  105.         Base64Decode = adoStream.Read
  106.     End If
  107.     adoStream.Close
  108. End Function
复制代码



ADODB.Stream可以在不同的地区ANSI编码之间利用Unicode做中转,进行区域编码转换,用处很大。同时,还能操作文件的读取和写入,功能强大,值得大家研究。

此外,上面的Base64编解码函数还用到了MSXML2.DOMDocument对象,本文不做讲解,请自行百度。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-1 01:38 | 显示全部楼层
本帖最后由 liucqa 于 2014-4-20 13:00 编辑

十四、使用 Adodb.Stream判断文件的Bom头,并返回编码类型
  1. Function CheckTextCode(fullname As String)
  2. '- ------------------------------------------- -
  3. '  ANSI无格式定义
  4. '  EFBBBF    UTF-8
  5. '  FFFE      UTF-16/UCS-2, little endian
  6. '  FEFF      UTF-16/UCS-2, big endian
  7. '  FFFE 0000 UTF-32/UCS-4, little endian
  8. '  0000 FEFF UTF-32/UCS-4, big endian
  9. '- ------------------------------------------- -
  10.     Dim body() As Byte
  11.     Set objStream = server.CreateObject("adodb.stream")
  12.     objStream.Type = 1
  13.     objStream.Mode = 3
  14.     objStream.Open
  15.     objStream.Position = 0
  16.     objStream.LoadFromFile fullname
  17.     body = objStream.read(2)
  18.     If AscB(MidB(body, 1, 1)) = &HEF And AscB(MidB(body, 2, 1)) = &HBB And AscB(MidB(body, 3, 1)) = &HBF Then
  19.         CheckTextCode = "utf-8"
  20.     ElseIf AscB(MidB(body, 1, 1)) = &HFF And AscB(MidB(body, 2, 1)) = &HFE Then
  21.         CheckTextCode = "unicode"
  22.     Else
  23.         CheckTextCode = "ANSI/gb2312"
  24.     End If
  25.     objStream.Close
  26.     Set objStream = Nothing
  27. End Function
复制代码



这个函数只能判断有Bom头的文件编码类型。无BOM的数据,需要通过遍历或者正则来进行判断。


正则判断字节数组是不是UTF8格式,数组前面不能有BOM
  1. Sub testUTF8()
  2.     Dim butf(2)
  3.     butf(0) = &HE4                                       'E4 B8 AD 是"中"的UTF-8编码
  4.     butf(1) = &HB8
  5.     butf(2) = &HAD
  6.     MsgBox isUTF8(Join(butf))
  7. End Sub
  8. Function isUTF8(ByRef text) As Boolean  'ByRef以提高效率
  9.     Dim s$, objReg As Object
  10.     Set objReg = CreateObject("vbscript.regexp")
  11.     s = "[\xC0-\xDF]([^\x80-\xBF]|$)"
  12.     s = s & "|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)"
  13.     s = s & "|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)"
  14.     s = s & "|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)"
  15.     s = s & "|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)"
  16.     s = s & "|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)"
  17.     s = s & "|[\x00-\x7F][\x80-\xBF]"
  18.     s = s & "|[\xC0-\xDF].[\x80-\xBF]"
  19.     s = s & "|[\xE0-\xEF]..[\x80-\xBF]"
  20.     s = s & "|[\xF0-\xF7]...[\x80-\xBF]"
  21.     s = s & "|[\xF8-\xFB]....[\x80-\xBF]"
  22.     s = s & "|[\xFC-\xFD].....[\x80-\xBF]"
  23.     s = s & "|[\xFE-\xFE]......[\x80-\xBF]"
  24.     s = s & "|^[\x80-\xBF]"
  25.     objReg.Pattern = s
  26.     isUTF8 = Not objReg.test(text)
  27. End Function
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-1 01:39 | 显示全部楼层
本帖最后由 liucqa 于 2013-4-3 09:31 编辑

十五、如何识别\u前缀的文本字符
在网页处理过程中,我们经常会遇到以\u开头的文本,这种格式是在每个Unicode编码前加上\u的前缀,在ISO标准中已经被淘汰,但部分早期网站和一些编写不规范的网站还在使用这个编码。

处理包含这种编码的文本,通常需要用到正则或者JS对象,下面给出一个使用正则的代码,供参考
  1. Sub TestRegUni()
  2.     Dim strTest$, i%, y%, arr1(), arr2()
  3.     Dim ireg As Object, imch As Object, mch As Object
  4.    
  5.     strTest = "\u4e2d \u56fd Test\u4e2d\+ \u56fd123"
  6.    
  7.     Set ireg = CreateObject("vbscript.regexp")
  8.     ireg.Global = True
  9.     ireg.Pattern = "\\u\w{4}"
  10.     Set imch = ireg.Execute(strTest)
  11.     For Each mch In imch
  12.         y = y + 1
  13.         ReDim Preserve arr1(1 To y)
  14.         ReDim Preserve arr2(1 To y)
  15.         arr1(y) = ChrW(CLng(Replace(mch.Value, "\u", "&h")))
  16.         arr2(y) = mch.Value
  17.     Next
  18.     For i = 1 To UBound(arr1)
  19.         strTest = Replace(strTest, arr2(i), arr1(i))
  20.     Next
  21.     MsgBox strTest
  22.     Set ireg = Nothing
  23. End Sub
复制代码


本教程到此结束。


附言:文本编码是一个深奥的课题,本文不过是介绍了冰山一角而已,如果您有更好的资料,欢迎跟帖支持,谢谢!

评分

3

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-4-1 09:41 | 显示全部楼层
这个必须得顶啊!!!!占位占位

TA的精华主题

TA的得分主题

发表于 2013-4-1 09:43 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-4-1 14:21 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-4-1 14:27 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-25 09:41 , Processed in 0.036884 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表