




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第八章 文件和流,圖形圖像研究所 計算機科學與技術、軟件學院浙江工業大學,高飛,陸佳煒等。Java程序設計實用教程。北京:清華大學出版社,2013(ISBN:978-7-302-31695-4) 高飛,趙小敏等。Java程序設計實用教程習題集。北京:清華大學出版社,2013(ISBN:978-7-302-32051-7,高飛 教授,博士生導師 Tel.URL: http:/,前言,本章的目的:什么是流?什么是字節流和字符流?如何訪問磁盤上的文件屬性?如何將對象保存到磁盤文件中(對象序列化)?Java中亂碼問題是如何形成的,回顧關鍵詞:用戶的輸入是邪惡的!Try-c
2、atch-finally、throws、throw,小節安排,文件和流,8.2.1 輸入字節流:InputStream,8.3、字符流,8.4、文件,8.2.2 輸出字節流:OutputStream,8.3.1 輸入字符流:Reader,8.3.2 輸出字符流:Writer,8.3.3 BufferedReader和BufferedWriter,8.1、流的基本概念,8.2、字節流,8.5、對象序列化,8.6、Java中的亂碼問題,8.3.4 字節流和字符流的異同,8.1、流的基本概念,8.2、字節流,8.2、字節流,輸入字節流:InputStream,8.2、字節流,*從mytext.txt
3、文件讀出并顯示在屏幕上*/ import java.io.*; public class FileIn public static void main(String args) try FileInputStream rf=new FileInputStream(H:/java/temp/mytext.txt);/打開文件 int b; while(b=rf.read()!=-1)/用read()方法逐個字節讀取 System.out.print(char)b); /轉換成char并顯示 rf.close(); catch(IOException ie) System.out.println(
4、ie); catch(Exception e) System.out.println(e);,8.2、字節流,輸出字節流:OutputStream,8.2、字節流,*以下示例用于說明如何利用FileOutputStream進行文件復制*/ import java.io.*; public class TestFileCopy public static void main(String args) try /復制的源文件TestVector.java FileInputStream rf=new FileInputStream(G:/java/TestVector.java); /復制的目的文
5、件TV2.txt,若不存在,則會自動創建 FileOutputStream wf=new FileOutputStream(G:/java/TV2.txt); byte b=new byte512; int count=-1; /每次讀取512個字節,count用于記錄實際讀取的字節數 while(count=rf.read(b, 0, 512)!=-1) wf.write(b,0,count); rf.close(); wf.close(); catch(IOException ie) System.out.println(ie.toString(); catch(Exception e)
6、System.out.println(e.toString();,小節安排,文件和流,8.2.1 輸入字節流:InputStream,8.3、字符流,8.4、文件,8.2.2 輸出字節流:OutputStream,8.3.1 輸入字符流:Reader,8.3.2 輸出字符流:Writer,8.3.3 BufferedReader和BufferedWriter,8.1、流的基本概念,8.2、字節流,8.5、對象序列化,8.6、Java中的亂碼問題,8.3.4 字節流和字符流的異同,8.3、字符流,8.3、字符流,輸入字符流:Reader,8.3、字符流,* 讀取G:/aillo.txt文件的內容
7、(一行一行讀),并將其內容寫入G:/jacky.txt中 知識點: java讀文件、寫文件- */ import java.io.*; public class TestFileWR public static void main(String args) try /創建FileReader對象,用來讀取字符流 FileReader fr = new FileReader(G:/aillo.txt); /緩沖指定文件的輸入 BufferedReader br = new BufferedReader(fr); /創建FileWriter對象,用來寫入字符流 FileWriter fw = ne
8、w FileWriter(G:/jacky.txt); /將緩沖對文件的輸出 BufferedWriter bw = new BufferedWriter(fw); String strLine;/用來保存每次讀取的一行,8.3、字符流,while (br.ready() strLine = br.readLine();/讀取一行 bw.write(strLine); /寫入文件 bw.newLine(); System.out.println(strLine);/在屏幕上輸出 bw.flush(); /刷新該流的緩沖,即將該流輸出到目的 bw.close(); br.close(); fw.
9、close(); fr.close(); catch (IOException e) e.printStackTrace();,8.3、字符流,輸出字符流:Writer,8.3、字符流,*從鍵盤輸入一行文字,寫入文件TestFileOut.txt中*/ import java.io.*; public class TestFileOut public static void main(String args) char c=new char512; byte b=new byte512; int n,i; try FileWriter wf=new FileWriter(TestFileOut
10、.txt); /從鍵盤讀入文字并存入字節數組b中 n=System.in.read(b); for(i=0;in;i+) ci=(char)bi; wf.write(c); wf.close(); catch(IOException e) System.out.println(e);,輸入123456ABCDEF并回車,輸入Java是一門優秀的語言!并回車,8.3、字符流,*從鍵盤輸入一行文字(可輸入中文字符),寫入文件TestFileOut.txt中*/ import java.io.*; public class TestFileOutCH public static void main(
11、String args) char c=new char512; int n,i; try FileWriter wf=new FileWriter(TestFileOutCH.txt); /利用InputStreamReader正確讀取中文 System.out.print(請輸入中文:); InputStreamReader isr=new InputStreamReader(System.in); n=isr.read(c,0,512);/一次性讀取512個字符,n表示實際讀取的字符數 wf.write(c); wf.close(); System.out.println(剛輸入的數據為
12、:+String.valueOf(c,0,n); catch(IOException e) System.out.println(e);,8.3、字符流,字符緩沖流:BufferedReader和BufferedWriter,以緩沖區方式對數據進行輸入輸出。 所謂緩沖區,是指一片臨時的內存區域。BufferedReader和BufferedWriter分別擁有8192個字符(16384個字節)的緩沖區。 當BufferedReader從源(文件、網絡、鍵盤或其他進程)讀取字符數據時,會先盡量從源中讀入字符數據并置入緩沖區,而之后若使用read()方法,會先從緩沖區中進行讀取。如果緩沖區數據不足
13、,才會再從源中讀取。 使用BufferedWriter時,寫入的數據并不會先輸出到目的地,而是先存儲至緩沖區中。如果緩沖區中的數據滿了,才會一次對目的地進行寫入。例如一個文件,通過緩沖區可減少對硬盤的輸入/輸出動作,以提高文件存取的效率,8.3、字符流,*本程序首先在控制臺輸入字符(逐行輸入),程序將輸入的文字存儲至指定的文件中,如果要結束程序,輸入quit字符串即可。*/ import java.util.*; import java.io.*; public class TestFileBRW public static void main(String args) try /緩沖Syst
14、em.in輸入流 /System.in是字節流,通過InputStreamReader將其轉換為字符流 BufferedReader bufReader = new BufferedReader(new InputStreamReader(System.in); /緩沖FileWriter BufferedWriter bufWriter = new BufferedWriter(new FileWriter(args0); String input = null; /每讀一行進行一次寫入動作 while(!(input = bufReader.readLine().equals(quit)
15、bufWriter.write(input,8.3、字符流,*newLine()方法寫入與操作系統相依的換行字符,依執行環境當時的OS來決定該輸出那種換行字符*/ bufWriter.newLine(); bufReader.close(); bufWriter.close(); catch(ArrayIndexOutOfBoundsException e) System.out.println(沒有指定文件); catch(IOException e) e.printStackTrace();,8.3、字符流,字節流和字符流的異同,本質區別在于byte和char。字節流采用二進制直接傳輸,用
16、字符流則牽涉到本地系統的編碼問題,在網絡通訊中,強烈建議使用byte字節流方式。 字節流與字符之間的轉化通過InputStreamReader和OutputStreamWriter來關聯,實際上是通過byte和String來關聯。在實際開發中出現的漢字問題實際上都是在字符流和字節流之間轉化不統一而造成的。在從字節流轉化為字符流時,也就是從byte轉化為String時,使用如下構造方法: publicString(bytebytes,StringcharsetName) 這個方法中有一個關鍵的字符集編碼參數charsetName,通常我們都省略了,那系統就用操作系統的默認的language。而在
17、字符流轉化為字節流時,實際上是String轉化為byte時,是使用如下方法進行轉化: byteString.getBytes(StringcharsetName) 字符流和字節流是根據處理數據的不同來區分的。字節流按照8位傳輸,字符流按照16位傳輸由于字符流使用Unicode字符集,支持多國文字,因此若流要跨越多種平臺傳輸,應使用字符流。字符流的傳輸效率比字節流的高,小節安排,文件和流,8.2.1 輸入字節流:InputStream,8.3、字符流,8.4、文件,8.2.2 輸出字節流:OutputStream,8.3.1 輸入字符流:Reader,8.3.2 輸出字符流:Writer,8.3
18、.3 BufferedReader和BufferedWriter,8.1、流的基本概念,8.2、字節流,8.5、對象序列化,8.6、Java中的亂碼問題,8.3.4 字節流和字符流的異同,8.4.1、文件,File文件相關屬性,例如: /假設當前目錄為G:/Java1,有文件 G:/Java1/TestFilePRO.java和目錄/G:/Java1/gfei File f=new File(TestFilePRO.java); File d=new File(Gfei); System.out.println(f.getName=+f.getName();/輸出TestFilePRO.jav
19、a System.out.println(f.getPath=+f.getPath();/輸出TestFilePRO.java /以下語句輸出G:Java1TestFilePRO.java System.out.println(f.getAbsolutePath=+f.getAbsolutePath(); System.out.println(f.getParent=+f.getParent();/輸出null System.out.println(f.length=+f.length();/筆者示例中輸出668 System.out.println(d.getName=+d.getName(
20、);/輸出Gfei System.out.println(d.getPath=+d.getPath();/輸出Gfei System.out.println(d.getAbsolutePath=+d.getAbsolutePath();/輸出G:java1Gfei System.out.println(d.getParent=+d.getParent();/輸出null System.out.println(d.length=+d.length();/輸出0,8.4.1、文件,File文件操作,例如: File ds=new File(subdir); File dd=new File(gfe
21、i1); File fs=new File(TestFileSRC.java); File fd=new File(TestFileDEST.txt); ds.renameTo(dd);/改為gfei1 fs.renameTo(fd);/改為TestFileDEST.txt,public boolean renameTo(File dest) /重新命名文件或目錄 /刪除文件或目錄。如果是目錄,則該目錄必須為空才能刪除。 public boolean delete(,8.4.1、文件,目錄操作,public boolean mkdir() /創建目錄 public String list()/
22、返回一個字符串數組,是給定目錄下的文件與子目錄 public File listFiles()/返回File對象數組,是給定目錄下的文件,8.4.1、文件,*打印某目錄下(包含子目錄)所有文件和文件大小*/ import java.io.*; public class TestFileLIST public static void main(String args)throws IOException File files=new File(.);/.表示當前目錄(與TestFileLIST.java所在的同一個目錄) listPath(files); public static void l
23、istPath(File f) throws IOException String file_list=f.list(); for(int i=0;ifile_list.length;i+) File cf=new File(f.getPath(),file_listi); if(cf.isDirectory() /判斷是否為子目錄 listPath(cf);/列舉該子目錄下的文件 if(cf.isFile()/判斷是否為文件 try /輸出文件大小 System.out.println(cf.getCanonicalPath()+:+cf.length(); catch(IOExceptio
24、n e) e.printStackTrace();,8.4.2、隨機訪問文件類:RandomAccessFile,RandomAccessFile類提供了對文件的隨機訪問方式,即可在文件的任意位置讀或寫數據而且可以同時進行讀和寫的操作,8.4.2、隨機訪問文件類:RandomAccessFile,提供了類似于readInt()的其他方法用于讀取byte、boolean、char、double、float、long、short、unsignedbyte、unsignedshort等數據類型的方法,即readByte()、readBoolean()、readChar()、readDouble()、
25、readFloat()、readLong()、readShort()、readUnsignedByte()、readUnsignedShort()等 提供了writeByte()、writeBoolean()、writeChar()、writeDouble()、writeFloat()、writeLong()、writeShort()等方法用于寫入數據,8.4.2、隨機訪問文件類:RandomAccessFile,*向文件中寫入10個數據,第i個數據圓周率*i(i=0, 1, 2, , 9),然后將第2個(i=2)改為0,最后將10個數據全部輸出*/ import java.io.IOExce
26、ption; import java.io.RandomAccessFile; public class TestFileRAF public static void main(String args ) try RandomAccessFile f=new RandomAccessFile(TestFileRAF.txt, rw);/可讀寫 int i; double d; /寫:向文件寫入10個數據 for (i=0; i10; i+) f.writeDouble(Math.PI*i,8.4.2、隨機訪問文件類:RandomAccessFile,修改:對文件中第2個double數據改為0
27、f.seek(16);/文件指針往前走16個字節(2個double數據) f.writeDouble(0); f.seek(0);/文件指針回到文件首部 /讀?。簩⑷繑祿x出并打印到屏幕中 for (i=0; i 10; i+) d=f.readDouble( ); System.out.println( + i + : + d); f.close( ); catch (IOException e) System.err.println(發生異常: + e); e.printStackTrace( );,8.4.2、隨機訪問文件類:RandomAccessFile,8.4.3、文件過濾接口:
28、FileFilter和FilenameFilter,FileFilter和FilenameFilter是為開發者提供在文件系統中進行過濾或者說是搜索所需要文件的功能,均有accept()方法: /FileFilter: file表示要過濾目錄中的文件對象 public boolean accept(File file); /*FilenameFilter: 參數dir是要過濾的目錄, name是目錄中的文件名*/ public boolean accept(File dir, String name); 區別:FileFilter提供文件對象的訪問方法,而FilenameFilter是按照目錄
29、和文件的名稱的方式來工作,8.4.3、文件過濾接口:FileFilter和FilenameFilter,實現文件或目錄過濾所需步驟,聲明一個過濾器類并實現FileFilter或FilenameFilter接口中的accept方法。 使用File類的list()和listFiles()進行過濾,其參數為第步中的過濾器類的對象作為參數,就可實現對文件名的過濾。File類的list()和listFiles()方法聲明如下: public String list(FilenameFilter filter) public File listFiles(FilenameFilter filter) pu
30、blic File listFlies(FileFilter filter) 其中,filter須是第步中實現了FileFilter或FilenameFilter接口中的accept方法的過濾器類的對象,8.4.3、文件過濾接口:FileFilter和FilenameFilter,import java.io.*; /第步:聲明過濾類ListFilter并實現FilenameFilter接口中的accept方法 class ListFilter implements FilenameFilter private String pre=“”, ext=“”;/pre表示文件前綴,ext表示文件后
31、綴 public ListFilter(String filterstr) int i, j; filterstr=filterstr.toLowerCase(); i=filterstr.indexOf(*); j=filterstr.indexOf(.); if(i0) pre=filterstr.substring(0,i); if(i=-1,8.4.3、文件過濾接口:FileFilter和FilenameFilter,實現accept方法 public boolean accept(File dir,String filename) boolean y=true; try filena
32、me=filename.toLowerCase(); y=filename.startsWith(pre),8.4.3、文件過濾接口:FileFilter和FilenameFilter,第步:使用File類的list()和listFiles()進行過濾 public class TestFileSearch public static void main(String args) /要求兩個參數:第一個參數表示目錄,第二參數表示要過濾的文件 String strDir, strExtension; switch(args.length) case 1: strDir=.; strExtensi
33、on=args0; break; case 2: strDir=args0; strExtension=args1; break; default: System.out.println(需兩個參數!); return; File f=new File(strDir); ListFilter ls=new ListFilter(strExtension); String str=f.list(ls); for(int i=0; istr.length; i+) System.out.println(stri);,小節安排,文件和流,8.2.1 輸入字節流:InputStream,8.3、字符流
34、,8.4、文件,8.2.2 輸出字節流:OutputStream,8.3.1 輸入字符流:Reader,8.3.2 輸出字符流:Writer,8.3.3 BufferedReader和BufferedWriter,8.1、流的基本概念,8.2、字節流,8.5、對象序列化,8.6、Java中的亂碼問題,8.3.4 字節流和字符流的異同,8.5、對象序列化,什么是對象序列化,保存內存中某個對象的方法很多,但是Java給你提供一種更好的保存對象狀態的機制,那就是對象序列化。 java中對象序列化的過程就是將對象寫入字節流和從字節流中讀取對象。將對象狀態轉換成字節流之后,可以保存到文件、通過管道輸出到
35、另一線程或通過網絡連接將對象數據發送到另一主機,8.5、對象序列化,什么情況下需要序列化,把內存中的對象保存到一個文件中或者數據庫中 用套接字(socket)在網絡上傳送對象 通過RMI傳輸對象,8.5、對象序列化,實現序列化的步驟,第一步:創建一個FileOutputStream對象,如下: FileOutputStream fs = new FileOutputStream(foo.ser); 第二步:java.io.ObjectOutputStream負責將對象寫入字節流。因此第二步是利用第一步創建的FileOutputStream對象創新一個ObjectOutputStream對象,如
36、下: ObjectOutputStream os = new ObjectOutputStream(fs); 第三步:將對象寫入 Foo myFoo1=new Foo(); Foo myFoo2=new Foo(); Foo myFoo3=new Foo(); os.writeObject(myFoo1); os.writeObject(myFoo2); os.writeObject(myFoo3); 第四步:關閉ObjectOutputStream os.close(,8.5、對象序列化,序列化對象的條件,被序列化的對象必須是實現java.io.Serializable接口的類對象。java
37、.io.Serializable接口中沒有方法需要實現,之所以要implements該接口,只是告訴JVM,該類對象是可被序列化而已,例如: imports java.io.*; class Foo implements Serializable int width; int height; Date todayDate;,8.5、對象序列化,反序列化,反序列化是打開字節流并重構對象。對象序列化不僅要將基本數據類型轉換成字節表示,有時還要恢復數據。反序列化通常使用java.io.ObjectInputStream從字節流重構對象,例如: FileInputStream in = new Fil
38、eInputStream(foo.ser); ObjectInputStream ois = new ObjectInputStream(in); Foo myFoo1=(Foo)ois.readObject(); Foo myFoo2=(Foo)ois.readObject(); Foo myFoo3=(Foo)ois.readObject(,8.5、對象序列化,import java.io.Serializable; /*Student定義為序列化類*/ public class Student implements Serializable static final long seria
39、lVersionUID = 123456L; String m_name; int m_id; int m_height; public Student( String name, int id, int h ) m_name = name; m_id = id; m_height = h; public void output( ) System.out.println(姓名: + m_name); System.out.println(學號: + m_id); System.out.println(身高: + m_height);,8.5、對象序列化,*將Student對象數據寫入obje
40、ct.dat*/ import java.io.FileOutputStream; import java.io.ObjectOutputStream; public class TestWriteObject public static void main(String args ) try ObjectOutputStream f = new ObjectOutputStream( new FileOutputStream(object.dat); Student s = new Student( 張三, 2003001, 172); f.writeObject(s); s.output(
41、 ); f.close( ); catch (Exception e) System.err.println(發生異常: + e); e.printStackTrace( );,8.5、對象序列化,*從object.dat讀出Student對象數據*/ import java.io.FileInputStream; import java.io.ObjectInputStream; public class TestReadObject public static void main(String args ) try ObjectInputStream f = new ObjectInput
42、Stream( new FileInputStream(object.dat); Student s = (Student)(f.readObject( ); s.output( ); f.close( ); catch (Exception e) System.err.println(發生異常: + e); e.printStackTrace( );,8.5、對象序列化,序列化注意事項,只有對象的數據被保存,方法與構造函數不被序列化。 聲明為transient或static的變量不能被序列化,小節安排,文件和流,8.2.1 輸入字節流:InputStream,8.3、字符流,8.4、文件,8
43、.2.2 輸出字節流:OutputStream,8.3.1 輸入字符流:Reader,8.3.2 輸出字符流:Writer,8.3.3 BufferedReader和BufferedWriter,8.1、流的基本概念,8.2、字節流,8.5、對象序列化,8.6、Java中的亂碼問題,8.3.4 字節流和字符流的異同,8.6.1、Java中字符的表達,Java中字 符表達,char,byte,網絡傳輸或存儲 的序列化形式,內存形式,一個字節 8bits,一個Unicode字符 16bits,String,一組char,8.6.1、Java中字符的表達,例如: String ying = 英; c
44、har cy= ying.charAt(0); /取得首字符 /將英轉換成java默認編碼字符(UTF-16) String yingHex = Integer.toHexString(cy); System.out.println(yingHex.toUpperCase();/輸出默認編碼:82 F1 /將英轉換成GBK編碼 byte yingGBBytes = ying.getBytes(GBK); String hex; for(int i=0; iyingGBBytes.length; i+) hex=Integer.toHexString(yingGBBytesi /英的GBK編碼:
45、D3 A2,8.6.2、Unicode簡介,什么是Unicode呢?Unicode,又稱為統一碼、萬國碼或單一碼,它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求,即為每種語言的每個字符設定一個統一的序數。 ISO與Unicode獨立發展,至1992年合并協同。從Unicode 2.0開始,Unicode采用了與ISO 10646-1相同的字庫和字碼;ISO也承諾,ISO 10646將不會替超出0 x10FFFF的UCS-4編碼賦值,以使二者保持一致,8.6.2、Unicode編碼方式,Unicode編碼基于ISO 10646定義的通用字符集
46、(Universal Character Set,UCS) ,有UCS-2和UCS-4,分別用2個字節和4個字節編碼。 UCS-4定義如下,而UCS-4的高位的兩個字節為0即為UCS-2 Unicode是UCS-4的子集,計劃使用第0分組的17個平面,因此其編碼數為:17(平面)*256(行)*256(碼位)=1114112 個編碼,編碼范圍為011141121,即00 x10FFFF。實際定義了238605個,分布在平面0、1、2、14(0000 1110)、15(0000 1111)、16(0001 0000),其中15和16平面只是分別定義了兩個專用區,平面0的0 xE000-0 xF8
47、FF為專用區,0 xD800-0 xDFFF為代理區,因此目前真正定義的字符有238605-65534*2-6400-2048=99089個 。 因此,編碼集的取值范圍如下:UCS-2 UnicodeUCS-4,8.6.3、Unicode實現方式,整個Unicode 編碼系統或者說Unicode編碼標準可分為編碼方式和實現方式兩個層次。編碼方式是指Unicode如何對各種語言的每個字符進行編號的;而實現方式則是指同一個字符的Unicode編碼在不同的系統中的程序實現方式,比如漢語中的“字”在Unicode中的編號為23383,那么它在Windows或Mac OS操作系統中分別占幾個字節?如何存
48、儲與表達?等等,這些問題就是指Unicode的實現方式。 例:漢字“嚴”的Unicode是十六進制數0 x4E25,轉換成二進制數足足有15位(100 1110 0010 0101),也就是說這個符號的表示至少需要2個字節。表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。 如何才能區分Unicode和ASCII? 計算機怎么知道三個字節表示一個符號,而不是分別表示三個符號呢? 如果Unicode統一規定,每個符號用三個或四個字節表示,那么每個英文字母前都必然有二到三個字節是0,這對于存儲來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。 它們造成的結果是:1)出現了
49、Unicode的多種存儲方式,也就是說有許多種不同的二進制格式,可以用來表示Unicode。2)Unicode在很長一段時間內無法推廣,直到互聯網的出現,8.6.3、Unicode實現方式,在Unicode中,漢語字對應的編碼是23383。在Unicode中,我們有很多方式將數字23383表示成程序中的數據,包括:UTF-8、UTF-16、UTF-32。UTF是UCS Transformation Format的縮寫,可以翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據。 例如,漢字對應的數字是0 x6C49和0 x5B57,而編碼的程序數據是: BYTE d
50、ata_utf8 = 0 xE6, 0 xB1, 0 x89, 0 xE5, 0 xAD, 0 x97; / UTF-8 WORD data_utf16 = 0 x6C49, 0 x5B57; / UTF-16編碼 DWORD data_utf32 = 0 x6C49, 0 x5B57; / UTF-32編碼 這里用BYTE、WORD、DWORD分別表示無符號8位整數,無符號16位整數和無符號32位整數。UTF-8、UTF-16、UTF-32分別以BYTE、WORD、DWORD作為編碼單位。漢字的UTF-8編碼需要6個字節。漢字的UTF-16編碼需要兩個WORD,大小是4個字節。漢字的UTF-
51、32編碼需要兩個DWORD,大小是8個字節,8.6.3、Unicode實現方式:UTF-8,8.6.3、Unicode實現方式:UTF-8,8.6.3、Unicode實現方式:UTF-16,UTF-16編碼以16位無符號整數為單位。令某個字符的Unicode編碼為U,則用UTF-16實現該編碼的規則如下: 如果U0 x10000,U的UTF-16編碼就是U對應的16位無符號整數(為書寫簡便,下文將16位無符號整數記作WORD)。 如果U0 x10000,我們先計算U=U-0 x10000,然后將U寫成二進制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16編碼(二進制)就
52、是:110110yy yyyyyyyy 110111xx xxxxxxxx,8.6.3、Unicode實現方式:UTF-16,例:已知Unicode編碼,計算其UTF-16編碼 U=0 x20C30 U0 x10000 U=U-0 x10000=0 x10C30=0001 0000 1100 0011 0000 用前10位依次替代模板中的y,用后10位依次替代模板中的x,得:1101100001000011 1101110000110000,即0 xD843 0 xDC30,此為4字節的UTF-16編碼,8.6.3、Unicode實現方式:UTF-16,根據規則,U0 x10000,用四個字節
53、表示,其中第一個WORD是110110yy yyyyyyyy,其最小為11011000 00000000,最大為11011011 11111111,即0 xD800-0 xDBFF,同理第二個WORD為0 xDC00-0 xDFFF,這2048個編碼在Unicode中為專用,正是使用于此。 也就是說,沒有單個字符的編碼是位于0 xD800-0 xDFFF之間的,如果出現在此范圍內,說明是由四個字節構成一個字符;否則是由兩個字節構成一個字符。 則,給定UTF-16編碼序列,怎么知道這是一個WORD的UTF-16編碼還是兩個WORD的UTF-16編碼呢,8.6.3、Unicode實現方式:UTF-
54、16,高位替代是指這個范圍(0 xD800-0 xDB7F)的碼位是兩個WORD的UTF-16編碼的第一個WORD。 低位替代就是指這個范圍(0 xDC00-0 xDFFF)的碼位是兩個WORD的UTF-16編碼的第二個WORD。 高位專用替代是兩個WORD的UTF-16編碼的第一個WORD在此范圍內對應的是Unicode專用區編碼0 xF0000-0 x10FFFF,它在Unicode中沒有定義,8.6.3、Unicode實現方式:UTF-16,例:從網絡上讀取到一個字節序列(16進制表示:D9 E2 DD E5),同時假設該字節序列是UTF-16字符,并使用Big Endian(即高位在低
55、地址,低位在高地址)的字節序,判斷該序列是一個字符(4字節編碼)還是兩個字符(2字節編碼): 每次讀入兩個字節(先讀入D9 E2),根據Big Endian規則,該數據為0 xD9E2。我們先檢查一下,這兩個字節是不是在0 xD800-0 xDB7F范圍內?如果是,那表示我們讀到了一個超過兩個字節的字符,在本例中,0 xD9E2正好是在這個范圍內,因此,我們就知道這兩個字節跟接下來的兩個字節0 xDDE5才能組成一個真正的字符;如果不在0 xD800-0 xDBFF范圍內,那簡單了,這就是一個雙字節的字符而已。 由此,本例中的字符即為0 xD9E2DDE5,根據UTF-16編碼規則,將其展開為
56、二制位如下: 110110 0111100010 110111 0111100101 再根據UTF-16編碼規則,得到U=0111100010 0111100101,再計算U= U+0 x10000=0 x889E5,這就是該字符對應的Unicode碼,8.6.3、Unicode實現方式:UTF-16,根據UTF-16編碼規則,若第一個WORD位于高位替代范圍(0 xD800-0 xDB7F),則第二個WORD必然位于低位替代范圍(0 xDC00-0 xDFFF),否則必然導致亂碼; 若第一個WORD位于高位專用替代范圍(0 xDB80-0 xDBFF),則第二個WORD必須位于低位替代范圍(
57、0 xDC00-0 xDFFF),否則必然導致亂碼; 若第一個WORD位于高位專用替代范圍(0 xDB80-0 xDBFF),且第二個WORD位于低位替代范圍(0 xDC00-0 xDFFF),但接受方與發送方在該范圍內的Unicode編碼實現方式不一致,則導致亂碼,8.6.4、Unicode實現方式:UTF-32,UTF-32編碼以32位無符號整數為單位。Unicode的UTF-32編碼就是其對應的32位無符號整數,8.6.5、字節序:Little Endian和Big Endian,名稱來自英國作家斯威夫特的格列佛游記:因人們爭論吃雞蛋時究竟是從大頭(Big-Endian)敲開還是從小頭(
58、Little-Endian)敲開前后爆發了六次戰爭,一個皇帝送了命,另一個皇帝丟了王位。 Little Endian和Big Endian是CPU處理多字節數的不同方式。例如“漢”的Unicode編碼是0 x6C49。那么寫到文件里或從網絡發送出去時(按字節流)時,究竟是將6C寫在前面,還是將49寫在前面?如果將6C寫在前面,就是Big Endian;如果將49寫在前面,就是Little Endian。 為什么電子郵件常常出現亂碼?就是因為發信人和收信人使用的編碼方式、字節序不一樣,8.6.5、字節序:Little Endian和Big Endian,Unicode規范中定義,每一個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫做“零寬度非換行空格”(ZERO WIDTH NO-BREAK SPACE),用FEFF表示,正好是兩個字節,而且FF比FE大1。 定義:如果一個序列的頭兩個字節是FE FF,就表示該文件采用Big
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年陜西貨運從業資格證考試500題
- 某商超自救技能規定
- 幼兒園看圖寫人小故事9篇范文
- 蔬菜農資采購與存儲管理系統協議
- 2025年高性能鈷粉項目提案報告
- 2025年高性能陶瓷刀具材料項目規劃申請報告
- 2025年新型結構不銹鋼絲繩項目申請報告模板
- 智能停車車牌識別系統開發協議
- 2025年阿拉伯語等級考試沖刺復習試卷
- 2025年法語TEF考試試卷寫作技巧與范文分析試題
- 土地利用現狀分類代碼表
- 華為“1+X”職業技能等級(網絡系統建設與運維)中級考試題庫(含答案)
- (完整版)生產車間地面畫線標準
- 單位財務內控制度
- 有機硅化合物的基本性質
- “阿里巴巴”并購“餓了么”案例分析
- 口腔完整病歷范文(合集27篇)
- 山東省病原微生物實驗室及實驗活動備案管理系統
- 小學道德與法治-被動物咬傷怎么辦教學設計學情分析教材分析課后反思
- GB/T 30114.1-2013空間科學及其應用術語第1部分:基礎通用
- FZ/T 63012-2009滌綸長絲高強縫紉線
評論
0/150
提交評論