您好,登錄后才能下訂單哦!
這篇文章主要講解了java字節(jié)與字符有什么區(qū)別,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。
一、字節(jié)
所謂字節(jié)(Byte),是計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)的一種計(jì)量單位。一個(gè)二進(jìn)制位稱為比特(bit),8個(gè)比特組成一個(gè)字節(jié),也就是說一個(gè)字節(jié)可以用于區(qū)分256個(gè)整數(shù)(0~255)。由此我們可以知道,字節(jié)本是面向計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)及傳輸?shù)幕締挝唬罄m(xù)的字符也就是以字節(jié)為單位存儲(chǔ)的,不同編碼的字符占用的字節(jié)數(shù)不同。
那么在Java中,除了存儲(chǔ)的意義外,Java還將字節(jié)Byte作為一種基本數(shù)據(jù)類型,該數(shù)據(jù)類型在內(nèi)存中占用一個(gè)字節(jié),用于(-128~127)范圍內(nèi)的整數(shù)
byte a = -128; byte b = 127;
總的來說,字節(jié)在Java中有兩種含義:
存儲(chǔ)的單位Java的數(shù)據(jù)類型,用于表示-128~127范圍的整數(shù)
二、字符
計(jì)算機(jī)底層存儲(chǔ)的是字節(jié),字符的設(shè)計(jì)則是用于展示符號(hào)。屏幕上顯示的各種文字,數(shù)字,符號(hào)等就是解碼的字符。所以我們說字符是用來顯示的符號(hào),它將存儲(chǔ)的字節(jié)轉(zhuǎn)換成人們看得懂的符號(hào),因此字符的核心就是定義字節(jié)與展示符號(hào)之間的關(guān)系,這種映射關(guān)系通常也叫做編碼。
2.1、編碼的由來
為什么要編碼呢?前面我們知道數(shù)據(jù)都是以字節(jié)為單位存儲(chǔ)在計(jì)算機(jī)中,字節(jié)可以區(qū)分256個(gè)整數(shù),最容易想到的就是將這256個(gè)整數(shù)定義為256種狀態(tài)并分別對(duì)應(yīng)256個(gè)字符。但是人類符號(hào)太多了,256種是不夠的。所以人們想到將多個(gè)字節(jié)合并起來表示人類語言符號(hào),編碼的問題就轉(zhuǎn)化成了字節(jié)的組合問題。
2.2、編碼的常見格式
如今有很多編碼格式,常見的如ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16等等。
ASCII編碼是最基礎(chǔ)的編碼格式,標(biāo)準(zhǔn)的ASCII碼一共有128個(gè),占用字節(jié)的低7位,將英語系語種的符號(hào)都能覆蓋住,但是總的來說能表示的字符還是非常有限。
ISO-8859-1編碼是ASCII編碼的一種擴(kuò)展,它用了字節(jié)的8位,能表示256種字符,且向下兼容ASCII,包含了絕大多數(shù)的西歐符號(hào)。
GB2312是雙字節(jié)編碼,意味著它使用兩個(gè)字節(jié)來表示符號(hào),包含有6763個(gè)漢字。
GBK是GB2312的一個(gè)擴(kuò)展,也是雙字節(jié)編碼,能夠表示21003個(gè)漢字,且向下兼容GB2312。
...
編碼的規(guī)范越來越多,不同語言的國家都定義了自己的語言符號(hào)編碼標(biāo)準(zhǔn),一時(shí)間編碼標(biāo)準(zhǔn)百花齊放,在互聯(lián)網(wǎng)的時(shí)代里交流十分不便,不同編碼體系之間的信息交流都需要采用不同的解碼方案,不然就會(huì)出現(xiàn)亂碼的現(xiàn)象。于是國際標(biāo)準(zhǔn)化組織ISO制定了一個(gè)能夠容納世界上所有文字和符號(hào)的字符編碼方案Unicode。Unicode是一個(gè)字符集,它規(guī)定了人類所有字符對(duì)應(yīng)的二進(jìn)制數(shù),至于這個(gè)二進(jìn)制數(shù)怎么存儲(chǔ)則是由開發(fā)者來進(jìn)行實(shí)現(xiàn)。其中比較流行的實(shí)現(xiàn)是UTF-8和UTF-16,還有一種UTF-32。
UTF-32編碼使用4個(gè)字節(jié),也就是32位二進(jìn)制存儲(chǔ)Unicode字符,效率高但是空間浪費(fèi)。
UTF-8編碼是一種變長的編碼方式,它使用1~6個(gè)字節(jié)來存儲(chǔ),對(duì)于英語系的字符使用一個(gè)字節(jié),向下兼容ASCII,對(duì)于漢字則使用兩個(gè)字節(jié),依次類推,這樣就能夠節(jié)省一定的空間。
UTF-16編碼是介于兩者之間的一種編碼方式。對(duì)于部分字符采用2個(gè)字節(jié),另一部分字符采用4個(gè)字節(jié)。因此UTF-16無法兼容ASCII。
在平時(shí)的使用中,UTF-8的使用還是比較多,就是由于它既能向下兼容ASCII,還能夠在一定程度上節(jié)省空間。
2.3、Java IO流中的編碼和解碼
Java中是如何進(jìn)行編碼和解碼的呢?我們知道,編碼/解碼的過程主要是發(fā)生在字符與字節(jié)之間轉(zhuǎn)換的過程。在展示字符的時(shí)候,我們將內(nèi)存中的字節(jié)解碼成符號(hào),在存儲(chǔ)或者傳輸文件時(shí),我們將字符編碼位字節(jié)數(shù)據(jù)。解碼
解碼的過程是將字節(jié)轉(zhuǎn)換為字符,也就是我們?cè)谧x取文件或者網(wǎng)絡(luò)數(shù)據(jù)的過程。
在java中,我們通過FileReader讀取文件數(shù)據(jù),F(xiàn)ileReader繼承自InputStreamReader。在InputStreamReader中使用了解碼器StreamDecoder。
// InputStreamReader.java import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import sun.nio.cs.StreamDecoder; public class InputStreamReader extends Reader { // 解碼器,按照指定編碼方式將字節(jié)轉(zhuǎn)換成字符 private final StreamDecoder sd; // 通過dec指定解碼器使用的編碼方案 public InputStreamReader(InputStream in, CharsetDecoder dec){ super(in); if (dec == null) throw new NullPointerException("charset decoder"); sd = StreamDecoder.forInputStreamReader(in, this, dec); } // 讀字符,以int形式(4字節(jié))返回字符 public int read() throws IOException { return sd.read(); } }
通過上述InputStreamReader源碼我們可以知道:
讀取輸入流時(shí),通過StreamDecoder完成字節(jié)到字符的轉(zhuǎn)換可以通過構(gòu)造方法來設(shè)置編碼方案讀取的字符以int型數(shù)據(jù)返回,即4個(gè)字節(jié)
另外,上述列舉只是源碼的一部分,我們?cè)O(shè)置編碼方案有很多種形式,如在構(gòu)造方法種傳入編碼方式的String類型名稱、傳入CharSet類型的字符集以及上述的CharsetDecoder類型的字符解碼方式。如果不傳入編碼方案,則默認(rèn)為當(dāng)前環(huán)境的編碼方案。編碼
與解碼類似,在存儲(chǔ)文件或者寫入數(shù)據(jù)的時(shí)候,我們將字符轉(zhuǎn)換為字節(jié),寫入文件或者網(wǎng)絡(luò)。
在java種,我們通過FileWriter來寫入文件,F(xiàn)ileWriter繼承自O(shè)utputStreamWriter。在OutputStreamWriter種使用了編碼器StreamEncoder。
// OutputStreamWriter.java import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import sun.nio.cs.StreamEncoder; public class OutputStreamWriter extends Writer { // 編碼器,按照指定編碼方式將字符轉(zhuǎn)換成字節(jié) private final StreamEncoder se; // 通過enc指定編碼方案 public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { super(out); if (enc == null) throw new NullPointerException("charset encoder"); se = StreamEncoder.forOutputStreamWriter(out, this, enc); } // 寫字符,寫入的字符以int類型傳入 public void write(int c) throws IOException { se.write(c); }
通過源碼我們可以知道:
看完上述內(nèi)容,是不是對(duì)java字節(jié)與字符有什么區(qū)別有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。