熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Java中編碼以及Unicode總結

2022-06-13   來源: Java核心技術 

  

  基本概念

  bit 位只能是或者

  byte 字節一個字節是 byte= bits 計算機表示的基本單位

  KBMBGBTBPB是以與byte進行換算

  進制 用符號進行計數 十進制二進制八進制()十六進制(xFF)

  字符文字和符號的總稱

  字符集 多個字符集合的總稱ASCII字符集GB字符集GBK字符集BIG字符集GB字符集Unicode字符集

  byte可表示^=個字符的表示

   ×

   ×

   ×

   ×F

   ×

   xFE

   xFF

  以補碼的形式表示的二進制編碼

  的表示=反碼補碼=反碼+=

  表示的就是=取反就是也就是所以就是

  

  字符集和編碼

  字符(Character)

  字符(Character)是文字與符號的總稱包括文字圖形符號數學符號等

  字符集(Character Set)

  一組抽象字符的集合就是字符集(Character Set)字符集常常和一種具體的語言文字對應起來該文字中的所有字符或者大部分常用字符就構成了該文字的字符集比如英文字符集一組有共同特征的字符也可以組成字符集比如繁體漢字字符集日文漢字字符集字符集的子集也是字符集

  計算機要處理各種字符就需要將字符和二進制內碼對應起來這種對應關系就是字符編碼(Encoding)制定編碼首先要確定字符集並將字符集內的字符排序然後和二進制數字對應起來根據字符集內字符的多少會確定用幾個字節來編碼每種編碼都限定了一個明確的字符集合叫做被編碼過的字符集 (Coded Character Set)這是字符集的另外一個含義通常所說的字符集大多都是指編碼字符集(Coded Character Set)

  

   ASCII字符集

  ASCII(American Standard Code for Information Interchange美國信息互換標准代碼)是基於羅馬字母表的一套電腦編碼系統由美國國家標准局(ANSI)制定

  可以表示^=個字符在計算機的存儲單元中一個ASCII碼值占一個字節(個二進制位)其最高位(b)用作奇偶校驗位 位編碼的字符集只能支持個字符為了表示更多的歐洲常用字符對ASCII進行了擴展ASCII擴展字符集使用位(bits)表示一個字符字符

  ASCII擴展字符集比ASCII字符集擴充出來的符號包括表格符號計算符號希臘字母和特殊的拉丁符號

   GB 字符集

  GB又稱為GB字符集全稱為《信息交換用漢字編碼字符集·基本集》由原中國國家標准總局發布日實施在中國大陸和新加坡獲廣泛使用GB收錄簡化漢字及一般符號序號數字拉丁字母日文假名希臘字母俄文字母漢語拼音符號漢語注音字母 個圖形字符其中包括個漢字其中一級漢字二級漢字包括拉丁字母希臘字母日文平假名及片假名字母俄語西裡爾字母在內的個全角字符

  GB中對所收漢字進行了分區處理每區含有個漢字/符號這種表示方式也稱為區位碼各區包含的字符如下區為特殊符號區為一級漢字按拼音排序區為二級漢字按部首/筆畫排序區及區則未有編碼

  兩個字節中前面的字節為第一字節後面的字節為第二字節習慣上稱第一字節為高字節 而稱第二字節為低字節高位字節使用了xAxF (把區(區未有編碼)的區號加上xA)低位字節使用了xAxFE (把加上xA)

  以GB字符集的第一個漢字字為例它的區號位號則區位碼是在大多數計算機程序中高字節和低字節分別加xA得到程序的漢字處理編碼xBA計算公式是xB=xA+ xA=xA+

   GBK 字符集

  GBK全名為漢字內碼擴展規范英文名Chinese Internal Code SpecificationK 即是擴展所對應的漢語拼音(KuoZhan)中字的聲母GBK 來自中國國家標准代碼GB GBK: 漢字國標擴展碼基本上采用了原來GB所有的漢字及碼位並涵蓋了原Unicode中所有的漢字總共收錄了個符號 個漢字及提供了個造字碼位[(GBKHxB)*xE+(GBKLxA)]*(漢字離散後每個漢字點陣所占用的字節)

  GBK是GB的擴展是向上兼容的因此GB中的漢字的編碼與GBK中漢字的相同另外GBK中還包含繁體字的編碼

  GBK中每個漢字仍然包含兩個字節第一個字節的范圍是×xFE(即第二個字節的范圍是×xFE(即 GBK中有碼位包含漢字

  

   BIG字符集

  又稱大五碼或五大碼年由台灣財團法人信息工業策進會和五間軟件公司宏碁 (Acer)神通 (MiTAC)佳佳零壹 (Zero One)大眾 (FIC)創立故稱大五碼Big碼的產生是因為當時台灣不同廠商各自推出不同的編碼如倚天碼IBM PS王安碼等彼此不能兼容另一方面台灣政府當時尚未推出官方的漢字編碼而中國大陸的GB編碼亦未有收錄繁體中文字

  Big字符集共收錄個中文字該字符集在中國台灣使用耐人尋味的是該字符集重復地收錄了兩個相同的字(xAxCA)(xDCDxDDFC)

  Big碼使用了雙字節儲存方法以兩個字節來編碼一個字第一個字節稱為高位字節第二個字節稱為低位字節高位字節的編碼范圍 xAxF低位字節的編碼范圍××E及xAxFE各編碼范圍對應的字符類型如下xAxABF為標點符號希臘字母及特殊符號另外於xAxA存放了雙音節度量衡單位用字兙兛兞兝兡兣嗧瓩糎xAxCE為常用漢字先按筆劃再按部首排序xCxFD為次常用漢字亦是先按筆劃再按部首排序

   GB字符集

  GB 的全稱是GB《信息交換用漢字編碼字符集基本集的擴充》是我國政府於日發布的新的漢字編碼國家標准日後在中國市場上發布的軟件必須符合本標准GB 收錄了個漢字GB 收錄了個漢字GB的總編碼空間超過萬個碼位

  GB 字符集標准解決漢字日文假名朝鮮語和中國少數民族文字組成的大字符集計算機編碼問題該標准的字符總編碼空間超過萬個編碼位收錄了 個漢字覆蓋中文日文朝鮮語和中國少數民族文字滿足中國大陸香港台灣日本和韓國等東亞地區信息交換多文種大字量多用途統一編碼格式的要求並且與Unicode 版本兼容填補Unicode擴展字符字匯統一漢字擴展A的內容並且與以前的國家字符編碼標准(GBGB)兼容

  GB 標准采用單字節雙字節和四字節三種方式對字符編碼單字節部分使用××F碼(對應於ASCII碼的相應碼)雙字節部分首字節碼從××FE尾字節碼位分別是××E和××FE四字節部分采用GB/T 未采用的××作為對雙字節編碼擴充的後綴這樣擴充的四字節編碼其范圍為××FEFE其中第一三個字節編碼碼位均為××FE第二四個字節編碼碼位均為××

  雙字節部分收錄內容主要包括GB全部CJK漢字有關標點符號表意文字描述符增補的漢字和部首/構件雙字節編碼的歐元符號等四字節部分收錄了上述雙字節字符之外的包括CJK統一漢字擴充A在內的GB 中的全部字符

  ANSI編碼

  不同的國家和地區制定了不同的標准由此產生了 GB BIG JIS 等各

  

  自的編碼標准這些使用 個字節來代表一個字符的各種漢字延伸編碼方式稱為 ANSI 編碼在簡體中文系統下ANSI 編碼代表 GB 編碼在日文操作系統下ANSI 編碼代表 JIS 編碼DBCS(Double Byte Charecter Set 雙字節字符集)在DBCS系列標准裡最大的特點是兩字節長的漢字字符和一字節長的英文字符並存於同一套編碼方案裡因此他們寫的程序為了支持中文處理必須要注意字串裡的每一個字節的值如果這個值是大於那麼就認為一個雙字節字符集裡的字符出現了

  漢字編碼范圍

  名稱 第一字節 第二字節

  GB xBxF() xAxFE()

  GBK ×xFE() ×xFE()

  Big ×xFE() ××E()或者xAxFE()

   字符集編碼(Character Set Encoding)

  ASCIIGBGBKBIGGB UCSUtfutfutf 都有自己不同的規則都有自己的對應規則但都兼容ASCII在使用時要注意這些編碼相互之間的轉換規則對於沒有轉換規則的編碼體系之間進行轉換只能依靠查編碼表進行

   ISO的編碼體系

   ASCII編碼

  ASCII的編號是ISO

   ISO編碼

  ISO 全稱ISO/IEC 是國際標准化組織(ISO)及國際電工委員會(IEC)聯合制定的一系列位字符集的標准現時定義了個字符集

  * ISO (Latin) – 西歐語言

  * ISO (Latin) – 中歐語言

  * ISO (Latin) – 南歐語言世界語也可用此字符集顯示

  * ISO (Latin) – 北歐語言

  * ISO (Cyrillic) – 斯拉夫語言

  * ISO (Arabic) – 阿拉伯語

  * ISO (Greek) – 希臘語

  * ISO (Hebrew) – 希伯來語(視覺順序)

  * ISO I – 希伯來語(邏輯順序)

  * ISO (Latin 或 Turkish) – 它把Latin的冰島語字母換走加入土耳其語字母

  * ISO (Latin 或 Nordic) – 北日耳曼語支用來代替Latin

  * ISO (Thai) – 泰語從泰國的 TIS 標准字集演化而來

  * ISO (Latin 或 Baltic Rim) – 波羅的語族

  * ISO (Latin 或 Celtic) – 凱爾特語族

  * ISO (Latin) – 西歐語言加入Latin欠缺的法語及芬蘭語重

  

  音字母以及歐元符號

  * ISO (Latin) – 東南歐語言主要供羅馬尼亞語使用並加入歐元符號

  ISO(UCS)編碼與Unicode

  UCS :

  通用字符集(Universal Character SetUCS)是由ISO制定的ISO (或稱ISO/IEC )標准所定義的字符編碼方式采用字節編碼

  Unicode:

  Unicode(統一碼萬國碼單一碼)是一種在計算機上使用的字符編碼

  它是 制定的編碼機制 要將全世界常用文字都函括進去它為每種語言中的每個字符設定了統一並且唯一的二進制編碼以滿足跨語言跨平台進行文本轉換處理的要求年開始研發年正式公布隨著計算機工作能力的增強Unicode也在面世以來的十多年裡得到普及但自從unicode開始Unicode采用了與ISO 相同的字庫和字碼ISO也承諾ISO將不會給超出×FFFF的UCS編碼賦值使得兩者保持一致Unicode的編碼方式與ISO 的通用字符集(Universal Character SetUCS)概念相對應目前的用於實用的Unicode版本對應於UCS使用位的編碼空間也就是每個字符占用個字節基本滿足各種語言的使用實際上目前版本的Unicode尚未填充滿這位編碼保留了大量空間作為特殊使用或將來擴展

  UTF:

  Unicode 的實現方式不同於編碼方式

  一個字符的Unicode編碼是確定的但是在實際傳輸過程中由於不同系統平台的設計不一定一致以及出於節省空間的目的對Unicode編碼的實現方式有所不同Unicode的實現方式稱為Unicode轉換格式(Unicode Translation Format簡稱為 UTF)

  UTF: bit變長編碼對於大多數常用字符集(ASCII中~字符)它只使用單字節而對其它常用字符(特別是朝鮮和漢語會意文字)它使用字節

  UTF: bit編碼是變長碼大致相當於位編碼值在×

  ×FFFF之間基本上就是Unicode編碼的實現與CPU字序有關

  UTF:bit編碼定長編碼對應於字符的Unicode表示

  Unicode big endia:

  在Windows系統中保存文本文件時通常可以選擇編碼為ANSIUnicodeUnicode big endian和UTF這裡的ANSI和Unicode big endia是什麼編碼呢?

  UTF以字節為編碼單元沒有字節序的問題UTF以兩個字節為編碼單元在解釋一個UTF文本前首先要弄清楚每個編碼單元的字節序

  Unicode規范中推薦的標記字節順序的方法是BOM(即Byte Order Mark)

  在UCS編碼中有一個叫做ZERO WIDTH NOBREAK SPACE的字符它的編碼是FEFF而FFFE在UCS中是不存在的字符所以不應該出現在實際傳輸中UCS規范建議我們在傳輸字節流前先傳輸字符ZERO WIDTH NOBREAK SPACE

  如果接收者收到FEFF就表明這個字節流是BigEndian的如果收到FFFE

  

  就表明這個字節流是LittleEndian的因此字符ZERO WIDTH NOBREAK SPACE又被稱作BOMWindows就是使用BOM來標記文本文件的編碼方式的

   codepage的編碼體系

  codepage 指的是一個經過挑選的以特定順序排列的字符內碼列表對於早期的單字節內碼的語種codepage中的內碼順序使得系統可以按照此列表來根據鍵盤的輸入值給出一個對應的內碼對於雙字節內碼則給出的是MultiByte到Unicode的對應表這樣就可以把以Unicode形式存放的字符轉化為相應的字符內碼類似unicode只是另外一種字符編碼方式注意ASP和SAP中的codepage的區別

  ASP中

  CodePage的作用是決定頁面以何種編碼方式顯示動態內容當頁面被服務器處理之後頁面將以CodePage設定的編碼輸出到客戶端當然CodePage的參數需正確否則將產生錯誤信息CodePage 值無效指定的 CodePage 值無效(事件ID: 如果CodePage沒有設置則服務器使用默認的CodePage加載到你的Session裡面使用程序代碼 ResponseWrite(SessionCodePage)可以查看你當前使用的CodePage

  SAP中最經常我們使用的讀取數據的方法就是使用GUI_UPLOAD這個FM在這個FM中有個CODEPAGE是用來指定代碼頁的

  Siebel Value

  SAP Code page

  Description

  CP

  

  SAP Latin – ISO – code page

  ISO

  

  SAP Latin – ISO

  ISO

  

  SAP Cyrillic – ISO

  CP

  

  SAP Turkish – ISO

  CP

  

  SAP Greek – ISO – Not a complete match

  CP

  

  SAP Hebrew – ISO – Not a complete match

  CP

  

  

  SAP ShiftJIS

  CP

  

  SAP Taiwanese

  CP

  

  SAP Chinese

  CP

  

  SAP Korean

  CP

  

  SAP Thai

  

  Unicode歷史

  Unicode聯盟與ISO的工作組終於開始討論Unicode與UCS的合並問題最終兩者統一了抽象字符集(即任何一個在 Unicode中存在的字符在UCS中也存在)對於碼空間兩者同意以一百一十萬為限Unicode將碼空間擴展到了一百一十萬而UCS將永久性的不使用一百一十萬以後的碼位UCS和Unicode都指的是編碼字符集而不是字符集編碼

  字符集編碼決定了如何將一個字符的整數編號對應到一個二進制的整數值有的編碼方案簡單的將該整數值直接作為其在計算機中的表示而存儲例如英文字符就是這樣幾乎所有的字符集編碼方案中英文字母的整數編號與其在計算機內部存儲的二進制形式都一致當初Unicode與UCS還沒成家之時UCS也是需要人愛需要人疼的沒有自己的字符集編碼怎麼成UCS與UCS就扮演了這樣的角色 UCS與UTF除了名字不同以外思想完全一樣而UCS與UTF在對前個字符的處理上也完全相同唯一的區別只在於 UCS 不支持surrogate pair機制即是說UCS只能對前個字符編碼對其後的字符毫無辦法

  

  Unicode的編碼形式

   Unicode字符集

  Unicode字符集編碼是Universal MultipleOctet Coded Character Set 通用多八位編碼字符集的簡稱是由一個名為 Unicode 學術學會(Unicode Consortium)的機構制訂的字符

  編碼系統支持現今世界各種不同語言的書面文本的交換處理及顯示該編碼於年開始研發年正式公布最新版本是日的 Unicode Unicode是一種在計算機上使用的字符編碼它為每種語言中的每個字符設定了統一並且唯一的二進制編碼以滿足跨語言跨平台進行文本轉換處理的要求Unicode 標准始終使用十六進制數字而且在書寫時在前面加上前綴U+例如字母A的編碼為 所以A的編碼書寫為U+

  

  現在的Unicode碼空間為U+到U+FFFF一共個碼位其中只有 個碼位是合法的(我來替你做算術個碼位不合法)但並不是說現在的Unicode就有這麼多個字符了實際上其中很多碼位還是空閒的到 Unicode 規范為止只有個碼位被分配了字符(但無論如何仍比很多人認為的個字符要多得多了)其中U+ 到U+FFFF的部分被稱為基本多語言面(Basic Multilingual PlaneBMP)U+及以上的字符稱為補充字符在Java中(Java之後)補充字符使用兩個char型變量來表示這兩個 char型變量就組成了所謂的surrogate pair(在底層實際上是使用一個int進行表示的)第一個char型變量的范圍稱為高代理部分(highsurrogates rangeuDuDBFF個碼位) 第二個char型變量的范圍稱為lowsurrogates range(從uDCuDFFF個碼位)這樣使用surrogate pair可以表示的字符數一共是的平方計加上BMP的個碼位去掉個非法的碼位正好是 個碼位

  關於Unicode的碼空間實際上有一些稍不小心就會讓人犯錯的地方比如我們都知道從U+到U+FFFF的部分被稱為基本多語言面(Basic Multilingual PlaneBMP)這個范圍內的字符在使用UTF編碼時只需要一個char型變量就可以保存仔細看看這個范圍應該有這麼大因此你會說單字節的UTF編碼能夠表示個字符你也會說Unicode的基本多語言面包含個字符但是再想想剛才說過的 surrogate pair一個UTF表示的增補字符(再一次的需要兩個char型變量才能表示的字符)怎樣才能被正確的識別為增補字符而不是兩個普通的字符呢?答案你也知道就是通過看它的第一個char是不是在高代理范圍內第二個char是不是在低代理范圍內來決定這也意味著高代理和低代理所占的共 個碼位(從xDxDFFF)是不能分配給其他字符的但這是對UTF這種編碼方法而言而對Unicode這樣的字符集呢?在 Unicode的編號中U+D到U+DFFF是否有字符分配?答案是也沒有!這是典型的字符集為方便編碼方法而做的安排(你問他們這麼做的目的?當然是希望基本多語言面中的字符和一個char型的UTF編碼的字符能夠一一對應少些麻煩從中我們也能看出UTF與Unicode間很深的淵源與結合)也就是說無論Unicode還是UTF編碼後的字符×xFFFF這個范圍內只有個字符這就好比最初的CPU被勉強拿來做多媒體應用用得多了CPU就不得不修正自己從硬件上對多媒體應用提供支持了

  盡管不情願但說到這裡總還得扯扯相關的概念代碼點和代碼單元代碼點(Code Point)就是指Unicode中為字符分配的編號一個字符只占一個代碼點例如我們說到字符它的代碼點是U+C代碼單元(Code Unit)則是針對編碼方法而言它指的是編碼方法中對一個字符編碼以後所占的最小存儲單元例如UTF代碼單元是一個字節因為一個字符可以被編碼為個或者個字節在UTF代碼單元變成了兩個字節(就是一個 char)因為一個字符可以被編碼為個或個char(你找不到比一個char還小的UTF編碼的字符嘿嘿)說得再羅嗦一點一個字符僅僅對應一個代碼點但卻可能有多個代碼單元(即可能被編碼為個char)以上概念絕非學術化的繞口令這意味著當你想以一種統一的方式指定自己使用什麼字符的時候使用代碼點(即你告訴你的程序你要用Unicode中的第幾個字符)總是比使用代碼單元更好(因為這樣做的話你還得區分情況有時候提供一個進制數字有時候要提供兩個)

  

  例如我們有一個增補字符???(哈哈你看到了三個問號對吧?因為我的系統顯示不出這個字符)它在Unicode中的編號是U+FA當在程序中需要使用這個字符的時候就可以這樣來寫

  String s=StringvalueOf(CharactertoChars(×FA));

  char[]chars=stoCharArray();

  for(char c:chars){

  Systemoutformat(%x(short)c);

  }

  後面的for循環把這個字符的UTF編碼打印了出來結果是dedca注意到了嗎?這個字符變成了兩個char型變量其中xde就是高代理部分的值xdca就是低代理的值

  Unicode字符集編碼(Universal MultipleOctet Coded Character Set)通用多八位編碼字符集的簡稱支持世界上超過種語言的國際字符集Unicode是一種在計算機上使用的字符編碼它為每種語言中的每個字符設定了統一並且唯一的二進制編碼以滿足跨語言跨平台進行文本轉換處理的要求Unicode 標准始終使用十六進制數字而且在書寫時在前面加上前綴U+字母A的編碼書寫為U+

  Unicode計劃使用了個平面一共有 *=個碼位在Unicode 版本中已定義的碼位只有分布在平面平面平面平面平面平面其中平面和平面上只是定義了兩個各占個碼位的專用區(Private Use Area)分別是xFxFFFFD和××FFFD所謂專用區就是保留給大家放自定義字符的區域可以簡寫為 PUA平面也有一個專用區xExFFF個碼位平面xDxDFFF個碼位是一個被稱作代理區(Surrogate)的特殊區域代理區的目的用兩個UTF字符表示BMP以外的字符在介紹UTF編碼時會介紹如前所述在Unicode 版本中*=余下的個已定義碼位分布在平面平面平面和平面 它們對應著Unicode目前定義的個字符其中包括個漢字平面平面平面和平面上分別定義了 個字符平面個字符都是漢字平面上定義了個漢字

   UCS編碼

  早期的Unicode標准有UCSUCS的說法UCS用兩個字節編碼UCS個字節編碼UCS根據最高位為的最高字節分成^=個group每個group再根據次高字節分為個平面(plane)每個平面根據第個字節分為行(row)每行有 個碼位(cell)group 的平面被稱作BMP(Basic Multilingual Plane)將UCS的BMP去掉前面的兩個零字節就得到了UCS

  每個平面有^=個碼位

   UTF編碼

  Unicode 標准的編碼字符集的字符編碼方案UTF是 Unicode Translation Format即把Unicode轉做某種格式的意思UTFUTF 和 UTF 是Unicode 標准的編碼字符集的字符編碼方案UTF 使用一個或兩個未分配的

  

  位代碼單元的序列對Unicode 代碼點進行編碼UTF 即將每一個 Unicode 代碼點表示為相同值的 位整數

  在Unicode中漢字對應的數字是在Unicode中我們有很多方式將數字表示成程序中的數據包括UTF UTFUTFUTF是UCS Transformation Format的縮寫可以翻譯成Unicode字符集轉換格式即怎樣將Unicode定義的數字轉換成程序數據例如漢字對應的數字是 ×c×b而編碼的程序數據是

  BYTE data_utf[] = {xE xB × xE xAD ×}; // UTF編碼

  WORD data_utf[] = {×c ×b}; // UTF編碼

  DWORD data_utf[] = {×c ×b}; // UTF編碼

  這裡用BYTEWORDDWORD分別表示無符號位整數無符號位整數和無符號 位整數UTFUTFUTF分別以BYTEWORDDWORD作為編碼單位漢字的UTF編碼需要個字節漢字的 UTF編碼需要兩個WORD大小是個字節漢字的UTF編碼需要兩個DWORD大小是個字節根據字節序的不同UTF可以被實現為UTFLE或UTFBEUTF可以被實現為UTFLE或UTFBE下面介紹UTFUTF UTF字節序和BOM

  UTF

  UTF最多是使用個字節來表示一個字符但理論上來說UTF最多需要用字節表示一個字符

  F的字符用單個字節來表示

  FF的字符用兩個字節表示(中文的編碼范圍)

  FFFF的字符用字節表示

  UTF以字節為單位對Unicode進行編碼從Unicode到UTF的編碼方式如下

  Unicode編碼 ║ UTF 字節流(二進制)

  F ║ xxxxxxx bit

  FF ║ xxxxx xxxxxx bit

  FFFF ║ xxxx xxxxxx xxxxxx bit

  FFFF ║ xxx xxxxxx xxxxxx xxxxxx bit

  UTF的特點是對不同范圍的字符使用不同長度的編碼對於××F之間的字符UTF編碼與ASCII編碼完全相同UTF編碼的最大長度是個字節從上表可以看出字節模板有個x即可以容納位二進制數字Unicode的最大碼位×FFFF也只有

  例字的Unicode編碼是×C×C×xFFFF之間使用用字節模板了xxxx xxxxxx xxxxxx×C寫成二進制是 用這個比特流依次代替模板中的x得到 即E B

  例Unicode編碼×C××FFFF之間使用用 字節模板了xxx xxxxxx xxxxxx xxxxxx×C寫成位二進制數字(不足位就在前面補 用這個比特流依次代替模板中的x得到 即F A B B

  

  UTF

  UTF編碼以位無符號整數為單位我們把Unicode編碼記作U編碼規則如下

  如果U<×U的UTF編碼就是U對應的位無符號整數(為書寫簡便下文將位無符號整數記作WORD)

  如果U≥×我們先計算U=U×然後將U寫成二進制形式yyyy yyyy yyxx xxxx xxxxU的UTF編碼(二進制)就是yyyyyyyyyy xxxxxxxxxx

  為什麼U可以被寫成個二進制位?Unicode的最大碼位是×ffff減去 ×U的最大值是xfffff所以肯定可以用個二進制位表示例如Unicode編碼×C減去×得到×C寫成二進制是 用前位依次替代模板中的y用後位依次替代模板中的x就得到 xD xDC

  按照上述規則Unicode編碼××FFFF的UTF編碼有兩個WORD第一個WORD的高位是第二個 WORD的高位是可見第一個WORD的取值范圍(二進制)是 xDxDBFF第二個WORD的取值范圍(二進制)是 xDCxDFFF

  為了將一個WORD的UTF編碼與兩個WORD的UTF編碼區分開來Unicode編碼的設計者將xDxDFFF保留下來並稱為代理區(Surrogate)

  D-DBF ║ High Surrogates ║ 高位替代

  DB-DBFF ║ High Private Use Surrogates ║ 高位專用替代

  DC-DFFF ║ Low Surrogates ║ 低位替代

  高位替代就是指這個范圍的碼位是兩個WORD的UTF編碼的第一個WORD低位替代就是指這個范圍的碼位是兩個WORD的UTF編碼的第二個WORD那麼高位專用替代是什麼意思?我們來解答這個問題順便看看怎麼由UTF 編碼推導Unicode編碼

  如果一個字符的UTF編碼的第一個WORD在xDBxDBFF之間那麼它的 Unicode編碼在什麼范圍內?我們知道第二個WORD的取值范圍是xDCxDFFF所以這個字符的UTF編碼范圍應該是 xDB xDCxDBFF xDFFF我們將這個范圍寫成二進制

  

  按照編碼的相反步驟取出高低WORD的後並拼在一起得到

  

  即xexfffff按照編碼的相反步驟再加上×得到xf×ffff這就是UTF編碼的第一個 WORD在xdbxdbff之間的Unicode編碼范圍即平面和平面因為Unicode標准將平面和平面都作為專用區所以xDBxDBFF之間的保留碼位被稱作高位專用替代

  UTF

  UTF編碼以位無符號整數為單位Unicode的UTF編碼就是其對應的位無符號整數

  

  字節序

  根據字節序的不同UTF可以被實現為UTFLE或UTFBEUTF可以被實現為UTFLE或UTFBE例如

  Unicode編碼 ║ UTFLE ║ UTFBE ║ UTFLE ║ UTFBE

  ×C C ║ C C C

  ×C D DC ║ D DC C C

  BOM

  那麼怎麼判斷字節流的字節序呢?Unicode標准建議用BOM(Byte Order Mark)來區分字節序即在傳輸字節流前先傳輸被作為BOM的字符零寬無中斷空格這個字符的編碼是FEFF而反過來的FFFE(UTF )和FFFE(UTF)在Unicode中都是未定義的碼位不應該出現在實際傳輸中下表是各種UTF編碼的BOM

  UTF編碼 ║ Byte Order Mark

  UTF ║ EF BB BF

  UTFLE ║ FF FE

  UTFBE ║ FE FF

  UTFLE ║ FF FE

  UTFBE ║ FE FF

  

  java中使用的Unicode

   內部編碼

  Java中字符只以一種形式存在那就是JVM內部的內部表示Unicode碼編號(U+~U+FFFF)JVM的唯一確定一個字符使得一個編碼在進入jvm或者從jvm輸出時需要進行編碼轉換也就是編碼轉換只發生在JVM和OS以及網絡傳輸的交互地帶也就是IO的各種byte或者 reader/writer輸入輸出發生作用的地方在JVM和OS以及網絡流交互的時間Reader和Writer只是適用默認編碼進行了默認的編碼轉換來轉換為字符流面向字符是指系統文件中的字符和內存中的要一致而面向字節是要保證系統中的二進制內容和讀入JVM內部的二進制內容要一致

   utf

  總共個平面

  ×~×FFFF =個碼位

  Unicode已定義的碼位是

  平面之定義了占個碼位的專用區xF~xFFFFD

  平面之定義了占個碼位的專用區×~×FFFD

  平面中定義了個專有區xE~xFFF

  *=余下的分布在平面

  

  平面上定義了個字符

  平面上定義了個字符

  平面上定義了個字符

  平面上定義了個字符

  平面個字符都是漢字平面上定義了個漢字

  基本平面 ×~xFFFF

  ~平面 ×~xEFFFF xD~xDBFF高位 DCOO~DFFF低位

  平面 xF~xFFFFF xDB~xDBBF高位 DCOO~DFFF低位

  平面 ×~×FFFF xDBC~xDBFF高位 DCOO~DFFF低位

  高位序列和低位序列的判斷

  javalangString#getBytes(String) 的源代碼

  javalangStringCodingencode 的源代碼再通過其底層類庫的字符集類sunioCharacterEncoding 可以找出 Unicode 的轉換器是采用sunioCharToByteUnicode 這個類的這個類的 sunio 包是讀取fileencodingpkg 這個系統屬性拼接字符串反射而來的

  

  常見問題

   通用UTF來編碼

  大量使用國外的開源軟件時UTF才是編碼界最通用的語言對英文是單字節中文是三字節在大量的英文存在的情況下高效

  編碼問題時查看

  %javahome%/jre/lib/charsetsjar

   語言的編碼

  CC++Python內部字符串都是使用當前系統默認編碼

  PythonJava內部字符串用Unicode保存

  Ruby有一個內部變量$KCODE用來表示可識別的多字節字符串的編碼變量值為EUC SJIS UTFNONE之一$KCODE的值為EUC將假定字符串或正則表達式的編碼為EUCJP同樣地若為SJIS時則認定為Shift JIS若為UTF″時則認定為UTF若為NONE將不會識別多字節字符串在向該變量賦值時只有第個字節起作用且不區分大小寫字母e E 代表EUCs S 代表 SJISu U 代表 UTFn N 則代表 NONE默認值為NONE即默認情況下Ruby把字符串當成單字節序列來處理

   js的unicode

  <script type=text/javascript>

  documentwrite(StringfromCharCode());

  documentwrite(<br />);

  documentwrite(StringfromCharCode());

  </script>

  

   網頁編碼

  一個網頁要在浏覽器中正常顯示需要保持網頁文件的編碼網頁的meta標簽聲明(charset 來制定的其實是encoding編碼而不是字符集)浏覽器編碼設置是一致的

   聯通亂碼

  在Win下的新建一個記事本文件輸入聯通兩個字之後保存之後重新打開發現出現亂碼這是因為GBK編碼與UTF編碼產生了編碼沖突

  從UNICODE到UTF的轉換規則

  Unicode UTF

  F xxxxxxx

  FF xxxxx xxxxxx

   – FFFF xxxx xxxxxx xxxxxx

  聯的Unicode編碼是[x] [x]

  通的Unicode編碼是[x] [xA]

  A在FFFF之間所以要用字節模板xxxx xxxxxx xxxxxx使用第三種轉換得到

  [xE] [x] [x] [xE] [x] [xA]這就是其UTF的編碼

  新建一個文本文件時記事本的編碼默認是ANSI 中文的就是GBK編碼此時聯通的內碼是[xC] [xAA] [xCD] [xA]

  C

  AA

  CD

  A

  其中聯的兩個字節通的兩個字節的起始部分的都是″和與UTF規則裡的兩字節模板是一致所以再次用記事本打開時記事本誤認為這是一個UTF編碼的文件按照反編碼得到UNICODE的x A××這個字符什麼也不是這就是聯通兩個字的文件沒有辦法在記事本裡正常顯示的原因如果多幾個字的輸入話由於記事本檢測到不是合格的uft編碼的字節轉而會采用GBK亂碼又不出現

  Google學習亂碼

  CN&newwindow=&q=學習

  出現亂碼

   java 編譯時的亂碼

  對於不是平台默認編碼的情況下java源文件在編譯時需要指定源文件的編碼否則無法正常編譯

  對於win下默認的GBK編碼

  C:\>javac SqlUtilityjava

  C:\>javac encoding GBK SqlUtilityjava

  C:\>javac encoding utf SqlUtilityjava

  

  SqlUtilityjava:: 警告編碼 utf 的不可映射字符

  * ????????????????

  ^

  對於unicode的默認是utf

  C:\>javac SqlUtilityjava

  SqlUtilityjava:: 非法字符 \

  C:\>javac encoding utf SqlUtilityjava

  對於utf的編碼win下需要刪除文件頭的二進制編碼EFBBBF(因為它是由Unicode標准的FEFF為了保證字節序而存在)並不是

  C:\>javac SqlUtilityjava

  SqlUtilityjava:: 警告編碼 GBK 的不可映射字符

  锘?**

  ^

  SqlUtilityjava:: 非法字符 \

  锘?**

  ^

   錯誤

   警告

  C:\>javac encoding utf SqlUtilityjava

  SqlUtilityjava:: 非法字符 \

  C:\>javac encoding utf SqlUtilityjava

  SqlUtilityjava:: 非法字符 \

  ?/**

  ^

   錯誤

  注刪除EFBBBF之後的

  C:\>javac encoding utf SqlUtilityjava


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26112.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.