ADODB.Stream
生活随笔
收集整理的這篇文章主要介紹了
ADODB.Stream
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
讀寫文本文件時出現了亂碼,找到了ADODB.Stream,可以指定字符集讀取文本
Function ReadUTF()Filename = "F:\vba\2018 - new\2018-10-29 cad打樁\3 - cad打樁\代碼\1.txt"With CreateObject("ADODB.Stream").Type = 2 '讀取文本文件.Mode = 3 '讀寫 .Open.LoadFromFile Filename ' .Charset = "UTF-8" ' .Charset = "Unicode".Charset = "GB2312" 'GB2312 = ANSI.Position = 2ReadUTF = .ReadText.CloseEnd WithDebug.Print ReadUTFEnd 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 = 1objstream.Mode = 3objstream.Openobjstream.Position = 0objstream.LoadFromFile pathbintou = objstream.read(2)If bintou(0) = &HEF And bintou(1) = &HBB Thencheckcode = "utf-8"ElseIf bintou(0) = &HFF And bintou(1) = &HFE Thencheckcode = "unicode"ElseIf bintou(0) = 49 And bintou(1) = 50 Thencheckcode = "gb2312"Elsecheckcode = "其他"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.CloseSet objstream = NothingEnd Function?
AscB(MidB(bintou, 1, 1)) = &HEFbintou(0) = &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 2-byte| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16)*\z/x;以上表達式可轉換成其他編程語言。這樣就能處理各類問題,例如過長的錯誤編碼以及非法的代理使用。$field 屬于UTF-8編碼時就會順利返回,否則失敗。?
關于 BOM 和 NO BOM
http://club.excelhome.net/thread-998747-2-1.html 十、網絡文本的傳輸標準(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 endianFF 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 0001aa 1010 1010cd 1100 1101a8 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頭。
最后提供一個詳細說明 adodb.stream 對象的屬性和方法的網址?
https://blog.csdn.net/icanlove/article/details/39394701?
轉載于:https://www.cnblogs.com/LcxSummer/p/10371149.html
總結
以上是生活随笔為你收集整理的ADODB.Stream的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Golang的reflect
- 下一篇: iOS一键生成所有图标