用VBS判断无BOM头的文件是否UTF-8编码

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:38   1723   0

http://demon.tw/programming/vbs-validate-utf8.html

标签: BOM, UTF-8, VB, VBS, VBScript

在 VBS 贴吧看到吧主发的一个《如何区别无BOM头的UTF-8和GBK?》的贴子,故为此文。这种问题都解决不了,VBS 吧主的水平也不过如此。

字节顺序记号(英语:byte-order mark,BOM)是位于码点U+FEFF的统一码字符的名称。当以UTF-16或UTF-32来将UCS/统一码字符所组成的字符串编码时,这个字符被用来标示其字节序。它常被用来当做标示文件是以UTF-8、UTF-16或UTF-32编码的记号。

更多关于 BOM 的资料请自己阅读维基百科

批处理之家有个《VBS版文件编码识别、转换工具(GB2312、UTF-8、Unicode、BIG5)》的帖子,其中检测文件编码的 CheckCode.vbs 是这么写的:

Function CheckCode (Usage)
Dim slz
set slz = CreateObject("Adodb.Stream") 
slz.Type = 1
slz.Mode = 3
slz.Open
slz.Position = 0
slz.Loadfromfile file
Bin=slz.read(2)
if AscB(MidB(Bin,1,1))=&HEF and AscB(MidB(Bin,2,1))=&HBB Then
Codes="UTF-8"
elseif AscB(MidB(Bin,1,1))=&HFF and AscB(MidB(Bin,2,1))=&HFE Then
Codes="Unicode"
else
Codes="GB2312"
end if
WScript.echo file,Usage,Codes
slz.Close
set slz = Nothing
End Function

这个代码只检测了 BOM,把没有 BOM 的文件都认为是 GB2312 编码,很显然是错误的。并不是所有 UTF-8 编码的文件都带 BOM 标记的,事实上,绝大部分 UTF-8 文件都不带 BOM。

理论上,要准确地判断一个文件的编码是很困难的,但是判断 一个文件是否为 UTF-8 编码却相对比较简单,在《构建可扩展的Web站点》一书中就有很好的 PHP 代码:

<?php
function is_valid_utf8(&$input){
    $rx = '[\xC0-\xDF]([^\x80-\xBF]|$)';
    $rx .= '|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)';
    $rx .= '|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)';
    $rx .= '|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)';
    $rx .= '|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)';
    $rx .= '|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)';
    $rx .= '|[\x00-\x7F][\x80-\xBF]';
    $rx .= '|[\xC0-\xDF].[\x80-\xBF]';
    $rx .= '|[\xE0-\xEF]..[\x80-\xBF]';
    $rx .= '|[\xF0-\xF7]...[\x80-\xBF]';
    $rx .= '|[\xF8-\xFB]....[\x80-\xBF]';
    $rx .= '|[\xFC-\xFD].....[\x80-\xBF]';
    $rx .= '|[\xFE-\xFE]......[\x80-\xBF]';
    $rx .= '|^[\x80-\xBF]';
    return preg_match("!$rx!", $input) ? 0 : 1;
}
?>

我们要做的就是改写成 VBS:

Function read(path)
    '将Byte()数组转成String字符串
    Dim ado, a(), i, n
    Set ado = CreateObject("ADODB.Stream")
    ado.Type = 1 : ado.Open
    ado.LoadFromFile path
    n = ado.Size - 1
    ReDim a(n)
    For i = 0 To n
        a(i) = ChrW(AscB(ado.Read(1)))
    Next
    read = Join(a, "")
End Function

'Author: Demon
'Date: 2011/11/10
'Website: http://demon.tw

Function is_valid_utf8(ByRef input) 'ByRef以提高效率
    Dim s, re
    Set re = New Regexp
    s = "[\xC0-\xDF]([^\x80-\xBF]|$)"
    s = s & "|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)"
    s = s & "|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)"
    s = s & "|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)"
    s = s & "|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)"
    s = s & "|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)"
    s = s & "|[\x00-\x7F][\x80-\xBF]"
    s = s & "|[\xC0-\xDF].[\x80-\xBF]"
    s = s & "|[\xE0-\xEF]..[\x80-\xBF]"
    s = s & "|[\xF0-\xF7]...[\x80-\xBF]"
    s = s & "|[\xF8-\xFB]....[\x80-\xBF]"
    s = s & "|[\xFC-\xFD].....[\x80-\xBF]"
    s = s & "|[\xFE-\xFE]......[\x80-\xBF]"
    s = s & "|^[\x80-\xBF]"
    re.Pattern = s
    is_valid_utf8 = (Not re.Test(input))
End Function

s = read("utf-8.txt") '读取文件
WScript.Echo is_valid_utf8(s) '判断是否UTF-8
 
 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
yu2n说道: 
   

[code] ' 检察文件是否为UTF-8,有BOM/无BOM皆可,读取文件BOM头/前4Kbit判读 Function is_valid_utf8(ByVal file) is_valid_utf8 = False '将Byte()数组转成String字符串 Dim ado, a(), i, n, Bin, s, re Set ado = CreateObject("ADODB.Stream") ado.Type = 1 : ado.Open ado.LoadFromFile file n = ado.Size - 1 ' 检查空文件/限制读取4Kbit If n = 1024*4-1 Then n = 1024*4-1 '4Kbit ' 使用BOM判断 Bin = ado.read(2) If AscB(MidB(Bin,1,1)) = &HEF And AscB(MidB(Bin,2,1)) = &HBB Then is_valid_utf8 = True : Exit Function End If '将Byte()数组转成String字符串 ReDim a(n) : ado.Position = 0 For i = 0 To n a(i) = ChrW(AscB(ado.Read(1))) Next '使用正则表达式判断 Set re = New Regexp s = "[\xC0-\xDF]([^\x80-\xBF]|$)" s = s & "|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)" s = s & "|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)" s = s & "|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)" s = s & "|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)" s = s & "|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)" s = s & "|[\x00-\x7F][\x80-\xBF]" s = s & "|[\xC0-\xDF].[\x80-\xBF]" s = s & "|[\xE0-\xEF]..[\x80-\xBF]" s = s & "|[\xF0-\xF7]...[\x80-\xBF]" s = s & "|[\xF8-\xFB]....[\x80-\xBF]" s = s & "|[\xFC-\xFD].....[\x80-\xBF]" s = s & "|[\xFE-\xFE]......[\x80-\xBF]" s = s & "|^[\x80-\xBF]" re.Pattern = s is_valid_utf8 = (Not re.Test(Join(a, ""))) End Function [/code]

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP