读写文本文件时出现了乱码,找到了ADODB.Stream,可以指定字符集读取文本

Function ReadUTF()

    Filename = "F:\vba\2018 - new\2018-10-29 cad打桩\3 - cad打桩\代码\1.txt"

    With CreateObject("ADODB.Stream")
.Type = '读取文本文件
.Mode = '读写
.Open
.LoadFromFile Filename
' .Charset = "UTF-8"
' .Charset = "Unicode"
.Charset = "GB2312" 'GB2312 = ANSI
.Position =
ReadUTF = .ReadText
.Close
End With Debug.Print ReadUTF End Function

发现ANSI竟然就是GB2312,不过百度一下才发现不仅仅是简单的等于GB2312,有个网址讲的非常的到位

http://club.excelhome.net/thread-998747-1-1.html
三、ANSI编码(ISO8859、GB2312、Big5、JIS等等)

      在二楼的介绍中,我们讲解了计算机是如何显示键盘字符的(通常我们称为ASCII字符)。那么,我们伟大的中华民族的汉字多达十万个,常用的也有两三万,这又该如何显示呢?ASCII标准编码只有0~127,
扩展编码128~255,完全放不下这么多汉字嘛。 莫非,电脑发明的时候,就是给英语国家用的? 是的,你猜对了,最早电脑发明的时候,完全没有考虑这个世界上还会有其他的民族也会用到电脑,而这些民族的字符集会多达数万!有人问了,为什么当年的
科学家不考虑地球的其他民族呢?俺猜想,这与当年存储器的容纳能力有关,如果采用一个字节存储英文字符,完全足够了。如果考虑其他民族,就要用两个甚至更多的存储空间来存放英文字符(以便兼容多民族字符),
而为了这种兼容需要多支付的存储空间,其代价是当年的技术所不能承受的。 后来,随着技术的进步,单位存储空间的费用已经降低到了一个可以接受的地步,为地球多民族的字符集做编码,终于变为了可能。ANSI(美国国家标准学会)在这样的背景下,出台了一系列字符集,这些字符
集再加上其他国家为本国语言所设计的早期字符集,统称为ANSI编码。 所以,提到ANSI字符集,你一定要知道,这是一个由许多不同国家的字符集所构成的一个字符集集合的统称,而不是一个特定的字符集。同一个操作系统在不同的国家的ANSI编码,就是这个国家的字符集编码。
例如,欧洲国家用ISO8859(包括15个不同国家的子集)、中国大陆用GB2312、台湾用Big5、日本用JIS等等 ANSI的子集,在不同的操作系统下是不一样的,这取决于操作系统所支持的字符集。例如,同样是简体中文,Win32下的ANSI是GB2312,Windows95是GBK。Windows7是GB18030(完整支持需要安装扩展字体)等 补充内容 (2013-4-27 00:08):
GB2312、GBK、 GB18030等都属于双字节字符集 (DBCS double-byte character set)。 DBCS是亚洲字符集,包括简中、繁中、日、韩。在读取DBCS字符流时,只要遇到高位为1的字节,就可以将下两个字节
作为一个双字节编码。

后又发现 position如果设置为0,竟然会有一个乱码出现,但是文件的内容为什么不是从0开始的,而是从2开始的(position即光标的位置,就是设置从第几个字符开始读取文件内容),原来前两个字节用来定义文件的编码方式了,不过也不能简单的说是前两个字节,有些编码方式不是前两个字节

Function checkcode(path)

    Set objstream = CreateObject("adodb.stream")
objstream.Type =
objstream.Mode =
objstream.Open
objstream.Position =
objstream.LoadFromFile path
bintou = objstream.read() If bintou() = &HEF And bintou() = &HBB Then
checkcode = "utf-8" ElseIf bintou() = &HFF And bintou() = &HFE Then
checkcode = "unicode" ElseIf bintou() = And bintou() = Then
checkcode = "gb2312" Else
checkcode = "其他"
End If ' If AscB(MidB(bintou, 1, 1)) = &HEF And AscB(MidB(bintou, 2, 1)) = &HBB Then
' checkcode = "utf-8"
' ElseIf AscB(MidB(bintou, 1, 1)) = &HFF And AscB(MidB(bintou, 2, 1)) = &HFE Then
' checkcode = "unicode"
' Else
' checkcode = "gb2312"
' End If objstream.Close
Set objstream = Nothing End Function
AscB(MidB(bintou, , )) = &HEF

bintou() = &HEF

经过测试,两种方式都是可以的,但是个人更喜欢简洁明了一点的方式
UTF8文件有BOM和No BOM两种,其区别在于BOM多了三个字节(EFBBBF),对比了二进制文件,发现有这个区别,如果是NoBOM的文件就无法通过前两个字节判断是否为UTF-8文件。

对于没有BOM的UTF-8文件,可以通过遍历判断是否为UTF-8编码。遍历方法可以是二进制的移位判断或者是正则。

https://www.w3.org/International/questions/qa-forms-utf-8

例如,当使用Perl时,可用以下的表达式测试页面是否使用了UTF-8编码:

$field =~
m/\A(
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong -byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{} # straight -byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{} # planes -
| [\xF1-\xF3][\x80-\xBF]{} # planes -
| \xF4[\x80-\x8F][\x80-\xBF]{} # plane
)*\z/x; 以上表达式可转换成其他编程语言。这样就能处理各类问题,例如过长的错误编码以及非法的代理使用。$field 属于UTF-8编码时就会顺利返回,否则失败。

关于 BOM 和 NO BOM

http://club.excelhome.net/thread-998747-2-1.html

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

很多时候,我们不能直接传输Unicode编码的文本字符。因为Unicode编码不是为传输而设计,其编码为硬性规定。对接收方来说,接到了Unicode编码的数据,很难判断这是什么编码格式,会造成识别上的混乱。
为了兼容ASCII字符,并避免遇到\0造成字符串中断,以及解决英文传输体积被填零放大一倍的问题,提出了UTF-8编码规范。UTF-8的每一个字符按规则编码为1~4任一字节组合。中文大部分为为3字节长,部分四字节。 为了避免在文本传输中发生混乱,互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。 此外,在 Unix 世界中使用 UCS-( 或 UCS-) 会导致非常严重的问题。使用这两种编码方式的字符串,可能会包含诸如 字节 "/0" 或 "/" 作 为很多宽字符的组成部 分,
而这样的字节在文件名和其它 C 语言库函数中有特殊的意义。此外,大多数 Unix 工具都被设计用来处理 ASCII 文件的,不进行大 幅 度的修改是无法读取 -bit 字符的。
基于这些原因,在文件名、文本文件、环境变量等地方, UCS- ( 或 UCS- ) 不是一种合适的 Unicode 外部编码。
在 ISO -: 附 录 D 、 RFC3629 以 及 Unicode 4.0 标准的 3.9 节中均有定义的 UTF- 编码方法则不存在上述问题。所以在类 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- 和UTF-32之间的相同)。 如何识别文本传输的编码:
最标准的途径是检测文本最开头的几个字节(BOM),
开头字节 Charset/encoding,
EF BB BF UTF-
FF FE UTF-/UCS-, little endian -- Windows标准(低位在前),Unicode编码
FE FF UTF-/UCS-, big endian
FF FE UTF-/UCS-, little endian.
FE FF UTF-/UCS-, big-endian. 如果传输的文本没有Bom,那就需要采用正则或者其他方式来遍历文本,判断编码规范了。 这里有个有趣的现象。如果你打开记事本,输入联通两个字,然后把文件保存成ANSI格式。当你再次打开的时候,会发现文本乱码。
这是因为"联通"的ANSI/GB2312编码是:
c1
aa
cd
a8
恰好符合UTF-8的编码规范,因此造成识别错误。如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,
而会用ANSI的方式解读之,这时乱码就不出现了。 对于添加UTF- BOM( 字节串 :0XFF 0XBB 0XBF) 的做法,不被Unicode组织推荐,特别是是不能在 POSIX 系统中采用这种做法。此外,在文件头部添加 UTF- 签名会对很多已有惯例产生妨碍,例如处理一个纯文本程序。 正则表达式判断数据是否为UTF-8编码, 参考 http://www.w3.org/International/questions/qa-forms-utf-8,后面有参考代码 最后,总结一下各种文本编码:
ANSI/GB2312/GBK/GB18030 这些都是区域性编码,没有BOM
UNICODE 目前Windows操作系统使用的内码(低位在前),得到大部分编程语言的支持。标准数据有BOM头。
UTF-/UTF- 通常我们把这个看作传输编码(Unicode的实现方式),用于互联网数据传输。标准数据可能有BOM头。

最后提供一个详细说明 adodb.stream 对象的属性和方法的网址

https://blog.csdn.net/icanlove/article/details/39394701

ADODB.Stream的更多相关文章

  1. asp上传图片提示 ADODB.Stream 错误 '800a0bbc'的解决方法

    asp上传图片提示 ADODB.Stream 错误 '800a0bbc' 有这个提示有很多问题导致.权限是常见一种.这个不多说,还有一个有点怪的就是 windows2008显示系统时间的格式竟然是:2 ...

  2. IE下使用ADODB.Stream实现断点续传

    最近研究了一下IE自带的一些Activex控件,可以比较简单的实现断点续传功能 不过这种方式不推荐,因为安全性较低,而且需要修改客户端注册表,调低ie安全配置 还有就是我比较懒,只打算写个思路和几个关 ...

  3. 解决:ADODB.Stream 错误 '800a0bbc' 写入文件失败

    重装更改目录为e盘后,上传文件出现问题.解决方法: 调用adodb.stream的savetofile方法时发生错误, ADODB.Stream 错误 800a0bbc 写入文件失败.(msxml3. ...

  4. asp adodb.stream读取文件和写文件

    读取文件操作: '------------------------------------------------- '函数名称:ReadTextFile '作用:利用AdoDb.Stream对象来读 ...

  5. ASP 读写文件FSO,adodb.stream

    例如静态化页面的时候 总结:用server.CreateObject("adodb.stream") 来读写比较好,可避免乱码和读取到多余的字符.....不推荐 "scr ...

  6. adodb.stream对象的方法/属性

    Cancel 方法      使用方法如下      Object.Cancel      说明:取消执行挂起的异步 Execute 或 Open 方法的调用.Close   方法      使用方法 ...

  7. ADODB.Stream在进行文件上传时报错

    最近在做web项目,有个控件是上传材料文件和文件夹,本地运行正常,放到服务器上,一直报错:AutoRuntime服务器无法创建..... 解决方法: 1.配置ie浏览器的安全级别 2.修改ie浏览器对 ...

  8. ASP模拟POST请求异步提交数据的方法

    这篇文章主要介绍了ASP模拟POST请求异步提交数据的方法,本文使用MSXML2.SERVERXMLHTTP.3.0实现POST请求,需要的朋友可以参考下 有时需要获取远程网站的某些信息,而服务器又限 ...

  9. WinHttp

    using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System. ...

随机推荐

  1. 在Ubuntu平台上创建Cordova Camera HTML5应用

    在这篇文章中,我们将具体介绍怎样使用Cordova Camera HTML5 应用.很多其它关于Cordova的开发指南,开发人员能够參考文章"the Cordova Guide" ...

  2. VFL语言简洁

    一.VFL语言简洁 VFL(Visual format language)语言是苹果为了简化手写Autolayout代码所创建的专门负责编写约束的代码.为我们简化了许多代码量. 二.使用步骤 使用步骤 ...

  3. linux替换目录下所有文件中的某字符串

    linux替换目录下所有文件中的某字符串 比如,要将目录/modules下面所有文件中的zhangsan都修改成lisi,这样做: sed -i "s/zhangsan/lisi/g&quo ...

  4. ConfigurationManager.AppSettings Property

    在app.config文件中添加如下配置 <appSettings> <add key="Server" value="127.0.0.1"/ ...

  5. 【TODO】Ruby Range类

    创建: 2017/10/28   Range类                                                                             ...

  6. ural 1012. K-based Numbers. Version 2(大数dp)

    和1009相同,只是n达到了180位,可以模拟大数加和大数乘,这里用的java中的大数. import java.math.BigInteger; import java.util.Scanner; ...

  7. php排序函数测试

    1.sort,asort,arsort函数 十万个数的数组排序,用了0.17秒 $starttime=explode(' ',microtime());;for ($i=0; $i <10000 ...

  8. [Swift通天遁地]八、媒体与动画-(3)实现视频播放的水印、Overlay、暂停时插入广告等效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  9. Java线程之Synchronized用法

    synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对 ...

  10. Java根据年度将数据分组

    现在有这么一组数据 code                   name                year 45615654           x1                      ...