欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何理解JAVA.IO、字符編碼

這篇文章主要介紹“如何理解JAVA.IO、字符編碼”,在日常操作中,相信很多人在如何理解JAVA.IO、字符編碼問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何理解JAVA.IO、字符編碼”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

網(wǎng)站設(shè)計(jì)制作過(guò)程拒絕使用模板建站;使用PHP+MYSQL原生開(kāi)發(fā)可交付網(wǎng)站源代碼;符合網(wǎng)站優(yōu)化排名的后臺(tái)管理系統(tǒng);成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)收費(fèi)合理;免費(fèi)進(jìn)行網(wǎng)站備案等企業(yè)網(wǎng)站建設(shè)一條龍服務(wù).我們是一家持續(xù)穩(wěn)定運(yùn)營(yíng)了十多年的創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司。

1 JAVA.IO字節(jié)流

如何理解JAVA.IO、字符編碼

inputstream.png

  • LineNumberInputStream和StringBufferInputStream官方建議不再使用,推薦使用LineNumberReader和StringReader代替

  • ByteArrayInputStream和ByteArrayOutputStream  字節(jié)數(shù)組處理流,在內(nèi)存中建立一個(gè)緩沖區(qū)作為流使用,從緩存區(qū)讀取數(shù)據(jù)比從存儲(chǔ)介質(zhì)(如磁盤(pán))的速率快

  1. //用ByteArrayOutputStream暫時(shí)緩存來(lái)自其他渠道的數(shù)據(jù) 

  2. ByteArrayOutputStream data = new ByteArrayOutputStream(1024); //1024字節(jié)大小的緩存區(qū) 

  3. data.write(System.in.read()); // 暫存用戶輸入數(shù)據(jù) 

  4.  

  5. //將data轉(zhuǎn)為ByteArrayInputStream 

  6. ByteArrayInputStream in = new ByteArrayInputStream(data.toByteArray()); 


  • FileInputStream和FileOutputStream 訪問(wèn)文件,把文件作為InputStream,實(shí)現(xiàn)對(duì)文件的讀寫(xiě)操作

  • ObjectInputStream和ObjectOutputStream  對(duì)象流,構(gòu)造函數(shù)需要傳入一個(gè)流,實(shí)現(xiàn)對(duì)JAVA對(duì)象的讀寫(xiě)功能;可用于序列化,而對(duì)象需要實(shí)現(xiàn)Serializable接口

//java對(duì)象的寫(xiě)入 FileOutputStream fileStream = new FileOutputStream("example.txt"); ObjectOutputStream out = new ObjectOutputStream(fileStream); Example example = new Example(); out.writeObject(example);  //java對(duì)象的讀取 FileInputStream fileStream = new FileInputStream("example.txt"); ObjectInputStream in = new ObjectInputStream(fileStream); Example = (Example) in.readObject();
  • PipedInputStream和PipedOutputStream  管道流,適用在兩個(gè)線程中傳輸數(shù)據(jù),一個(gè)線程通過(guò)管道輸出流發(fā)送數(shù)據(jù),另一個(gè)線程通過(guò)管道輸入流讀取數(shù)據(jù),實(shí)現(xiàn)兩個(gè)線程間的數(shù)據(jù)通信

// 創(chuàng)建一個(gè)發(fā)送者對(duì)象 Sender sender = new Sender(); // 創(chuàng)建一個(gè)接收者對(duì)象 Receiver receiver = new Receiver(); // 獲取輸出管道流 // 獲取輸入輸出管道流 PipedOutputStream outputStream = sender.getOutputStream();  PipedInputStream inputStream = receiver.getInputStream(); // 鏈接兩個(gè)管道,這一步很重要,把輸入流和輸出流聯(lián)通起來(lái)   outputStream.connect(inputStream); sender.start();// 啟動(dòng)發(fā)送者線程 receiver.start();// 啟動(dòng)接收者線程
  • SequenceInputStream 把多個(gè)InputStream合并為一個(gè)InputStream,允許應(yīng)用程序把幾個(gè)輸入流連續(xù)地合并起來(lái)

InputStream in1 = new FileInputStream("example1.txt"); InputStream in2 = new FileInputStream("example2.txt"); SequenceInputStream sequenceInputStream = new SequenceInputStream(in1, in2); //數(shù)據(jù)讀取 int data = sequenceInputStream.read();
  • FilterInputStream和FilterOutputStream 使用了裝飾者模式來(lái)增加流的額外功能,子類構(gòu)造參數(shù)需要一個(gè)InputStream/OutputStream

ByteArrayOutputStream out = new ByteArrayOutputStream(2014); //數(shù)據(jù)寫(xiě)入,使用DataOutputStream裝飾一個(gè)InputStream //使用InputStream具有對(duì)基本數(shù)據(jù)的處理能力 DataOutputStream dataOut = new DataOutputStream(out); dataOut.writeDouble(1.0); //數(shù)據(jù)讀取 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); DataInputStream dataIn = new DataInputStream(in); Double data = dataIn.readDouble();
  • DataInputStream和DataOutputStream (Filter流的子類)  為其他流附加處理各種基本類型數(shù)據(jù)的能力,如byte、int、String

  • BufferedInputStream和BufferedOutputStream (Filter流的子類) 為其他流增加緩沖功能

  • PushBackInputStream (FilterInputStream子類)  推回輸入流,可以把讀取進(jìn)來(lái)的某些數(shù)據(jù)重新回退到輸入流的緩沖區(qū)之中

  • PrintStream (FilterOutputStream子類) 打印流,功能類似System.out.print

2 JAVA.IO字符流

如何理解JAVA.IO、字符編碼

21.png

  • 從字節(jié)流和字符流的導(dǎo)向圖來(lái),它們之間是相互對(duì)應(yīng)的,比如CharArrayReader和ByteArrayInputStream

  • 字節(jié)流和字符流的轉(zhuǎn)化:InputStreamReader可以將InputStream轉(zhuǎn)為Reader,OutputStreamReader可以將OutputStream轉(zhuǎn)為Writer

//InputStream轉(zhuǎn)為Reader InputStream inputStream = new ByteArrayInputStream("程序".getBytes()); InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); //OutputStream轉(zhuǎn)為Writer OutputStream out = new FileOutputStream("example.txt"); OutputStreamWriter writer = new OutputStreamWriter(out); //以字符為單位讀寫(xiě) writer.write(reader.read(new char[2]));
  • 區(qū)別:字節(jié)流讀取單位是字節(jié),字符流讀取單位是字符;一個(gè)字符由字節(jié)組成,如變字長(zhǎng)編碼UTF-8是由1~4個(gè)字節(jié)表示

3 亂碼問(wèn)題和字符流

  • 字符以不同的編碼表示,它的字節(jié)長(zhǎng)度(字長(zhǎng))是不一樣的。如“程”的utf-8編碼格式,由[-25][-88][-117]組成。而ISO_8859_1編碼則是單個(gè)字節(jié)[63]

  • 平時(shí)工作對(duì)資源的操作都是面向字節(jié)流的,然而數(shù)據(jù)資源根據(jù)不同的字節(jié)編碼轉(zhuǎn)為字節(jié)時(shí),它們的內(nèi)容是不一樣,容易造成亂碼問(wèn)題

  • 兩種出現(xiàn)亂碼場(chǎng)景  encode和decode使用的字符編碼不一致:資源使用UTF-8編碼,而在代碼里卻使用GBK解碼打開(kāi)使用字節(jié)流讀取字節(jié)數(shù)不符合字符規(guī)定字長(zhǎng):字符是由字節(jié)組成的,比如“程”的utf-8格式是三個(gè)字節(jié);如果在InputStream里以每?jī)蓚€(gè)字節(jié)讀取流,再轉(zhuǎn)為String(java默認(rèn)編碼是utf-8),此時(shí)會(huì)出現(xiàn)亂碼(半個(gè)中文,你猜是什么)

  1. ByteArrayInputStream in = new ByteArrayInputStream("程序大法好".getBytes()); 

  2. byte[] buf = new byte[2]; //讀取流的兩個(gè)字節(jié) 

  3. in.read(buf); //讀取數(shù)據(jù) 

  4. System.out.println(new String(buf)); //亂碼 

  5. ---result----  

  6. ?  //亂碼 


  • 亂碼場(chǎng)景1,知道資源的字符編碼,就可以使用對(duì)應(yīng)的字符編碼來(lái)解碼解決

  • 亂碼場(chǎng)景2,可以一次性讀取所有字節(jié),再一次性編碼處理。但是對(duì)于大文件流,這是不現(xiàn)實(shí)的,因此有了字符流的出現(xiàn)

  • 字節(jié)流使用InputStreamReader、OutputStreamReader轉(zhuǎn)化為字符流,其中可以指定字符編碼,再以字符為單位來(lái)處理,可解決亂碼

InputStreamReader reader =        new InputStreamReader(inputStream, StandardCharsets.UTF_8);

4 字符集和字符編碼的概念區(qū)分

  • 字符集和字符編碼的關(guān)系,字符集是規(guī)范,字符編碼是規(guī)范的具體實(shí)現(xiàn);字符集規(guī)定了符號(hào)和二進(jìn)制代碼值的唯一對(duì)應(yīng)關(guān)系,但是沒(méi)有指定具體的存儲(chǔ)方式;

  • unicode、ASCII、GB2312、GBK都是字符集;其中ASCII、GB2312、GBK既是字符集也是字符編碼;注意不混淆這兩者區(qū)別;而unicode的具體實(shí)現(xiàn)有UTF-8,UTF-16,UTF-32

  • 最早出現(xiàn)的ASCII碼是使用一個(gè)字節(jié)(8bit)來(lái)規(guī)定字符和二進(jìn)制映射關(guān)系,標(biāo)準(zhǔn)ASCII編碼規(guī)定了128個(gè)字符,在英文的世界,是夠用的。但是中文,日文等其他文字符號(hào)怎么映射呢?因此其他更大的字符集出現(xiàn)了

  • unicode(統(tǒng)一字符集),早期時(shí)它使用2個(gè)byte表示1個(gè)字符,整個(gè)字符集可以容納65536個(gè)字符。然而仍然不夠用,于是擴(kuò)展到4個(gè)byte表示一個(gè)字符,現(xiàn)支持范圍是U+010000~U+10FFFF

  • unicode是兩個(gè)字節(jié)的說(shuō)法是錯(cuò)誤的;UTF-8是變字長(zhǎng)的,需要用1~4個(gè)字節(jié)存儲(chǔ);UTF-16一般是兩個(gè)字節(jié)(U+0000~U+FFFF范圍),如果遇到兩個(gè)字節(jié)存不下,則用4個(gè)字節(jié);而UTF-32是固定四個(gè)字節(jié)

  • unicode表示的字符,會(huì)用“U+”開(kāi)頭,后面跟著十六進(jìn)制的數(shù)字,如“字”的編碼就是U+5B57

  • UTF-8 編碼和unicode字符集

范圍 Unicode(Binary) UTF-8編碼(Binary) UTF-8編碼byte長(zhǎng)度 U+0000~U+007F 00000000  00000000 00000000 0XXXXXXX 0XXXXXX 1 U+0080~U+07FF 00000000 00000000 00000YYY  YYXXXXXX 110YYYYY 10XXXXXX 2 U+0800~U+FFFF 00000000 00000000 ZZZZYYYY YYXXXXXX  1110ZZZZ 10YYYYYY 10XXXXXX 3 U+010000~U+10FFFF 00000000 000AAAZZ ZZZZYYYY  YYXXXXXX 11110AAA 10ZZZZZZ 10YYYYYY 10XXXXXX 4

  • 程序是分內(nèi)碼和外碼,java的默認(rèn)編碼是UTF-8,其實(shí)指的是外碼;內(nèi)碼傾向于使用定長(zhǎng)碼,和內(nèi)存對(duì)齊一個(gè)原理,便于處理。外碼傾向于使用變長(zhǎng)碼,變長(zhǎng)碼將常用字符編為短編碼,罕見(jiàn)字符編為長(zhǎng)編碼,節(jié)省存儲(chǔ)空間與傳輸帶寬

  • JDK8的字符串,是使用char[]來(lái)存儲(chǔ)字符的,char是兩個(gè)字節(jié)大小,其中使用的是UTF-16編碼(內(nèi)碼)。而unicode規(guī)定的中文字符在U+0000~U+FFFF內(nèi),因此使用char(UTF-16編碼)存儲(chǔ)中文是不會(huì)出現(xiàn)亂碼的

  • JDK9后,字符串則使用byte[]數(shù)組來(lái)存儲(chǔ),因?yàn)橛幸恍┳址粋€(gè)char已經(jīng)存不了,如emoji表情字符,使用字節(jié)存儲(chǔ)字符串更容易拓展

  • JDK9,如果字符串的內(nèi)容都是ISO-8859-1/Latin-1字符(1個(gè)字符1字節(jié)),則使用ISO-8859-1/Latin-1編碼存儲(chǔ)字符串,否則使用UTF-16編碼存儲(chǔ)數(shù)組(2或4個(gè)字節(jié))

System.out.println(Charset.defaultCharset()); //輸出java默認(rèn)編碼 for (byte item : "程序".getBytes(StandardCharsets.UTF_16)) {     System.out.print("[" + item + "]"); } System.out.println(""); for (byte item : "程序".getBytes(StandardCharsets.UTF_8)) {     System.out.print("[" + item + "]"); } ----result---- UTF-8       //java默認(rèn)編碼UTF-8 [-2][-1][122][11][94][-113] //UTF_16:6個(gè)字節(jié)? [-25][-88][-117][-27][-70][-113] //UTF_8:6個(gè)字節(jié) 正常
  • “程序”的UTF-16編碼竟是輸出6個(gè)字節(jié),多出了兩個(gè)字節(jié),這是什么情況?再試試一個(gè)字符的輸

  1. for (byte item : "程".getBytes(StandardCharsets.UTF_16)) { 

  2.     System.out.print("[" + item + "]"); 

  3. ---result-- 

  4. [-2][-1][122][11] 


  • 可以看出UTF-16編碼的字節(jié)是多了[-2][-1]兩個(gè)字節(jié),十六進(jìn)制是0xFEFF。而它用來(lái)標(biāo)識(shí)編碼順序是Big endian還是Little  endian。以字符'中'為例,它的unicode十六進(jìn)制是4E2D,存儲(chǔ)時(shí)4E在前,2D在后,就是Big endian;2D在前,4E在后,就是Little  endian。FEFF表示存儲(chǔ)采用Big endian,F(xiàn)FFE表示使用Little endian

  • 為什么UTF-8沒(méi)有字節(jié)序的問(wèn)題呢?個(gè)人看法,因?yàn)閁TF-8是變長(zhǎng)的,由第一個(gè)字節(jié)的頭部的0、110、1110、11110判斷是否需后續(xù)幾個(gè)字節(jié)組成字符,使用Big  endian易讀取處理,反過(guò)來(lái)不好處理,因此強(qiáng)制用Big endian

  • 其實(shí)感覺(jué)UTF-16可以強(qiáng)制規(guī)定用Big endian;但這其中歷史問(wèn)題。。。

到此,關(guān)于“如何理解JAVA.IO、字符編碼”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

本文題目:如何理解JAVA.IO、字符編碼
當(dāng)前地址:http://chinadenli.net/article32/jhgppc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)云服務(wù)器軟件開(kāi)發(fā)網(wǎng)站改版虛擬主機(jī)App開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)