1. 程式人生 > >Javascript筆記(四)之字元編碼(綜合講述)

Javascript筆記(四)之字元編碼(綜合講述)

前言

在講解本章節的時候,我們需要了解到一些事情。如果要想做到頁面不亂碼,要求有如下幾個因素。 1、html頁面的<meta charset="UTF-8"/>標籤中的值與html文字的編碼一致,如果不一致會亂碼; 2、瀏覽器不能自動切換編碼; 3、頁面為"UTF-8",而mysql資料庫查詢為gbk,也會導致亂碼;mysql可以使用如下命令,來臨時設定查詢編碼 set names utf8 4、資料庫在儲存資料的時候,編碼不一致儲存,會導致資料庫中的資料顯示亂碼; 5、jsp頁面亂碼,需要加上<meta charset="UTF-8"/> <%@ page contentType="text/html; charset=utf-8" language="java" pageEncoding="utf-8" %>

,同樣檔案編碼需要和內容編碼一致 6、PHP解決亂碼,需要新增header("content-type:text/html;charset=utf-8"); 同樣檔案編碼需要和內容編碼一致

字元編碼介紹

計算機之中,儲存為二進位制的位元流,我們能夠識別到的實體化的字元,儲存的為二進位制。而這兩者需要採用一個轉換規則,我們稱之為"編碼"與"解碼"。編碼就是將字元轉換為bit流,而從bit流轉換為字元叫做解碼。

字符集與字元碼點

1、字符集 字符集是各種文字和符號的總稱,包括國家文字、標點符號、圖形符號、數字等。字符集(Character set)是多個字元的集合,字符集的種類比較多,每個字符集的字元個數不同,常見的字符集有GBK、GB2312、ASCII、Latin1、ISO-8859-1。很多規範和標準在最初制定的時候,沒有意識到這將會是以後全球普適的準則,或出於組織本身利益考慮。 2、字元碼點 字元碼點(Character encoding)是把字符集中的字元編碼為指定集合中的某一個物件(例如位元模式、自然數序列,8位組或電脈衝),以便在計算機中儲存和網路通訊。一般而言,直接將字元在字符集中的位置,或碼點(code point),作為編碼後的值,字符集和字元編碼是緊密耦合的。

ASCII碼

只要是學過程式語言,我想都會對ASCII碼有一定對認識。學過JSP和MySQL的同學一定會見過如下兩個編碼;ISO-8859-1和latin1。那麼他們之間有什麼關係呢?

1、ASCII碼

ASCII(American Standard Code for Information Interchange,美國資訊互換編碼)是基於基礎拉丁字元的一套電腦編碼系統,它主要用於顯示現代英語,而其擴充套件版本EASCII(Extended ASCII)則可以面前顯示其他西歐語言。它是先進最通用的單位元組編碼系統,並等同於國際標準ISO/IEC 646。 ASCII採用7bit來編碼,共128個碼位,由於計算機1個字元8bit,所以最高位位0,即使0x00-0x7F,其中95個可列印字元(包括常用字母、數字、標點符號),還有33個控制字元。具體資訊大家可以看相應的編碼表,這裡我就不引用來。

2、ISO-8859-1

那麼由於早期編碼是由美國人設計的,只支援基礎拉丁字元,而計算機發展到歐洲,對歐洲其他不只是使用基礎拉丁字元的國家就不夠用了。那麼就在ASCII碼沒有使用的第八位使用上,這樣就可以表達字元數到256個了,增長了一倍了,這就是所謂到EASCII。EASCII基本解決了整個西歐到字元編碼問題。但是對於歐洲其他地區來說,比方說北歐、東歐地區,256個字元依然不夠用了,因此積極出現了ISO-8859-1。為了解決256個字元不夠用到問題,ISO 8859採用了不再是單個獨立的編碼規則,而是使用一系列的字符集(共15個組成),分別成為ISO-8859-n(1,2,3,4…16,沒有12),其對應字符集對應不同的語法,如ISO-8859-1對應西歐語言,ISO-8859-2對應中歐語言,其中所熟悉的latin1就是ISO-8859-1的別名,它表示整個西歐字符集的範圍。ISO-8859-n與ASCII是相容的,即0x00-0x7f範圍與ASCII保持一致。

中文編碼

為了擴充ASCII碼,以顯示本國語言,不同國家與地區指定了不同的標準,由此產生了GB2312(中文簡體)、BIG5(中文繁體)、JIS(日文)等各自的編碼標準。

GB2312

為了滿足國內在計算機中使用漢字的需要,中國國家標準總局釋出了一系列的漢字字符集國家標準編碼,統稱國標碼(GB碼),其中最有影響的是1980年釋出的《資訊交換漢字編碼字符集·基本集》,標準號為GB2312-1980。GB2312通行於我國內地,新加坡等地也採用此編碼標準,並且幾乎所有的中文系統和國際化軟體都支援GB2312。 GB2312是一個簡體中文字符集,收錄簡化漢字及一般字元、序號、數字、拉丁字母、希臘字母、俄文字母、漢語拼音符號、漢語注音符號字元,共7445個圖形字元,其中6763個漢字。GB2312對所錄字元進行了分割槽處理,共94個區,從1到94,每個區94位,共94*94=8836個碼位,由此,每個字元都能找到其唯一對應的區位和碼位,這種方式也成為區位碼。各區具體說明如下

  1. 01-09區收錄除漢字外的682個字元,有164個空位(9 * 94 - 682)
  2. 10-15區為空白區,沒有使用
  3. 16-55區收錄3755個一級漢字(簡體),按拼音排序
  4. 56-87區收錄3008個二級漢字(簡體),按部首/筆畫排序
  5. 88-94區為空白區,沒有使用

GB2312以區位碼位基礎,對字符采用雙位元組編碼,其中高位元組表示區碼,低位元組表示位碼,由於區碼和位碼範圍都在1-94,因此範圍同ASCII的編碼衝突。例如漢字區位碼位7174(十進位制),表示位形式71、74,而兩個ASCII字元‘GJ’也是71、74,這種衝突就會導致編碼的混亂,所以位瞭解決這個問題,GB2312將區位碼均加上0xA0,這樣高低位元組的第八位都變成了1,進而同ASCII碼區分開發。 所以GB2312是相容ASCII碼都一種編碼方式。在這些編碼裡,連數學符號、羅馬希臘字元、日文的假名都遍進來了,而且還對本來有都數字、標點、字母都統統重新編碼來兩個位元組長都編碼,這就是全形字元,而原來都127以下都那些就叫做半形字元了。 GB2312採用雙位元組編碼,原則上可以有65536個碼位,實際只收錄了7445個。出於相容ASCII和節省儲存容量考慮。為什麼呢?因為你採用統一的雙位元組編碼,老外就不同意了,我本來一個位元組就能儲存和傳輸的,現在要用兩個位元組傳輸,要讓你相容我。於是,GB2312的雙位元組編碼是變長的,有些字元是單位元組,有些是雙位元組,由此代價就是損失一部分碼為,除此之外還有一部分空間以作他用; 然而古漢語、人名等方面出現等罕用字,GB2312不能處理,這就導致了後來GBK、GB18030等出現。

BIG5

在香港、臺灣與澳門地區,使用繁體中文字符集,然而GB2312面向簡體中文字符集,並不支援繁體漢字,而這些使用繁體中文字符集等地區,一度出現很多不同產商提出的字符集編碼,這些編碼彼此互不相容,造成來資訊交流的困難,為了統一繁體字符集編碼,1984年,臺灣五大廠商巨集碁、神通、佳佳、零壹以及大眾一同指定了一種繁體中文編碼方案,即BIG5,又稱大五碼。 大五碼是一種繁體中文漢字字符集,其中繁體漢字13053個,808個標點符號、希臘字母以及特殊符號。大五碼採用雙位元組編碼,第一位元組範圍0x81-0xfe,避開ASCII碼的衝突,第二個位元組0x40-0x7E和0xA1-0xFE。因此Big5的字元編碼同GB2312儲存衝突,所以二者不相容。

編碼範圍 符號類別
8140-A0FE 保留 (用作造字區)
A140-A3BF 標點符號、希臘字母、特殊符號
A3C0-A3FE 保留 (未開放用於造字區)
A440-C67E 常用漢字(先按筆劃,再按部首排序)
C6A1-C8FE 保留(用作造字區)
C940-F9D5 非常用漢字(先按筆劃,再按部首排序)
8140-A0fe 保留(用作造字區)

Big5編碼推出後,的到繁體中文軟體廠商廣泛支援,在使用繁體漢字地區迅速普及使用。目前,Big5編碼在臺灣、香港、澳門、其他海外華人中普遍使用,成為繁體中文編碼的事實標準。在網際網路中檢索繁體中文網站,所開啟的網頁中,大多都是通過Big5編碼。

GBK、GB18030

GBK為漢字內碼擴充套件規範,K為擴充套件的聲母,英文Chinese Internal Code Specification。GBK編碼標準相容GB2312,是對GB2312-1980的擴充套件,簡、繁體融於一庫。GBK採用雙位元組表示,總體編碼範圍為8140-FEFE。GBK相容ASCII。 GB18030全稱GB18030-2000《資訊交換用漢字編碼字符集基本集的擴充》,是我國於2000年3月17日釋出的新的漢字編碼國家標準,2001年31日後在中國市場上釋出的軟體必須符合本標準。 GB18030字符集標準解決了漢字、日文假名、朝鮮語和中國少數名字漢字組成的大字符集計算機編碼問題。該標準字元總編碼空間超過150萬個編碼位,收錄27484個漢字,覆蓋中文、日文、朝鮮語和中國少數民族文字。滿足中國大陸、香港、臺灣、日本和韓國等東亞地區資訊交換多文種、大字量、多用途、統一編碼格式對要求。 GB18030採用單位元組、雙位元組和四位元組三種方式對字元編碼,相容ASCII、GB2312和GBk。

Unicode編碼

Unicode字符集

雖然通過使用不同對字符集,我們可以在一臺機器上查閱不同語法對文件,但是我們依然無法解決一個問題:在一份文件中顯示世界上所有字元。為了解決這個問題,我們需要一個全人類達成共識對巨大對字符集,這就是Unicode字符集。 Unicode(萬國碼、國際碼、統一碼、單一碼)是電腦科學領域裡對一項業界標準。她對於世界上大部分對文字系統進行裡整理,編碼,使得電腦可以用更為簡單對方式來呈現和處理文字。Unicode至今仍在不斷增修,每個新版本都加入更多新的字元。Unicode發展由非營利機構統一碼聯盟(The Unicode Consortium)負責,該機構致力於讓Unicode方案取代既有都字元編碼方案。Unicode備受認可,並備受認可,並廣泛應用於電腦軟體都國際化於本地化過程。 Unicode字符集包含來可能出現都所有字元,每個字元對應一個數字,這個數字即碼點(Code Point)。

編碼方案

Unicode的編碼方案又叫做Unicode轉換格式,簡稱為UTF(Unicode Transformation Format),包括UTF-16、UTF-32以及UTF-8,其中又屬於UTF-8使用最為廣泛。

UTF-16編碼

UTF-16對應UCS-2,採用雙位元組編碼BMP內位於U+0000支U+D7FF以及U+E000至U+FFFF字元,編碼後的值賭贏的碼點,由於BMP內的U+D800至U+DFFF碼位不對應任何字元, UTF-16藉助這些碼位,根據一定的規則採用四位元組編碼輔助平面內U+10000至U+10FFFF的字元,因此, UTF-16是一種變長編碼方式。 UTF-16編碼分大端序(Big-Endian,簡稱 UTF-16 BE)和小端序(Little-Endian,簡稱 UTF-16 LE)兩種,區別在於位元組序不同。那麼我們如果收到 UTF-16位元組流“594E”,如何區分是奎字還是乙字呢? UTF-16採用BOM(Byte Order Mark,位元組序標記)機制來解決這個問題,在Unicode中有兩個特殊字元,一個是U+FEFF,表示"ZERO WIDTH NO-BREAK SPACE";另一個是U+FFFE,它在Unicode中是不存在 的字元,所以不應該出現在實際傳輸 中, UTF-16在傳輸位元組流前,先傳輸一個BOM,這樣接收者接收到FEFF,就表示這個位元組是Big-Endian;如果收到FFFE,就表明這個位元組流是Little-Endian的;

UTF-32編碼

UTF-32對應UCS-4,採用四個位元組編碼所有的Unicode字元。

UTF-8編碼

1、UTF-8編碼介紹 UTF-8是一種針對Unicode的可變長度字元編碼,也是一種字首碼。它可以用來表示Unicode標準中的任何字元,且其編碼中的第一個字元仍於ASCII相容,這使得ASCII字元的軟體無需或只需做少部分修改,即可繼續使用,因此它逐漸成為電子郵件、網頁及其他儲存或傳送文字的應用優先採用的編碼。 UTF-8使用一至六個自己為每個字元編碼(儘管如此,2003年UTF-8被RFC3629重新規範,只能使用原來Unicode定義的區域,U+0000到U+10FFFF,也就是說最多四個位元組); 2、UTF-8的優點: ASCII碼是UTF-8的子集,因為一個純ASCII字串也是一個合法的UTF-8字串,所以現存的ASCII文字不需要轉換。 UTF-8字串可以由一個簡單的演算法可靠識別出來 3、UTF-8的缺點: 與其他Unicode編碼相比,特別是UTF-16,在UTF-8中ASCII碼佔用的空間只有一半,可是在一些字元的UTF-8編碼佔用的空間要多出1/3,特比是中文、日文和韓文這樣的方塊文字;

由於在UTF-8編碼中,其自身已經帶來控制資訊,所以不需要BOM機制,但是也可以用BOm來表明編碼方式,字元"ZERO WIDTH NO-BREAK SPACE"帶UTF-8編碼就是0xEFBBBF,所以如果接收者接收到以0xEFBBBF開頭到位元組流就知道者是UTF-8編碼來,但是需要注意,不是所有軟體或程式都能夠爭取處理BOM標記,所以我們不推薦對UTF-8編碼對檔案加上BOM。

ANSI編碼

ANSI,美國國家標準協會(American National Standards Institute),在windows系統都編碼處理之中,一般採用ANSI來代表系統預設編碼方式,而且並不是確定都某一種編碼方式——在簡體中文作業系統中ANSI編碼預設值都是GB系列編碼,在繁體中文作業系統中ANSI編碼預設指的是BIG5,在日文作業系統中預設置的shift JIS等。