找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 2131|回复: 6

[技术讨论] VBS文本编码检测

[复制链接]
发表于 2025-10-6 10:52:59 | 显示全部楼层 |阅读模式
https://demon.tw/programming/vbs-validate-utf8.html
这里用vbscript逐字节读取转换文件

http://www.bathome.net/thread-71209-1-1.html
这里3楼用jscript逐字节读取转换文件

https://demon.tw/programming/vbs-binary-file-another.html
这里采用了Microsoft.XMLDOM对象读写二进制

经测试,用Microsoft.XMLDOM对象明显高效一点
  1. Dim t1, t2, oWMI, oSWbemDateTime, s

  2. s = "F:\资料\电子书\诡刺.txt"

  3. Set oWMI = GetObject("Winmgmts:\\.\Root\CIMV2")
  4. Set oSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")

  5. For Each i In oWMI.InstancesOf("Win32_OperatingSystem")
  6.     t1 = i.LocalDateTime
  7. Next
  8. wsh.Echo code1(s, "utf-8")
  9. For Each i In oWMI.InstancesOf("Win32_OperatingSystem")
  10.     t2 = i.LocalDateTime
  11. Next
  12. wsh.Echo t1 & vbCrLf & t2

  13. For Each i In oWMI.InstancesOf("Win32_OperatingSystem")
  14.     t1 = i.LocalDateTime
  15. Next
  16. wsh.Echo code2(s)
  17. For Each i In oWMI.InstancesOf("Win32_OperatingSystem")
  18.     t2 = i.LocalDateTime
  19. Next
  20. wsh.Echo t1 & vbCrLf & t2

  21. Function code1(ByVal file, ByVal Code)
  22.     Dim oVector, oNode, oStream, s, i
  23.     code1 = True
  24.     Set oVector = CreateObject("WIA.Vector")
  25.     Set oNode = CreateObject("Microsoft.XMLDOM").CreateElement("b")
  26.     oNode.DataType = "bin.hex"
  27.     Set oStream = CreateObject("ADODB.Stream")
  28.     oStream.Type = 1    'adTypeBinary
  29.     oStream.Mode = 3    'adModeReadWrite
  30.     oStream.Open()
  31.     oStream.LoadFromFile file
  32.     If oStream.Size = 0 Then Exit Function
  33.     oNode.NodeTypedValue = oStream.Read()
  34.     s = oNode.Text
  35.     oStream.Position = 0
  36.     oStream.Type = 2    'adTypeText
  37.     oStream.Charset = Code
  38.     t = oStream.ReadText()
  39.     oVector.SetFromString s
  40.     oNode.NodeTypedValue = oVector.BinaryData
  41.     If s <> oNode.Text Then code1 = False
  42. End Function

  43. Function code2(ByVal file)
  44.     Dim oNode, oStream, s, i
  45.     code2 = True
  46.     Set oNode = CreateObject("Microsoft.XMLDOM").CreateElement("b")
  47.     oNode.DataType = "bin.hex"
  48.     Set oStream = CreateObject("ADODB.Stream")
  49.     oStream.Type = 1    'adTypeBinary
  50.     oStream.Mode = 3    'adModeReadWrite
  51.     oStream.Open()
  52.     oStream.LoadFromFile file
  53.     If oStream.Size = 0 Then Exit Function
  54.     oNode.NodeTypedValue = oStream.Read()
  55.     s = "efbbbf" & oNode.Text
  56.     oStream.Position = 0
  57.     oStream.Type = 2    'adTypeText
  58.     oStream.Charset = "utf-8"
  59.     t = oStream.ReadText()
  60.     oStream.Position = 0
  61.     oStream.SetEOS()
  62.     oStream.WriteText t
  63.     oStream.Position = 0
  64.     oStream.Type = 1    'adTypeBinary
  65.     oNode.NodeTypedValue = oStream.Read()
  66.     If s <> oNode.Text Then code2 = False
  67. End Function

  68. Function code3(ByVal file)
  69.     Dim oStream, oRegExp, arr(), s
  70.     Set oStream = CreateObject("ADODB.Stream")
  71.     oStream.Type = 1    'adTypeBinary
  72.     oStream.Mode = 3    'adModeReadWrite
  73.     oStream.Open()
  74.     oStream.LoadFromFile file
  75.     If oStream.Size = 0 Then code3 = True : Exit Function
  76.     ReDim arr(oStream.Size - 1)
  77.     For s = 0 To oStream.Size - 1
  78.         arr(s) = ChrW(AscB(oStream.Read(1)))
  79.     Next
  80.     oStream.Close()
  81.     s = "[\xC0-\xDF]([^\x80-\xBF]|$)"        & _
  82.         "|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)" & _
  83.         "|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)" & _
  84.         "|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)" & _
  85.         "|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)" & _
  86.         "|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)" & _
  87.         "|[\x00-\x7F][\x80-\xBF]"            & _
  88.         "|[\xC0-\xDF].[\x80-\xBF]"           & _
  89.         "|[\xE0-\xEF]..[\x80-\xBF]"          & _
  90.         "|[\xF0-\xF7]...[\x80-\xBF]"         & _
  91.         "|[\xF8-\xFB]....[\x80-\xBF]"        & _
  92.         "|[\xFC-\xFD].....[\x80-\xBF]"       & _
  93.         "|[\xFE-\xFE]......[\x80-\xBF]"      & _
  94.         "|^[\x80-\xBF]"
  95.     Set oRegExp = New RegExp
  96.     oRegExp.MultiLine = False
  97.     oRegExp.Pattern = s
  98.     code3 = Not oRegExp.Test(Join(arr, ""))
  99. End Function
复制代码
code1采用WIA.Vector对象转换文本与二进制
code2采用ADODB.Stream对象转换文本与二进制
code3是用vbscript逐字节读取转换文件

测试1.23M的文件
code1 = 0.266秒
code2 = 0.243秒
code3 = 1.652秒

测试2.83M的文件
code1 = 1.082秒
code2 = 1.015秒
code3 = 3.749秒

测试4.87M的文件
code1 = 3.056秒
code2 = 2.903秒

估计要是有直接进行二进制数据比较的com对象或函数会更快一点
 楼主| 发表于 2025-10-6 12:06:23 | 显示全部楼层
本帖最后由 czjt1234 于 2025-10-7 09:44 编辑

失误,一楼的code1是错的
code2正确

http://www.bathome.net/viewthread.php?tid=57518
大文本还是用这个吧,贼快
发表于 2025-10-7 13:35:11 | 显示全部楼层
最好还是用.net稍微封装一个com 在vbs里用 最方便
发表于 2025-10-7 18:30:01 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-10-7 18:33 编辑


   文件编码检测至今仍是一个世界级难题,尤其是处理那些混合编码或长度很短的文件,有业内人士宁愿称其为是 '推测',其难度和挑战性说明可参考 https://blog.csdn.net/weixin_35972981/article/details/151367977
   uchardet 是目前比较广泛采用的文件编码 '检测' 方法之一,源自 Mozilla(火狐浏览器出品商)的开源代码,如 python, java, c# 等很多著名商业产品均有其应用接口。以前在老帖中介绍的 uchardet.exe 可从 https://github.com/JetDemo/uchardet 下载,是0.0.6版,目前较新的0.0.8版可从 https://github.com/gentlehill/uc ... refs/heads/main.zip 直接下载,其命令行用法非常简单》
   uchardet "input.txt"
即可。有兴趣者还可进一步咨询 ds ...
发表于 2025-10-9 00:30:27 | 显示全部楼层
编码检测一般不都是检测部分数据??检测个几kb感觉就足够了
Microsoft.XMLDOM或MSXML2.DOMDocument实际检测部分也会挺耗时的, 文件大小20m左右的话感觉不如WIA.Vector逐字节检测
 楼主| 发表于 2025-10-9 09:37:23 | 显示全部楼层
回复 5# Five66


我这个原理是用utf-8读取文本再写入,然后对比二进制数据
如果原始二进制数据和再写入后的二进制数据一样,就可认为编码正确

但是没有二进制数据对比的方法,所以转换为16进制数再比较
发表于 2025-10-9 14:09:14 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-10-9 16:37 编辑

回复 6# czjt1234

这是 '验明自身真伪' 的逻辑(用来证明一个文本文件的编码是否与 '预定编码' 一致),一个比较简捷的方法是用 powershell+fc.exe 实现,用 adodb.stream 也可以,但不如 powershell 的 [io.file] 读写方法能出入保全,还要后处理 utf-8 头标的干扰,比较繁复。调用系统内置的 fc.exe 可一步到位完成二进制逐字节比对。以下代码可证明一个指定文本文件(命令行参数)是否为 utf-8 编码(无头标)...

  1. @echo off &powershell "$t=[io.file]::readalltext('%~1');[io.file]::writealltext('#.$',$t)"
  2. fc /b "%~1" "#.$">nul&&echo,%~1》是无头标 utf-8 编码||echo,%~1》不是无头标 utf-8 编码
  3. del /q #.$ &pause&exit/b
复制代码
备注》代码中 readalltext, writealltext 采用默认编码值均为无头标 utf-8 编码,用 powershell v5.1 测试通过
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 01:47 , Processed in 0.021349 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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