关于字符编码,中文所占字节的整理。
1個(gè)字節(jié)byte=8bit(比特/位) ?1bit=0.125B字節(jié)
1個(gè)漢字兩個(gè)字節(jié) 16bit,2B.
字符:漢字,數(shù)字,字母等
Byte,bit是存儲單位
Bit——比特
B ——字節(jié)?
KB——千字節(jié)?
MB——兆字節(jié)?
GB——吉字節(jié)?
TB——太字節(jié)?
1B=8 Bit
1KB=1024B?
1MB=1024KB?
1GB=1024MB?
1TB=1024GB
中文不止2的8次方個(gè)255個(gè)字符。所以一個(gè)字節(jié)肯定不能表示。
你可能回想兩個(gè)字節(jié)2的16次方65 536。Gbk收錄的字?jǐn)?shù)沒有超過這數(shù)量。因此GBK、GB2312收編的漢字占2個(gè)字節(jié)。但是沒這么簡單,除了中文外還有其他的文字。
?
常用中文字符用utf-8編碼占用3個(gè)字節(jié)(大約2萬多字),但超大字符集中的更大多數(shù)漢字要占4個(gè)字節(jié)(在unicode編碼體系中,U+20000開始有5萬多漢字)。
相關(guān)補(bǔ)充:
?
?
?
我們知道機(jī)器只知道字節(jié),而字符卻是語義上的單位,它是有編碼的,一個(gè)字符可能編碼成1個(gè)2個(gè)甚至3個(gè)4個(gè)字節(jié)。這跟字符集編碼有關(guān)系,英文字母和數(shù)字是單字節(jié),但漢字這些自然語言中的字符是多字節(jié)的。一個(gè)字節(jié)只能表示255個(gè)字符,不可能用于全球那么多種自然語言的處理,因此肯定需要多字節(jié)的存儲方式。
當(dāng)我們在處理 Java 時(shí),比如 InputStream, OutputStream 它們是處理字節(jié)流的,就是說假設(shè)所有東西都是二進(jìn)制的字節(jié),而 Reader, Writer 則是字符流,它涉及到字符集的問題,因?yàn)榘岩粋€(gè)字符保存到磁盤或讀取出來需要指定一個(gè)字符集,平時(shí)你的代碼沒有指定是因?yàn)?JVM 讀取操作系統(tǒng)默認(rèn)的字符集,有時(shí)候(特別是數(shù)據(jù)交換的時(shí)候)可能這個(gè)默認(rèn)字符集不正確。
在 Java 中,它的內(nèi)核是使用 Unicode,也就是說它記住了每個(gè)字符的 Unicode 內(nèi)部編碼(一串?dāng)?shù)字,全球唯一,各國語言常用字符全部在里面,比如康熙字典這種古董中的多數(shù)漢字都在其中),只有把字符串通過網(wǎng)絡(luò)發(fā)送出去或保存到磁盤上或反過來讀取時(shí)才有字符編碼成字節(jié)的過程,因?yàn)橐粋€(gè)字符多個(gè)字節(jié)我們需要知道每個(gè)字符的這幾個(gè)字節(jié)是按什么順序排列的,第1個(gè)字節(jié)排前面還是排后面,多個(gè)字符串在一起時(shí)在讀取時(shí)怎么識別出哪幾個(gè)字節(jié)湊在一起是一個(gè)字符,這就是字符集編碼方案了,UTF8, GBK, GB2312, GB18030, BIG5,之類的都是其中一種字符集編碼方案。
inputStream?讀的是字節(jié)流,inputStreamReader?是inputStream到Reader的橋梁。Reader支持16位的Unicode字符輸出,
InputStream支持8位的字符輸出。InputStream 用于讀入?ASCII?字符和二進(jìn)制數(shù)據(jù)。
write(byte[] b,int off,int len)中的off偏移量具體指的是什么?
byte[] words = str.getBytes();
fos = new FileOutputStream("c:/test.txt");//此文件輸出流對象fos就和目標(biāo)數(shù)據(jù)源(c:/test.txt)聯(lián)系起來了。
fos.write(words, 0, words.length);//利用write方法將數(shù)據(jù)寫入到文件中去
System.out.println("文件已更新!");
這是代碼,我把0改成別的數(shù)就會(huì)出現(xiàn)異常。求高人講解!!
樓主的問題是off+len>b.length了,就是寫入的輸出字節(jié)數(shù)超出了要寫入的字節(jié)的長度;就好像我要只有4個(gè)字節(jié)的文字,卻要輸出到第5個(gè)字節(jié),那當(dāng)然會(huì)報(bào)錯(cuò)啦~~
//?有文字和符號種類加起來也只要編到?4個(gè)字節(jié)長就夠了。
//? UTF-8?是以?8位(即?1個(gè)字節(jié))為單元對原始碼進(jìn)行編碼(注意一
//?點(diǎn):這里所講的原始碼都是指Unicode碼),并規(guī)定:多字節(jié)碼(2個(gè)字
//?節(jié)以上才稱為多字節(jié))以轉(zhuǎn)換后第1個(gè)字節(jié)起頭的連續(xù)“1”的數(shù)目(這
//?些連續(xù)“1”稱為標(biāo)記位),表示轉(zhuǎn)換成幾個(gè)字節(jié):“110”連續(xù)兩個(gè)
//?“1”,表示轉(zhuǎn)換結(jié)果為2個(gè)字節(jié),“1110”表示3個(gè)字節(jié),而“11110”
//?則表示4個(gè)字節(jié)……跟隨在標(biāo)記位之后的“0”,其作用是分隔標(biāo)記位和
//?字符碼位。第2~第4個(gè)字節(jié)的起頭兩個(gè)位固定設(shè)置為“10”,也作為標(biāo)
//?記,剩下的6個(gè)位才做為字符碼位使用。
//? 這樣,2字節(jié)UTF-8碼剩下11個(gè)字符碼位,可用以轉(zhuǎn)換0080~07FF的
//?原始字符碼,3字節(jié)剩下16個(gè)字符碼位,可用以轉(zhuǎn)換0800~FFFF的原始字
//?符碼,由此類推。編碼方式的模板如下:
//
//?原始碼(16進(jìn)制) UTF-8編碼(二進(jìn)制)
//?--------------------------------------------
//?0000?-?007F???????0xxxxxxx
//?0080?-?07FF???????110xxxxx?10xxxxxx
//?0800?-?FFFF???????1110xxxx?10xxxxxx?10xxxxxx
//?……
//?--------------------------------------------
//
//? 模板中的“x”表示字符碼。
//? Ascii碼<007F,編為1個(gè)
//?字節(jié)的UTF-8碼。漢字的?Unicode編碼范圍為0800-FFFF,所以被編為
//?3個(gè)字節(jié)的UTF-8碼。
//? 例如“漢”字的Unicode編碼是6C49,6C49在0800-FFFF之間,所以
//?要用3個(gè)字節(jié)的模板:1110wwww?10xxxxyy?10yyzzzz。
//????6????C????4????9
//?0110?1100?0100?1001
//?wwww?xxxx?yyyy?zzzz
//?????wwww???xxxxyy???yyzzzz
//?1110wwww?10xxxxyy?10yyzzzz。
//?11100110?10110001?10001001
//????E???6????B???1????8???9
//“漢”字的UTF-8編碼是E6?B1?89
關(guān)于Unicode字符集
工程--設(shè)置--C/C++--預(yù)處理器,可以定義標(biāo)識符,如UNICODE,_UNICODE,標(biāo)識是按ASCII編譯,還是按UNICODE編譯
#include <tchar.h>
char定義全部 改成TCHAR,TCHAR根據(jù)設(shè)置不同定義為char或者wchar
字符串加用TEXT宏,如TEXT("你好"),根據(jù)編譯器的設(shè)置不同,分別定義為ANSI或者UNICODE版本
字符串也大部分有其通用版本:
最大長度版比標(biāo)準(zhǔn)版多一個(gè)參數(shù),表示緩沖區(qū)的長度
有v的其參數(shù)為參數(shù)列表指針,使用va_list、va_start和va_end宏
C提供的字符串函數(shù): ASCII 寬字符 通用形式
1.可變參數(shù):
標(biāo)準(zhǔn)版 sprintf swprintf _stprintf
最大長度版 _snprintf _snwprintf _sntprintf
WindowsNT版 wsprintfA wsprintfW wsprintf
2.數(shù)組的指針作參數(shù):
???
標(biāo)準(zhǔn)版 vsprintf vswprintf _vstprintf
最大長度版 _vsnprintf _vsnwprintf _vsntprintf
WindowsNT版 wvsprintfA wvsprintfW wvsprintf
以下引用《Windows程序設(shè)計(jì)》
美國標(biāo)準(zhǔn)
早期計(jì)算機(jī)的字符碼是從Hollerith卡片(號稱不能被折迭、卷曲或毀傷)發(fā)展而來的,該卡片由Herman Hollerith發(fā)明并首次在1890年的美國人口普查中使用。6位字符碼系統(tǒng)BCDIC(Binary-Coded Decimal Interchange Code:二進(jìn)制編碼十進(jìn)制交換編碼)源自Hollerith代碼,在60年代逐步擴(kuò)展為8位EBCDIC,并一直是IBM大型主機(jī)的標(biāo)準(zhǔn),但沒使用在其它地方。
美國信息交換標(biāo)準(zhǔn)碼(ASCII:American Standard Code for Information Interchange)起始于50年代后期,最后完成于1967年。開發(fā)ASCII的過程中,在字符長度是6位、7位還是8位的問題上產(chǎn)生了很大的爭議。從可靠性的觀點(diǎn)來看不應(yīng)使用替換字符,因此ASCII不能是6位編碼,但由于費(fèi)用的原因也排除了8位版本的方案(當(dāng)時(shí)每位的儲存空間成本仍很昂貴)。這樣,最終的字符碼就有26個(gè)小寫字母、26個(gè)大寫字母、10個(gè)數(shù)字、32個(gè)符號、33個(gè)句柄和一個(gè)空格,總共128個(gè)字符碼。ASCII現(xiàn)在記錄在ANSI X3.4-1986字符集-用于信息交換的7位美國國家標(biāo)準(zhǔn)碼(7-Bit ASCII:7-Bit American National Standard Code for Information Interchange),由美國國家標(biāo)準(zhǔn)協(xié)會(huì)(American National Standards Institute)發(fā)布。圖2-1中所示的ASCII字符碼與ANSI文件中的格式相似。
ASCII有許多優(yōu)點(diǎn)。例如,26個(gè)字母代碼是連續(xù)的(在EBCDIC代碼中就不是這樣的);大寫字母和小寫字母可通過改變一位數(shù)據(jù)而相互轉(zhuǎn)化;10個(gè)數(shù)字的代碼可從數(shù)值本身方便地得到(在BCDIC代碼中,字符「0」的編碼在字符「9」的后面!)
最棒的是,ASCII是一個(gè)非常可靠的標(biāo)準(zhǔn)。在鍵盤、視訊顯示卡、系統(tǒng)硬件、打印機(jī)、字體文件、操作系統(tǒng)和Internet上,其它標(biāo)準(zhǔn)都不如ASCII碼流行而且根深蒂固。
圖2-1 ASCII字符集
國際方面
ASCII的最大問題就是該縮寫的第一個(gè)字母。ASCII是一個(gè)真正的美國標(biāo)準(zhǔn),所以它不能良好滿足其它講英語國家的需要。例如英國的英鎊符號(£)在哪里?
英語使用拉丁(或羅馬)字母表。在使用拉丁語字母表的書寫語言中,英語中的單詞通常很少需要重音符號(或讀音符號)。即使那些傳統(tǒng)慣例加上讀音符號也無不當(dāng)?shù)挠⒄Z單字,例如c鰋perate或者résumé,拼寫中沒有讀音符號也會(huì)被完全接受。
但在美國以南、以北,以及大西洋地區(qū)的許多國家,在語言中使用讀音符號很普遍。這些重音符號最初是為使拉丁字母表適合這些語言讀音不同的需要。在遠(yuǎn)東或西歐的南部旅游,您會(huì)遇到根本不使用拉丁字母的語言,例如希臘語、希伯來語、阿拉伯語和俄語(使用斯拉夫字母表)。如果您向東走得更遠(yuǎn),就會(huì)發(fā)現(xiàn)中國象形漢字,日本和朝鮮也采用漢字系統(tǒng)。
ASCII的歷史開始于1967年,此后它主要致力于克服其自身限制以更適合于非美國英語的其它語言。例如,1967年,國際標(biāo)準(zhǔn)化組織(ISO:International Standards Organization)推薦一個(gè)ASCII的變種,代碼0x40、0x5B、0x5C、0x5D、0x7B、0x7C和0x7D「為國家使用保留」,而代碼0x5E、0x60和0x7E標(biāo)為「當(dāng)國內(nèi)要求的特殊字符需要8、9或10個(gè)空間位置時(shí),可用于其它圖形符號」。這顯然不是一個(gè)最佳的國際解決方案,因?yàn)檫@并不能保證一致性。但這卻顯示了人們?nèi)绾蜗氡M辦法為不同的語言來編碼的。
擴(kuò)展ASCII
在小型計(jì)算機(jī)開發(fā)的初期,就已經(jīng)嚴(yán)格地建立了8位字節(jié)。因此,如果使用一個(gè)字節(jié)來保存字符,則需要128個(gè)附加的字符來補(bǔ)充ASCII。1981年,當(dāng)最初的IBM PC推出時(shí),視訊卡的ROM中燒有一個(gè)提供256個(gè)字符的字符集,這也成為IBM標(biāo)準(zhǔn)的一個(gè)重要組成部分。
最初的IBM擴(kuò)展字符集包括某些帶重音的字符和一個(gè)小寫希臘字母表(在數(shù)學(xué)符號中非常有用),還包括一些塊型和線狀圖形字符。附加的字符也被添加到ASCII控制字符的編碼位置,這是因?yàn)榇蠖鄶?shù)控制字符都不是拿來顯示用的。
該IBM擴(kuò)展字符集被燒進(jìn)無數(shù)顯示卡和打印機(jī)的ROM中,并被許多應(yīng)用程序用于修飾其文字模式的顯示方式。不過,該字符集并沒有為所有使用拉丁字母表的西歐語言提供足夠多的帶重音字符,而且也不適用于Windows。Windows不需要圖形字符,因?yàn)樗幸粋€(gè)完全圖形化的系統(tǒng)。
在Windows 1.0(1985年11月發(fā)行)中,Microsoft沒有完全放棄IBM擴(kuò)展字符集,但它已退居第二重要位置。因?yàn)樽裱薃NSI草案和ISO標(biāo)準(zhǔn),純Windows字符集被稱作「ANSI字符集」。ANSI草案和ISO標(biāo)準(zhǔn)最終成為ANSI/ISO 8859-1-1987,即「American National Standard for Information Processing-8-Bit Single-Byte Coded Graphic Character Sets-Part 1: Latin Alphabet No 1」,通常也簡寫為「Latin 1」。
在Windows 1.0的《Programmer's Reference》中印出了ANSI字符集的最初版本,如圖2-2所示。
圖2-2 Windows ANSI字符集(基于ANSI/ISO 8859-1)
空方框表示該位置未定義字符。這與ANSI/ISO 8859-1的最終定義一致。ANSI/ISO 8859-1僅顯示了圖形字符,而沒有控制字符,因此沒有定義DEL。此外,代碼0xA0定義為一個(gè)非斷開的空格(這意味著在編排格式時(shí),該字符不用于斷開一行),代碼0xAD是一個(gè)軟連字符(表示除非在行尾斷開單詞時(shí)使用,否則不顯示)。此外,ANSI/ISO 8859-1將代碼0xD7定義為乘號(*),0xF7為除號(/)。Windows中的某些字體也定義了從0x80到0x9F的某些字符,但這些不是ANSI/ISO 8859-1標(biāo)準(zhǔn)的一部分。
MS-DOS 3.3(1987年4月發(fā)行)向IBM PC用戶引進(jìn)了代碼頁(code page)的概念,Windows也使用此概念。代碼頁定義了字符的映像代碼。最初的IBM字符集被稱作代碼頁437,或者「MS-DOS Latin US)。代碼頁850就是「MS-DOS Latin 1」,它用附加的帶重音字母(但不是圖2-2所示的Latin 1 ISO/ANSI標(biāo)準(zhǔn))代替了一些線形字符。其它代碼頁被其它語言定義。最低的128個(gè)代碼總是相同的;較高的128個(gè)代碼取決于定義代碼頁的語言。
在MS-DOS中,如果用戶為PC的鍵盤、顯示卡和打印機(jī)指定了一個(gè)代碼頁,然后在PC上創(chuàng)建、編輯和打印文件,一切都很正常,每件事都會(huì)保持一致。然而,如果用戶試圖與使用不同代碼頁的用戶交換文件,或者在機(jī)器上改變代碼頁,就會(huì)產(chǎn)生問題。字符碼與錯(cuò)誤的字符相關(guān)聯(lián)。應(yīng)用程序能夠?qū)⒋a頁信息與文件一起保存來試圖減少問題的產(chǎn)生,但該策略包括了某些在代碼頁間轉(zhuǎn)換的工作。
雖然代碼頁最初僅提供了不包括帶重音符號字母的附加拉丁字符集,但最終代碼頁的較高的128個(gè)字符還是包括了完整的非拉丁字母,例如希伯來語、希臘語和斯拉夫語。自然,如此多樣會(huì)導(dǎo)致代碼頁變得混亂;如果少數(shù)帶重音的字母未正確顯示,那么整個(gè)文字便會(huì)混亂不堪而不可閱讀。
代碼頁的擴(kuò)展正是基于所有這些原因,但是還不夠。斯拉夫語的MS-DOS代碼頁855與斯拉夫語的Windows代碼頁1251以及斯拉夫語的Macintosh代碼頁10007不同。每個(gè)環(huán)境下的代碼頁都是對該環(huán)境所作的標(biāo)準(zhǔn)字符集修正。IBM OS/2也支援多種EBCDIC代碼頁。
但等一下,你會(huì)發(fā)現(xiàn)事情變得更糟糕。
雙字節(jié)字符集
迄今為止,我們已經(jīng)看到了256個(gè)字符的字符集。但中國、日本和韓國的象形文字符號有大約21,000個(gè)。如何容納這些語言而仍保持和ASCII的某種兼容性呢?
解決方案(如果這個(gè)說法正確的話)是雙字節(jié)字符集(DBCS:double-byte character set)。DBCS從256代碼開始,就像ASCII一樣。與任何行為良好的代碼頁一樣,最初的128個(gè)代碼是ASCII。然而,較高的128個(gè)代碼中的某些總是跟隨著第二個(gè)字節(jié)。這兩個(gè)字節(jié)一起(稱作首字節(jié)和跟隨字節(jié))定義一個(gè)字符,通常是一個(gè)復(fù)雜的象形文字。
雖然中文、日文和韓文共享一些相同的象形文字,但顯然這三種語言是不同的,而且經(jīng)常是同一個(gè)象形文字在三種不同的語言中代表三件不同的事。Windows支持四個(gè)不同的雙字節(jié)字符集:代碼頁932(日文)、936(簡體中文)、949(韓語)和950(繁體漢字)。只有為這些國家(地區(qū))生產(chǎn)的Windows版本才支持DBCS。
雙字符集問題并不是說字符由兩個(gè)字節(jié)代表。問題在于一些字符(特別是ASCII字符)由1個(gè)字節(jié)表示。這會(huì)引起附加的程序設(shè)計(jì)問題。例如,字符串中的字符數(shù)不能由字符串的字節(jié)數(shù)決定。必須剖析字符串來決定其長度,而且必須檢查每個(gè)字節(jié)以確定它是否為雙字節(jié)字符的首字節(jié)。如果有一個(gè)指向DBCS字符串中間的指針,那么該字符串前一個(gè)字符的地址是什么呢?慣用的解決方案是從開始的指針分析該字符串!
Unicode解決方案
我們面臨的基本問題是世界上的書寫語言不能簡單地用256個(gè)8位代碼表示。以前的解決方案包括代碼頁和DBCS已被證明是不能滿足需要的,而且也是笨拙的。那什么才是真正的解決方案呢?
身為程序?qū)懽髡?#xff0c;我們經(jīng)歷過這類問題。如果事情太多,用8位數(shù)值已經(jīng)不能表示,那么我們就試更寬的值,例如16位值。而且這很有趣的,正是Unicode被制定的原因。與混亂的256個(gè)字符代碼映像,以及含有一些1字節(jié)代碼和一些2字節(jié)代碼的雙字節(jié)字符集不同,Unicode是統(tǒng)一的16位系統(tǒng),這樣就允許表示65,536個(gè)字符。這對表示所有字符及世界上使用象形文字的語言,包括一系列的數(shù)學(xué)、符號和貨幣單位符號的集合來說是充裕的。
明白Unicode和DBCS之間的區(qū)別很重要。Unicode使用(特別在C程序設(shè)計(jì)語言環(huán)境里)「寬字符集」。「Unicode中的每個(gè)字符都是16位寬而不是8位寬。」在Unicode中,沒有單單使用8位數(shù)值的意義存在。相比之下,在雙字節(jié)字符集中我們?nèi)匀惶幚?位數(shù)值。有些字節(jié)自身定義字符,而某些字節(jié)則顯示需要和另一個(gè)字節(jié)共同定義一個(gè)字符。
處理DBCS字符串非常雜亂,但是處理Unicode文字則像處理有秩序的文字。您也許會(huì)高興地知道前128個(gè)Unicode字符(16位代碼從0x0000到0x007F)就是ASCII字符,而接下來的128個(gè)Unicode字符(代碼從0x0080到0x00FF)是ISO 8859-1對ASCII的擴(kuò)展。Unicode中不同部分的字符都同樣基于現(xiàn)有的標(biāo)準(zhǔn)。這是為了便于轉(zhuǎn)換。希臘字母表使用從0x0370到0x03FF的代碼,斯拉夫語使用從0x0400到0x04FF的代碼,美國使用從0x0530到0x058F的代碼,希伯來語使用從0x0590到0x05FF的代碼。中國、日本和韓國的象形文字(總稱為CJK)占用了從0x3000到0x9FFF的代碼。
Unicode的最大好處是這里只有一個(gè)字符集,沒有一點(diǎn)含糊。Unicode實(shí)際上是個(gè)人計(jì)算機(jī)行業(yè)中幾乎每個(gè)重要公司共同合作的結(jié)果,并且它與ISO 10646-1標(biāo)準(zhǔn)中的代碼是一一對應(yīng)的。Unicode的重要參考文獻(xiàn)是《The Unicode Standard,Version 2.0》(Addison-Wesley出版社,1996年)。這是一本特別的書,它以其它文件少有的方式顯示了世界上書寫語言的豐富性和多樣性。此外,該書還提供了開發(fā)Unicode的基本原理和細(xì)節(jié)。
Unicode有缺點(diǎn)嗎?當(dāng)然有。Unicode字符串占用的內(nèi)存是ASCII字符串的兩倍。(然而壓縮文件有助于極大地減少文件所占的磁盤空間。)但也許最糟的缺點(diǎn)是:人們相對來說還不習(xí)慣使用Unicode。身為程序?qū)懽髡?#xff0c;這就是我們的工作。
寬字符和 C
對C程序?qū)懽髡邅碚f,16位字符的想法的確讓人掃興。一個(gè)char和一個(gè)字節(jié)同寬是最不能確定的事情之一。沒幾個(gè)程序?qū)懽髡咔宄嗀NSI/ISO 9899-1990,這是「美國國家標(biāo)準(zhǔn)程序設(shè)計(jì)語言-C」(也稱作「ANSI C」)通過一個(gè)稱作「寬字符」的概念來支持用多個(gè)字節(jié)代表一字符的字符集。這些寬字符與常用的字符完美地共存。
ANSI C也支持多字節(jié)字符集,例如中文、日文和韓文版本W(wǎng)indows支持的字符集。然而,這些多字節(jié)字符集被當(dāng)成單字節(jié)構(gòu)成的字符串看待,只不過其中一些字符改變了后續(xù)字符的含義而已。多字節(jié)字符集主要影響C語言程序執(zhí)行時(shí)期鏈接庫函數(shù)。相比之下,寬字符比正常字符寬,而且會(huì)引起一些編譯問題。
寬字符不需要是Unicode。Unicode是一種可能的寬字符集。然而,因?yàn)楸緯慕裹c(diǎn)是Windows而不是C執(zhí)行的理論,所以我將把寬字符和Unicode作為同義語。
Char數(shù)據(jù)型態(tài)
假定我們都非常熟悉在C程序中使用char數(shù)據(jù)型態(tài)來定義和儲存字符跟字符串。但為了便于理解C如何處理寬字符,讓我們先回顧一下可能在Win32程序中出現(xiàn)的標(biāo)準(zhǔn)字符定義。
下面的語句定義并初始化了一個(gè)只包含一個(gè)字符的變量:
char c = 'A' ;
???????
變量c需要1個(gè)字節(jié)來保存,并將用十六進(jìn)制數(shù)0x41初始化,這是字母A的ASCII代碼。
您可以像這樣定義一個(gè)指向字符串的指針:
char * p ;
???????
因?yàn)閃indows是一個(gè)32位操作系統(tǒng),所以指針變量p需要用4個(gè)字節(jié)保存。您還可初始化一個(gè)指向字符串的指針:
char * p = "Hello!" ;
???????
像前面一樣,變量p也需要用4個(gè)字節(jié)保存。該字符串保存在靜態(tài)內(nèi)存中并占用7個(gè)字節(jié)-6個(gè)字節(jié)保存字符串,另1個(gè)字節(jié)保存終止符號0。
您還可以像這樣定義字符數(shù)組:
char a[10] ;
???????
在這種情況下,編譯器為該數(shù)組保留了10個(gè)字節(jié)的儲存空間。表達(dá)式sizeof(a)將返回10。如果數(shù)組是整體變量(即在所有函數(shù)外定義),您可使用像下面的語句來初始化一個(gè)字符數(shù)組:
char a[] = "Hello!" ;
???????
如果您將該數(shù)組定義為一個(gè)函數(shù)的區(qū)域變量,則必須將它定義為一個(gè)static變量,如下:
static char a[] = "Hello!" ;
???????
無論哪種情況,字符串都儲存在靜態(tài)程序內(nèi)存中,并在末尾添加0,這樣就需要7個(gè)字節(jié)的儲存空間。
寬字符
Unicode或者寬字符都沒有改變char數(shù)據(jù)型態(tài)在C中的含義。char繼續(xù)表示1個(gè)字節(jié)的儲存空間,sizeof (char)繼續(xù)返回1。理論上,C中1個(gè)字節(jié)可比8位長,但對我們大多數(shù)人來說,1個(gè)字節(jié)(也就是1個(gè)char)是8位寬。
C中的寬字符基于wchar_t數(shù)據(jù)型態(tài),它在幾個(gè)表頭文件包括WCHAR.H中都有定義,像這樣:
typedef unsigned short wchar_t ;
???????
因此,wchar_t數(shù)據(jù)型態(tài)與無符號短整數(shù)型態(tài)相同,都是16位寬。
要定義包含一個(gè)寬字符的變量,可使用下面的語句:
wchar_t c = 'A' ;
???????
變量c是一個(gè)雙字節(jié)值0x0041,是Unicode表示的字母A。(然而,因?yàn)镮ntel微處理器從最小的字節(jié)開始儲存多字節(jié)數(shù)值,該字節(jié)實(shí)際上是以0x41、0x00的順序保存在內(nèi)存中。如果檢查Unicode文字的計(jì)算機(jī)儲存應(yīng)注意這一點(diǎn)。)
您還可定義指向?qū)捵址闹羔?#xff1a;
wchar_t * p = L"Hello!" ;
???????
注意緊接在第一個(gè)引號前面的大寫字母L(代表「long」)。這將告訴編譯器該字符串按寬字符保存-即每個(gè)字符占用2個(gè)字節(jié)。通常,指針變量p要占用4個(gè)字節(jié),而字符串變量需要14個(gè)字節(jié)-每個(gè)字符需要2個(gè)字節(jié),末尾的0還需要2個(gè)字節(jié)。
同樣,您還可以用下面的語句定義寬字符數(shù)組:
static wchar_t a[] = L"Hello!" ;
???????
該字符串也需要14個(gè)字節(jié)的儲存空間,sizeof (a) 將返回14。索引數(shù)組a可得到單獨(dú)的字符。a[1] 的值是寬字符「e」,或者0x0065。
雖然看上去更像一個(gè)印刷符號,但第一個(gè)引號前面的L非常重要,并且在兩個(gè)符號之間必須沒有空格。只有帶有L,編譯器才知道您需要將字符串存為每個(gè)字符2字節(jié)。稍后,當(dāng)我們看到使用寬字符串而不是變量定義時(shí),您還會(huì)遇到第一個(gè)引號前面的L。幸運(yùn)的是,如果忘記了包含L,C編譯器通常會(huì)給提出警告或錯(cuò)誤信息。
您還可在單個(gè)字符文字前面使用L前綴,來表示它們應(yīng)解釋為寬字符。如下所示:
wchar_t c = L'A' ;
???????
但通常這是不必要的,C編譯器會(huì)對該字符進(jìn)行擴(kuò)充,使它成為寬字符。
?
String str = "hello everybody!";
簡單來說,write(byte[] b, int off, int len)就是將數(shù)組 b 中的 len 個(gè)字節(jié)按順序?qū)懭胼敵隽鳌K匀绻?b 為 null,則拋出 NullPointerException。如果 off 為負(fù),或 len 為負(fù),又或者 off+len 大于數(shù)組 b 的長度,則拋出 IndexOutOfBoundsException。如果 len 為零,則不寫入字節(jié)。否則,首先寫入字節(jié) b[off],然后寫入字節(jié) b[off+1],依此類推;最后一個(gè)寫入字節(jié)是 b[off+len-1]。
?
//?UTF-8?編碼字符理論上可以最多到?6個(gè)字節(jié)長,但目前全世界的所
?(2011-10-20 20:54:03)
轉(zhuǎn)載▼
最初的unicode編碼是固定長度的,16位,也就是2兩個(gè)字節(jié)代表一個(gè)字符,這樣一共可以表示65536個(gè)字符。顯然,這樣要表示各種語言中所有的字符是遠(yuǎn)遠(yuǎn)不夠的。Unicode4.0規(guī)范考慮到了這種情況,定義了一組附加字符編碼,附加字符編碼采用2個(gè)16位來表示,這樣最多可以定義1048576個(gè)附加字符,目前unicode4.0只定義了45960個(gè)附加字符。
Unicode只是一個(gè)編碼規(guī)范,目前實(shí)際實(shí)現(xiàn)的unicode編碼只要有三種:UTF-8,UCS-2和UTF-16,三種unicode字符集之間可以按照規(guī)范進(jìn)行轉(zhuǎn)換。
UTF-8
UTF-8是一種8位的unicode字符集,編碼長度是可變的,并且是ASCII字符集的嚴(yán)格超集,也就是說ASCII中每個(gè)字符的編碼在UTF-8中是完全一樣的。UTF-8字符集中,一個(gè)字符可能是1個(gè)字節(jié),2個(gè)字節(jié),3個(gè)字節(jié)或者4個(gè)字節(jié)長。一般來說,歐洲的字母字符長度為1到2個(gè)字節(jié),而亞洲的大部分字符則是3個(gè)字節(jié),附加字符為4個(gè)字節(jié)長。
Unix平臺中普遍支持UTF-8字符集,HTML和大多數(shù)瀏覽器也支持UTF-8,而window和java則支持UCS-2。
UTF-8的主要優(yōu)點(diǎn):
·?對于歐洲字母字符需要較少的存儲空間。
·?容易從ASCII字符集向UTF-8遷移。
UCS-2
UCS-2是固定長度為16位的unicode字符集。每個(gè)字符都是2個(gè)字節(jié),UCS-2只支持unicode3.0,所以不支持附加字符。
UCS-2的優(yōu)點(diǎn):
·?對于亞洲字符的存儲空間需求比UTF-8少,因?yàn)槊總€(gè)字符都是2個(gè)字節(jié)。
·?處理字符的速度比UTF-8更快,因?yàn)槭枪潭ㄩL度編碼的。
·?對于windows和java的支持更好。
UTF-16
UTF-16也是一種16位編碼的字符集。實(shí)際上,UTF-16就是UCS-2加上附加字符的支持,也就是符合unicode4.0規(guī)范的UCS-2。所以UTF-16是UCS-2的嚴(yán)格超集。
UTF-16中的字符,要么是2個(gè)字節(jié),要么是4個(gè)字節(jié)表示的。UTF-16主要在windows2000以上版本使用。
UTF-16相對UTF-8的優(yōu)點(diǎn),和UCS-2是一致的。
Oracle從7.0開始提供對Unicode的支持。Oracle個(gè)版本的unicode字符集支主要有:
AL32UTF8
一種UTF-8編碼的字符集,支持最新的unicode4.0標(biāo)準(zhǔn)。字符長度為1,2或者3個(gè)字節(jié),附加字符則為4字節(jié)長。
UTF8
支持unicode3.0的UTF-8編碼方式。由于附加字符是在unicode3.1中提出的,UTF8不支持附加字符。但是unicode3.0已經(jīng)為附加字符預(yù)留了編碼空間,所以即使在UTF8的數(shù)據(jù)庫中插入附加字符,也是可以的,只是數(shù)據(jù)庫會(huì)將該字符分隔成兩部分,需要占6個(gè)字符的長度。所以,如果需要支持附加字符,那么建議將數(shù)據(jù)庫的字符集切換為新的AL32UTF8。
UTF8可用于數(shù)據(jù)庫字符集,也可用于國家字符集。
UTFE
UTFE是基于EBCDIC平臺的unicode字符集,就像ASCII平臺上的UTF8一樣。不同的是,UTFE中,每個(gè)字符可能占1,2,3或者4個(gè)字節(jié),而附加字符則需要2個(gè)4個(gè)字節(jié),也就是8個(gè)字節(jié)來表示。
AL16UTF16
AL16UTF16是一種UTF-16編碼的unicode字符集,在Oracle中用于國家字符集。
AL24UTFFSS
該字符集只支持unicode1.1規(guī)范,在Oracle7.2~8i版本中使用,目前已經(jīng)淘汰。
?
CString在Unicode下一個(gè)字節(jié)占16bit,在ascii下占8bit,改成char數(shù)組后在什么環(huán)境下都一樣的
?
編寫程序最好是:同一個(gè)源文件既可以在UNICODE下編譯,又可以在ANSI下編譯
?
總結(jié)
以上是生活随笔為你收集整理的关于字符编码,中文所占字节的整理。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx+PHP(FastCGI)搭建
- 下一篇: 联想百店同庆活动 IdeaPad V45