一起学 Java(四) File、Try 、序列化、MySQL、Socket
一、Java 流(Stream)、文件(File)和IO
Java.io 包幾乎包含了所有操作輸入、輸出需要的類。所有這些流類代表了輸入源和輸出目標(biāo)。
Java.io 包中的流支持很多種格式,比如:基本類型、對(duì)象、本地化字符集等等。
一個(gè)流可以理解為一個(gè)數(shù)據(jù)的序列。輸入流表示從一個(gè)源讀取數(shù)據(jù),輸出流表示向一個(gè)目標(biāo)寫數(shù)據(jù)。
Java 為 I/O 提供了強(qiáng)大的而靈活的支持,使其更廣泛地應(yīng)用到文件傳輸和網(wǎng)絡(luò)編程中。
?
Java?BufferedReader?類
讀取控制臺(tái)輸入
Java 的控制臺(tái)輸入由 System.in 完成。
為了獲得一個(gè)綁定到控制臺(tái)的字符流,你可以把 System.in 包裝在一個(gè) BufferedReader 對(duì)象中來(lái)創(chuàng)建一個(gè)字符流。
下面是創(chuàng)建 BufferedReader 的基本語(yǔ)法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));BufferedReader 對(duì)象創(chuàng)建后,我們便可以使用 read() 方法從控制臺(tái)讀取一個(gè)字符,或者用 readLine() 方法讀取一個(gè)字符串。
從控制臺(tái)讀取多字符輸入
從 BufferedReader 對(duì)象讀取一個(gè)字符要使用 read() 方法,每次調(diào)用 read() 方法,它從輸入流讀取一個(gè)字符并把該字符作為整數(shù)值返回。 當(dāng)流結(jié)束的時(shí)候返回 -1。該方法拋出 IOException。
// 使用 BufferedReader 在控制臺(tái)讀取字符package four;import java.io.*;public class BRRead {public static void main(String args[]) throws IOException{char c;// 使用 System.in 創(chuàng)建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.println("輸入字符, 按下 'q' 鍵退出。");// 讀取字符do {c = (char) br.read();System.out.println(c);} while(c != 'q');} }/*輸出結(jié)果 輸入字符, 按下 'q' 鍵退出。 suoning s u o n i n gq q*/ View Code從控制臺(tái)讀取字符串
從標(biāo)準(zhǔn)輸入讀取一個(gè)字符串需要使用 BufferedReader 的 readLine() 方法。
它的一般格式是:
String readLine( ) throws IOException // 使用 BufferedReader 在控制臺(tái)讀取字符package four;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class BRReadLines {public static void main(String args[]) throws IOException{// 使用 System.in 創(chuàng)建 BufferedReader BufferedReader br = new BufferedReader(newInputStreamReader(System.in));String str;System.out.println("Enter lines of text.");System.out.println("Enter 'end' to quit.");do {str = br.readLine();System.out.println(str);} while(!str.equals("end"));} }/*輸出結(jié)果 Enter lines of text. Enter 'end' to quit. suoning suoning end end */ View Code控制臺(tái)輸出
控制臺(tái)的輸出由 print( ) 和 println() 完成。這些方法都由類 PrintStream 定義,System.out 是該類對(duì)象的一個(gè)引用。
PrintStream 繼承了 OutputStream類,并且實(shí)現(xiàn)了方法 write()。這樣,write() 也可以用來(lái)往控制臺(tái)寫操作。
PrintStream 定義 write() 的最簡(jiǎn)單格式如下所示:
該方法將 byteval 的低八位字節(jié)寫到流中。 void write(int byteval) // 演示 System.out.write().import java.io.*;public class WriteDemo {public static void main(String args[]) {int b; b = 'S';System.out.write(b);System.out.write('\n');} }/*輸出結(jié)果 S */ View Code?
Java Scanner 類
java.util.Scanner 是 Java5 的新特征,我們可以通過(guò) Scanner 類來(lái)獲取用戶的輸入。
下面是創(chuàng)建 Scanner 對(duì)象的基本語(yǔ)法:
Scanner s = new Scanner(System.in);?
package four;import java.util.Scanner;public class ScannerDemo {public static void main(String[] args) { Scanner scan = new Scanner(System.in); // 從鍵盤接收數(shù)據(jù) //next方式接收字符串System.out.println("next方式接收:");// 判斷是否還有輸入if(scan.hasNext()){ String str1 = scan.next();System.out.println("輸入的數(shù)據(jù)為:"+str1); }} }/*輸出結(jié)果 next方式接收: suo ning 輸入的數(shù)據(jù)為:suo */ next package four;import java.util.Scanner;public class ScannerLinesDemo {public static void main(String[] args) { Scanner scan = new Scanner(System.in); // 從鍵盤接收數(shù)據(jù) //nextLine方式接收字符串System.out.println("nextLine方式接收:");// 判斷是否還有輸入if(scan.hasNextLine()){ String str2 = scan.nextLine();System.out.println("輸入的數(shù)據(jù)為:"+str2); }} }/*輸出結(jié)果 nextLine方式接收: suo ning 輸入的數(shù)據(jù)為:suo ning */ nextLine?
next() 與 nextLine() 區(qū)別
next():
- 1、一定要讀取到有效字符后才可以結(jié)束輸入。
- 2、對(duì)輸入有效字符之前遇到的空白,next() 方法會(huì)自動(dòng)將其去掉。
- 3、只有輸入有效字符后才將其后面輸入的空白作為分隔符或者結(jié)束符。
- next() 不能得到帶有空格的字符串。
nextLine():
- 1、以Enter為結(jié)束符,也就是說(shuō) nextLine()方法返回的是輸入回車之前的所有字符。
- 2、可以獲得空白。
?
輸入之前最好先使用 hasNextXxx() 方法進(jìn)行驗(yàn)證,再使用 nextXxx() 來(lái)讀取。
package four;import java.util.Scanner;public class ScannerHGDemo {public static void main(String[] args) { Scanner scan = new Scanner(System.in); // 從鍵盤接收數(shù)據(jù) int i = 0 ; float f = 0.0f ; System.out.print("輸入整數(shù):"); if(scan.hasNextInt()){ // 判斷輸入的是否是整數(shù) i = scan.nextInt() ; // 接收整數(shù) System.out.println("整數(shù)數(shù)據(jù):" + i) ; }else{ // 輸入錯(cuò)誤的信息 System.out.println("輸入的不是整數(shù)!") ; } System.out.print("輸入小數(shù):"); if(scan.hasNextFloat()){ // 判斷輸入的是否是小數(shù) f = scan.nextFloat() ; // 接收小數(shù) System.out.println("小數(shù)數(shù)據(jù):" + f) ; }else{ // 輸入錯(cuò)誤的信息 System.out.println("輸入的不是小數(shù)!") ; }Scanner scan1 = new Scanner(System.in);System.out.print("輸入個(gè)數(shù):"); double sum = 0; int m = 0; while(scan1.hasNextDouble()) { double x = scan1.nextDouble(); m = m + 1; sum = sum + x; } System.out.println(m+"個(gè)數(shù)的和為"+sum); System.out.println(m+"個(gè)數(shù)的平均值是"+(sum/m));} }/*輸出結(jié)果 輸入整數(shù):1 整數(shù)數(shù)據(jù):1 輸入小數(shù):1.1 小數(shù)數(shù)據(jù):1.1 輸入個(gè)數(shù):101個(gè)數(shù)的和為10.0 1個(gè)數(shù)的平均值是10.0 */ View Code?
讀寫文件
一個(gè)流被定義為一個(gè)數(shù)據(jù)序列。輸入流用于從源讀取數(shù)據(jù),輸出流用于向目標(biāo)寫數(shù)據(jù)。
下圖是一個(gè)描述輸入流和輸出流的類層次圖。
?
FileInputStream
該流用于從文件讀取數(shù)據(jù),它的對(duì)象可以用關(guān)鍵字 new 來(lái)創(chuàng)建。
有多種構(gòu)造方法可用來(lái)創(chuàng)建對(duì)象。
InputStream f = new FileInputStream("C:/java/hello");File f = new File("C:/java/hello"); InputStream f = new FileInputStream(f);創(chuàng)建了InputStream對(duì)象,就可以使用下面的方法來(lái)讀取流或者進(jìn)行其他的流操作:
| 1 | public void close() throws IOException{} 關(guān)閉此文件輸入流并釋放與此流有關(guān)的所有系統(tǒng)資源。拋出IOException異常。 |
| 2 | protected void finalize()throws IOException {} 這個(gè)方法清除與該文件的連接。確保在不再引用文件輸入流時(shí)調(diào)用其 close 方法。拋出IOException異常。 |
| 3 | public int read(int r)throws IOException{} 這個(gè)方法從 InputStream 對(duì)象讀取指定字節(jié)的數(shù)據(jù)。返回為整數(shù)值。返回下一字節(jié)數(shù)據(jù),如果已經(jīng)到結(jié)尾則返回-1。 |
| 4 | public int read(byte[] r) throws IOException{} 這個(gè)方法從輸入流讀取r.length長(zhǎng)度的字節(jié)。返回讀取的字節(jié)數(shù)。如果是文件結(jié)尾則返回-1。 |
| 5 | public int available() throws IOException{} 返回下一次對(duì)此輸入流調(diào)用的方法可以不受阻塞地從此輸入流讀取的字節(jié)數(shù)。返回一個(gè)整數(shù)值。 |
?
FileOutputStream
該類用來(lái)創(chuàng)建一個(gè)文件并向文件中寫數(shù)據(jù)。
如果該流在打開(kāi)文件進(jìn)行輸出前,目標(biāo)文件不存在,那么該流會(huì)創(chuàng)建該文件。
OutputStream f = new FileOutputStream("C:/java/hello")File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f);創(chuàng)建OutputStream 對(duì)象完成后,就可以使用下面的方法來(lái)寫入流或者進(jìn)行其他的流操作:
| 1 | public void close() throws IOException{} 關(guān)閉此文件輸入流并釋放與此流有關(guān)的所有系統(tǒng)資源。拋出IOException異常。 |
| 2 | protected void finalize()throws IOException {} 這個(gè)方法清除與該文件的連接。確保在不再引用文件輸入流時(shí)調(diào)用其 close 方法。拋出IOException異常。 |
| 3 | public void write(int w)throws IOException{} 這個(gè)方法把指定的字節(jié)寫到輸出流中。 |
| 4 | public void write(byte[] w) 把指定數(shù)組中w.length長(zhǎng)度的字節(jié)寫到OutputStream中。 |
?
?實(shí)例
package four;import java.io.*;public class myFileInputStream {public static void main(String[] args){try{byte bWrite [] = {11,22,33,55,66};OutputStream os = new FileOutputStream("F:\\sql_text\\department.txt");for(int x=0;x<bWrite.length;x++){os.write(bWrite[x]);}os.close();InputStream is = new FileInputStream("F:\\sql_text\\department.txt");int size = is.available();for(int i=0;i<size;i++){System.out.print(is.read());}is.close();} catch(IOException e){System.out.println("IOException..");}} } FileInputStream & FileOutputStream?上面的程序首先創(chuàng)建文件test.txt,并把給定的數(shù)字以二進(jìn)制形式寫進(jìn)該文件,同時(shí)輸出到控制臺(tái)上。
以上代碼由于是二進(jìn)制寫入,可能存在亂碼,你可以使用以下代碼實(shí)例來(lái)解決亂碼問(wèn)題:
package four;import java.io.*;public class fileStreamTest2{public static void main(String[] args) throws IOException {File f = new File("F:\\sql_text\\department.txt");FileOutputStream fop = new FileOutputStream(f);// 構(gòu)建FileOutputStream對(duì)象,文件不存在會(huì)自動(dòng)新建 OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");// 構(gòu)建OutputStreamWriter對(duì)象,參數(shù)可以指定編碼,默認(rèn)為操作系統(tǒng)默認(rèn)編碼,windows上是gbk writer.append("中文輸入");// 寫入到緩沖區(qū) writer.append("\r\n");//換行 writer.append("English");// 刷新緩存沖,寫入到文件,如果下面已經(jīng)沒(méi)有寫入的內(nèi)容了,直接close也會(huì)寫入 writer.close();//關(guān)閉寫入流,同時(shí)會(huì)把緩沖區(qū)內(nèi)容寫入文件,所以上面的注釋掉 fop.close();// 關(guān)閉輸出流,釋放系統(tǒng)資源 FileInputStream fip = new FileInputStream(f);// 構(gòu)建FileInputStream對(duì)象 InputStreamReader reader = new InputStreamReader(fip, "UTF-8");// 構(gòu)建InputStreamReader對(duì)象,編碼與寫入相同 StringBuffer sb = new StringBuffer();while (reader.ready()) {sb.append((char) reader.read());// 轉(zhuǎn)成char加到StringBuffer對(duì)象中 }System.out.println(sb.toString());reader.close();// 關(guān)閉讀取流 fip.close();// 關(guān)閉輸入流,釋放系統(tǒng)資源 } } FileInputStream & FileOutputStream??
二、Java 異常處理
要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:
- 檢查性異常:最具代表的檢查性異常是用戶錯(cuò)誤或問(wèn)題引起的異常,這是程序員無(wú)法預(yù)見(jiàn)的。例如要打開(kāi)一個(gè)不存在文件時(shí),一個(gè)異常就發(fā)生了,這些異常在編譯時(shí)不能被簡(jiǎn)單地忽略。
- 運(yùn)行時(shí)異常:?運(yùn)行時(shí)異常是可能被程序員避免的異常。與檢查性異常相反,運(yùn)行時(shí)異常可以在編譯時(shí)被忽略。
- 錯(cuò)誤:?錯(cuò)誤不是異常,而是脫離程序員控制的問(wèn)題。錯(cuò)誤在代碼中通常被忽略。例如,當(dāng)棧溢出時(shí),一個(gè)錯(cuò)誤就發(fā)生了,它們?cè)诰幾g也檢查不到的。
Exception 類的層次
所有的異常類是從 java.lang.Exception 類繼承的子類。
Exception 類是 Throwable 類的子類。除了Exception類外,Throwable還有一個(gè)子類Error 。
Java 程序通常不捕獲錯(cuò)誤。錯(cuò)誤一般發(fā)生在嚴(yán)重故障時(shí),它們?cè)贘ava程序處理的范疇之外。
Error 用來(lái)指示運(yùn)行時(shí)環(huán)境發(fā)生的錯(cuò)誤。
例如,JVM 內(nèi)存溢出。一般地,程序不會(huì)從錯(cuò)誤中恢復(fù)。
異常類有兩個(gè)主要的子類:IOException 類和 RuntimeException 類。
?
?
?
Java 內(nèi)置異常類
Java 語(yǔ)言定義了一些異常類在 java.lang 標(biāo)準(zhǔn)包中。
標(biāo)準(zhǔn)運(yùn)行時(shí)異常類的子類是最常見(jiàn)的異常類。由于 java.lang 包是默認(rèn)加載到所有的 Java 程序的,所以大部分從運(yùn)行時(shí)異常類繼承而來(lái)的異常都可以直接使用。
Java 根據(jù)各個(gè)類庫(kù)也定義了一些其他的異常,下面的表中列出了 Java 的非檢查性異常。
| ArithmeticException | 當(dāng)出現(xiàn)異常的運(yùn)算條件時(shí),拋出此異常。例如,一個(gè)整數(shù)"除以零"時(shí),拋出此類的一個(gè)實(shí)例。 |
| ArrayIndexOutOfBoundsException | 用非法索引訪問(wèn)數(shù)組時(shí)拋出的異常。如果索引為負(fù)或大于等于數(shù)組大小,則該索引為非法索引。 |
| ArrayStoreException | 試圖將錯(cuò)誤類型的對(duì)象存儲(chǔ)到一個(gè)對(duì)象數(shù)組時(shí)拋出的異常。 |
| ClassCastException | 當(dāng)試圖將對(duì)象強(qiáng)制轉(zhuǎn)換為不是實(shí)例的子類時(shí),拋出該異常。 |
| IllegalArgumentException | 拋出的異常表明向方法傳遞了一個(gè)不合法或不正確的參數(shù)。 |
| IllegalMonitorStateException | 拋出的異常表明某一線程已經(jīng)試圖等待對(duì)象的監(jiān)視器,或者試圖通知其他正在等待對(duì)象的監(jiān)視器而本身沒(méi)有指定監(jiān)視器的線程。 |
| IllegalStateException | 在非法或不適當(dāng)?shù)臅r(shí)間調(diào)用方法時(shí)產(chǎn)生的信號(hào)。換句話說(shuō),即 Java 環(huán)境或 Java 應(yīng)用程序沒(méi)有處于請(qǐng)求操作所要求的適當(dāng)狀態(tài)下。 |
| IllegalThreadStateException | 線程沒(méi)有處于請(qǐng)求操作所要求的適當(dāng)狀態(tài)時(shí)拋出的異常。 |
| IndexOutOfBoundsException | 指示某排序索引(例如對(duì)數(shù)組、字符串或向量的排序)超出范圍時(shí)拋出。 |
| NegativeArraySizeException | 如果應(yīng)用程序試圖創(chuàng)建大小為負(fù)的數(shù)組,則拋出該異常。 |
| NullPointerException | 當(dāng)應(yīng)用程序試圖在需要對(duì)象的地方使用?null?時(shí),拋出該異常 |
| NumberFormatException | 當(dāng)應(yīng)用程序試圖將字符串轉(zhuǎn)換成一種數(shù)值類型,但該字符串不能轉(zhuǎn)換為適當(dāng)格式時(shí),拋出該異常。 |
| SecurityException | 由安全管理器拋出的異常,指示存在安全侵犯。 |
| StringIndexOutOfBoundsException | 此異常由?String?方法拋出,指示索引或者為負(fù),或者超出字符串的大小。 |
| UnsupportedOperationException | 當(dāng)不支持請(qǐng)求的操作時(shí),拋出該異常。 |
?
下面的表中列出了 Java 定義在 java.lang 包中的檢查性異常類。
| ClassNotFoundException | 應(yīng)用程序試圖加載類時(shí),找不到相應(yīng)的類,拋出該異常。 |
| CloneNotSupportedException | 當(dāng)調(diào)用?Object?類中的?clone?方法克隆對(duì)象,但該對(duì)象的類無(wú)法實(shí)現(xiàn)?Cloneable?接口時(shí),拋出該異常。 |
| IllegalAccessException | 拒絕訪問(wèn)一個(gè)類的時(shí)候,拋出該異常。 |
| InstantiationException | 當(dāng)試圖使用?Class?類中的?newInstance?方法創(chuàng)建一個(gè)類的實(shí)例,而指定的類對(duì)象因?yàn)槭且粋€(gè)接口或是一個(gè)抽象類而無(wú)法實(shí)例化時(shí),拋出該異常。 |
| InterruptedException | 一個(gè)線程被另一個(gè)線程中斷,拋出該異常。 |
| NoSuchFieldException | 請(qǐng)求的變量不存在 |
| NoSuchMethodException | 請(qǐng)求的方法不存在 |
?
異常方法
下面的列表是 Throwable 類的主要方法:
?
| 1 | public String getMessage() 返回關(guān)于發(fā)生的異常的詳細(xì)信息。這個(gè)消息在Throwable 類的構(gòu)造函數(shù)中初始化了。 |
| 2 | public Throwable getCause() 返回一個(gè)Throwable 對(duì)象代表異常原因。 |
| 3 | public String toString() 使用getMessage()的結(jié)果返回類的串級(jí)名字。 |
| 4 | public void printStackTrace() 打印toString()結(jié)果和棧層次到System.err,即錯(cuò)誤輸出流。 |
| 5 | public StackTraceElement [] getStackTrace() 返回一個(gè)包含堆棧層次的數(shù)組。下標(biāo)為0的元素代表?xiàng)m?#xff0c;最后一個(gè)元素代表方法調(diào)用堆棧的棧底。 |
| 6 | public Throwable fillInStackTrace() 用當(dāng)前的調(diào)用棧層次填充Throwable 對(duì)象棧層次,添加到棧層次任何先前信息中。 |
?
捕獲異常
使用 try 和 catch 關(guān)鍵字可以捕獲異常。try/catch 代碼塊放在異常可能發(fā)生的地方。
try/catch代碼塊中的代碼稱為保護(hù)代碼,使用 try/catch 的語(yǔ)法如下:
try {// 程序代碼 }catch(ExceptionName e1) {//Catch 塊 }?
多重捕獲塊
一個(gè) try 代碼塊后面跟隨多個(gè) catch 代碼塊的情況就叫多重捕獲。
?
finally關(guān)鍵字
finally 關(guān)鍵字用來(lái)創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊。
無(wú)論是否發(fā)生異常,finally 代碼塊中的代碼總會(huì)被執(zhí)行。
在 finally 代碼塊中,可以運(yùn)行清理類型等收尾善后性質(zhì)的語(yǔ)句。
try{// 程序代碼 }catch(異常類型1 異常的變量名1){// 程序代碼 }catch(異常類型2 異常的變量名2){// 程序代碼 }finally{// 程序代碼 } finally?
實(shí)例
//ExcepTest.javapackage five;import java.*;public class ExcepTest {public static void main(String args[]){try{int a[] = new int[2];System.out.printf("Access element three :%s", a[3]);} catch (ArrayIndexOutOfBoundsException e) {System.out.printf("Exception thrown : %s", e);} finally{System.out.println("Finally.");}} } // Exception thrown : java.lang.ArrayIndexOutOfBoundsException: 3Finally.?
throws/throw 關(guān)鍵字:
如果一個(gè)方法沒(méi)有捕獲一個(gè)檢查性異常,那么該方法必須使用 throws 關(guān)鍵字來(lái)聲明。throws 關(guān)鍵字放在方法簽名的尾部。
也可以使用 throw 關(guān)鍵字拋出一個(gè)異常,無(wú)論它是新實(shí)例化的還是剛捕獲到的。
//testthrow.javapackage five;import java.io.*; import java.rmi.RemoteException;import javax.naming.InsufficientResourcesException;public class testthrow {public void deposit (double amount) throws RemoteException {throw new RemoteException();}public void withdraw (double amount) throws RemoteException, InsufficientResourcesException{// 多個(gè)異常 } }?
聲明自定義異常
在 Java 中你可以自定義異常。編寫自己的異常類時(shí)需要記住下面的幾點(diǎn)。
- 所有異常都必須是 Throwable 的子類。
- 如果希望寫一個(gè)檢查性異常類,則需要繼承 Exception 類。
- 如果你想寫一個(gè)運(yùn)行時(shí)異常類,那么需要繼承 RuntimeException 類。
可以像下面這樣定義自己的異常類:
class MyException extends Exception{ }?
實(shí)例
//MyException.javapackage five;public class MyException extends Exception {private double amont;public MyException(double amount){this.amont = amount;}public double getAmount (){return amont;} } MyException.java //CheckingAccount.javapackage five;public class CheckingAccount {public double balance;private int number;public CheckingAccount(int number){this.number = number;}public void deposit(double amount){balance += amount;}public void withdraw(double amount) throws MyException{if (amount <= balance){balance -= amount;} else {double needs = amount - balance;throw new MyException(needs);}}public double getBalance(){return balance;}public int getNumber(){return number;}} CheckingAccount.java package five;public class BankDemo {public static void main(String[] args){CheckingAccount c = new CheckingAccount(99);c.deposit(66);try{c.withdraw(10);System.out.println("10");c.withdraw(88);} catch (MyException e) {System.out.println("error Myerror " + e);System.out.println("error Myerror " + e.getAmount());e.printStackTrace();}}; }/** 10 error Myerror five.MyException error Myerror 32.0 five.MyExceptionat five.CheckingAccount.withdraw(CheckingAccount.java:22)at five.BankDemo.main(BankDemo.java:10) */ BankDemo.java?
三、java 序列化
Java 提供了一種對(duì)象序列化的機(jī)制,該機(jī)制中,一個(gè)對(duì)象可以被表示為一個(gè)字節(jié)序列,該字節(jié)序列包括該對(duì)象的數(shù)據(jù)、有關(guān)對(duì)象的類型的信息和存儲(chǔ)在對(duì)象中數(shù)據(jù)的類型。
將序列化對(duì)象寫入文件之后,可以從文件中讀取出來(lái),并且對(duì)它進(jìn)行反序列化,也就是說(shuō),對(duì)象的類型信息、對(duì)象的數(shù)據(jù),還有對(duì)象中的數(shù)據(jù)類型可以用來(lái)在內(nèi)存中新建對(duì)象。
整個(gè)過(guò)程都是 Java 虛擬機(jī)(JVM)獨(dú)立的,也就是說(shuō),在一個(gè)平臺(tái)上序列化的對(duì)象可以在另一個(gè)完全不同的平臺(tái)上反序列化該對(duì)象。
類 ObjectInputStream 和 ObjectOutputStream 是高層次的數(shù)據(jù)流,它們包含序列化和反序列化對(duì)象的方法。
ObjectOutputStream 類包含很多寫方法來(lái)寫各種數(shù)據(jù)類型,但是一個(gè)特別的方法例外:
public final void writeObject(Object x) throws IOException上面的方法序列化一個(gè)對(duì)象,并將它發(fā)送到輸出流。相似的 ObjectInputStream 類包含如下反序列化一個(gè)對(duì)象的方法:
public final Object readObject() throws IOException, ClassNotFoundException該方法從流中取出下一個(gè)對(duì)象,并將對(duì)象反序列化。它的返回值為Object,因此,你需要將它轉(zhuǎn)換成合適的數(shù)據(jù)類型。
為了演示序列化在Java中是怎樣工作的,我將使用Employee類,假設(shè)我們定義了如下的Employee類,該類實(shí)現(xiàn)了Serializable 接口。
// Employee.javapublic class Employee implements java.io.Serializable {public String name;public String address;public transient int SSN;public int number;public void mailCheck(){System.out.println("Mailing a check to " + name+ " " + address);} }請(qǐng)注意,一個(gè)類的對(duì)象要想序列化成功,必須滿足兩個(gè)條件:
該類必須實(shí)現(xiàn) java.io.Serializable 對(duì)象。
該類的所有屬性必須是可序列化的。如果有一個(gè)屬性不是可序列化的,則該屬性必須注明是短暫的。
如果你想知道一個(gè) Java 標(biāo)準(zhǔn)類是否是可序列化的,請(qǐng)查看該類的文檔。檢驗(yàn)一個(gè)類的實(shí)例是否能序列化十分簡(jiǎn)單, 只需要查看該類有沒(méi)有實(shí)現(xiàn) java.io.Serializable接口。
?
實(shí)例
序列化對(duì)象
ObjectOutputStream 類用來(lái)序列化一個(gè)對(duì)象,如下的 SerializeDemo 例子實(shí)例化了一個(gè) Employee 對(duì)象,并將該對(duì)象序列化到一個(gè)文件中。
該程序執(zhí)行后,就創(chuàng)建了一個(gè)名為 employee.ser 文件。該程序沒(méi)有任何輸出,但是你可以通過(guò)代碼研讀來(lái)理解程序的作用。
注意:?當(dāng)序列化一個(gè)對(duì)象到文件時(shí), 按照 Java 的標(biāo)準(zhǔn)約定是給文件一個(gè) .ser 擴(kuò)展名。
//SerializeDemo.javapackage five;import java.io.*;public class SerializeDemo {public static void main(String[] args){Employee e = new Employee();e.name = "Nick";e.address = "Beijing";e.SSN = 630571017;e.number = 18;try {FileOutputStream fileOut = new FileOutputStream("F:\\java_project\\employee.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(e);out.close();fileOut.close();System.out.println("enoloyee.ser");} catch (Exception e2) {e2.printStackTrace();}} }?
反序列化對(duì)象
下面的 DeserializeDemo 程序?qū)嵗朔葱蛄谢?#xff0c;/tmp/employee.ser 存儲(chǔ)了 Employee 對(duì)象。
//DeserializeDemo.javapackage five;import java.io.*;public class DeserializeDemo {public static void main(String[] args){Employee e = null;try {FileInputStream fileIn = new FileInputStream("F:\\java_project\\employee.ser");ObjectInputStream in = new ObjectInputStream(fileIn);e = (Employee) in.readObject();in.close();fileIn.close();} catch (IOException i){i.printStackTrace();return;} catch (ClassNotFoundException c) {System.out.println("Employee class not found");c.printStackTrace();return;}System.out.println("Employee.");System.out.println("Name: " + e.name);System.out.println("Address: " + e.address);System.out.println("SSN: " + e.SSN);System.out.println("Number: " + e.number);} }/* Employee. Name: Nick Address: Beijing SSN: 0 Number: 18 */readObject() 方法中的 try/catch代碼塊嘗試捕獲 ClassNotFoundException 異常。對(duì)于 JVM 可以反序列化對(duì)象,它必須是能夠找到字節(jié)碼的類。如果JVM在反序列化對(duì)象的過(guò)程中找不到該類,則拋出一個(gè) ClassNotFoundException 異常。
注意,readObject() 方法的返回值被轉(zhuǎn)化成 Employee 引用。
當(dāng)對(duì)象被序列化時(shí),屬性 SSN 的值為 630571017,但是因?yàn)樵搶傩允嵌虝旱?#xff0c;該值沒(méi)有被發(fā)送到輸出流。所以反序列化后 Employee 對(duì)象的 SSN 屬性為 0。
?
?
四、連接MySQL
Java 連接 MySQL 需要驅(qū)動(dòng)包,最新版下載地址為:http://dev.mysql.com/downloads/connector/j/,解壓后得到j(luò)ar庫(kù)文件,然后在對(duì)應(yīng)的項(xiàng)目中導(dǎo)入該庫(kù)文件。
Eclipse中導(dǎo)入外部jar包:
http://jingyan.baidu.com/article/ca41422fc76c4a1eae99ed9f.html
?
//MySQLDemo.javapackage six;import java.sql.*;public class MySQLDemo {// JDBC 驅(qū)動(dòng)名及數(shù)據(jù)庫(kù) URL(注意冒號(hào),少些一個(gè)讓我找了10分鐘)static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/test";// 數(shù)據(jù)庫(kù)的用戶名與密碼,需要根據(jù)自己的設(shè)置static final String USER = "root";static final String PASS = "suoning";public static void main(String[] args){Connection conn = null;Statement stmt = null;try{// 注冊(cè) JDBC 驅(qū)動(dòng) Class.forName(JDBC_DRIVER);// 打開(kāi)鏈接System.out.println("連接數(shù)據(jù)庫(kù)...");conn = DriverManager.getConnection(DB_URL, USER, PASS);// 執(zhí)行查詢System.out.println("實(shí)例化Statement...");stmt = conn.createStatement();String sql;sql = "SELECT * FROM user";ResultSet rs = stmt.executeQuery(sql);// 展開(kāi)結(jié)果集數(shù)據(jù)庫(kù)while (rs.next()){// 通過(guò)字段檢索int id = rs.getInt("id");String name = rs.getString("name");// 輸出數(shù)據(jù) System.out.print(id);System.out.print(" ");System.out.print(name);System.out.println();}// 完成后關(guān)閉 rs.close();stmt.close();conn.close();} catch (SQLException e){// 處理 JDBC 錯(cuò)誤 e.printStackTrace();} catch (Exception e){// 處理 Class.forName 錯(cuò)誤 e.printStackTrace();} finally{// 關(guān)閉資源try{if(stmt!=null) stmt.close();} catch (SQLException e){}try{if(conn!=null) conn.close();} catch (SQLException e){e.printStackTrace();}}System.out.println("The end.");} }/* 連接數(shù)據(jù)庫(kù)... 實(shí)例化Statement... 1 nick 2 jenny 3 honey The end. */?
五、Socket編程?
網(wǎng)絡(luò)編程是指編寫運(yùn)行在多個(gè)設(shè)備(計(jì)算機(jī))的程序,這些設(shè)備都通過(guò)網(wǎng)絡(luò)連接起來(lái)。
java.net 包中 J2SE 的 API 包含有類和接口,它們提供低層次的通信細(xì)節(jié)。你可以直接使用這些類和接口,來(lái)專注于解決問(wèn)題,而不用關(guān)注通信細(xì)節(jié)。
java.net 包中提供了兩種常見(jiàn)的網(wǎng)絡(luò)協(xié)議的支持:
-
TCP:TCP 是傳輸控制協(xié)議的縮寫,它保障了兩個(gè)應(yīng)用程序之間的可靠通信。通常用于互聯(lián)網(wǎng)協(xié)議,被稱 TCP / IP。
-
UDP:UDP 是用戶數(shù)據(jù)報(bào)協(xié)議的縮寫,一個(gè)無(wú)連接的協(xié)議。提供了應(yīng)用程序之間要發(fā)送的數(shù)據(jù)的數(shù)據(jù)包
?
套接字使用TCP提供了兩臺(tái)計(jì)算機(jī)之間的通信機(jī)制。 客戶端程序創(chuàng)建一個(gè)套接字,并嘗試連接服務(wù)器的套接字。
當(dāng)連接建立時(shí),服務(wù)器會(huì)創(chuàng)建一個(gè) Socket 對(duì)象。客戶端和服務(wù)器現(xiàn)在可以通過(guò)對(duì) Socket 對(duì)象的寫入和讀取來(lái)進(jìn)行進(jìn)行通信。
java.net.Socket 類代表一個(gè)套接字,并且 java.net.ServerSocket 類為服務(wù)器程序提供了一種來(lái)監(jiān)聽(tīng)客戶端,并與他們建立連接的機(jī)制。
以下步驟在兩臺(tái)計(jì)算機(jī)之間使用套接字建立TCP連接時(shí)會(huì)出現(xiàn):
-
服務(wù)器實(shí)例化一個(gè) ServerSocket 對(duì)象,表示通過(guò)服務(wù)器上的端口通信。
-
服務(wù)器調(diào)用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端連接到服務(wù)器上給定的端口。
-
服務(wù)器正在等待時(shí),一個(gè)客戶端實(shí)例化一個(gè) Socket 對(duì)象,指定服務(wù)器名稱和端口號(hào)來(lái)請(qǐng)求連接。
-
Socket 類的構(gòu)造函數(shù)試圖將客戶端連接到指定的服務(wù)器和端口號(hào)。如果通信被建立,則在客戶端創(chuàng)建一個(gè) Socket 對(duì)象能夠與服務(wù)器進(jìn)行通信。
-
在服務(wù)器端,accept() 方法返回服務(wù)器上一個(gè)新的 socket 引用,該 socket 連接到客戶端的 socket。
連接建立后,通過(guò)使用 I/O 流在進(jìn)行通信,每一個(gè)socket都有一個(gè)輸出流和一個(gè)輸入流,客戶端的輸出流連接到服務(wù)器端的輸入流,而客戶端的輸入流連接到服務(wù)器端的輸出流。
TCP 是一個(gè)雙向的通信協(xié)議,因此數(shù)據(jù)可以通過(guò)兩個(gè)數(shù)據(jù)流在同一時(shí)間發(fā)送.以下是一些類提供的一套完整的有用的方法來(lái)實(shí)現(xiàn) socket。
?
ServerSocket 類的方法
服務(wù)器應(yīng)用程序通過(guò)使用 java.net.ServerSocket 類以獲取一個(gè)端口,并且偵聽(tīng)客戶端請(qǐng)求。
ServerSocket 類有四個(gè)構(gòu)造方法:
| 序號(hào) | 方法描述 |
| 1 | public ServerSocket(int port) throws IOException 創(chuàng)建綁定到特定端口的服務(wù)器套接字。 |
| 2 | public ServerSocket(int port, int backlog) throws IOException 利用指定的 backlog 創(chuàng)建服務(wù)器套接字并將其綁定到指定的本地端口號(hào)。 |
| 3 | public ServerSocket(int port, int backlog, InetAddress address) throws IOException 使用指定的端口、偵聽(tīng) backlog 和要綁定到的本地 IP 地址創(chuàng)建服務(wù)器。 |
| 4 | public ServerSocket() throws IOException 創(chuàng)建非綁定服務(wù)器套接字。 |
創(chuàng)建非綁定服務(wù)器套接字。 如果 ServerSocket 構(gòu)造方法沒(méi)有拋出異常,就意味著你的應(yīng)用程序已經(jīng)成功綁定到指定的端口,并且偵聽(tīng)客戶端請(qǐng)求。
這里有一些 ServerSocket 類的常用方法:
| 序號(hào) | 方法描述 |
| 1 | public int getLocalPort() ??返回此套接字在其上偵聽(tīng)的端口。 |
| 2 | public Socket accept() throws IOException 偵聽(tīng)并接受到此套接字的連接。 |
| 3 | public void setSoTimeout(int timeout) ?通過(guò)指定超時(shí)值啟用/禁用 SO_TIMEOUT,以毫秒為單位。 |
| 4 | public void bind(SocketAddress host, int backlog) 將?ServerSocket?綁定到特定地址(IP 地址和端口號(hào))。 |
?
Socket 類的方法
java.net.Socket 類代表客戶端和服務(wù)器都用來(lái)互相溝通的套接字。客戶端要獲取一個(gè) Socket 對(duì)象通過(guò)實(shí)例化 ,而 服務(wù)器獲得一個(gè) Socket 對(duì)象則通過(guò) accept() 方法的返回值。
Socket 類有五個(gè)構(gòu)造方法.
| 序號(hào) | 方法描述 |
| 1 | public Socket(String host, int port) throws UnknownHostException, IOException. 創(chuàng)建一個(gè)流套接字并將其連接到指定主機(jī)上的指定端口號(hào)。 |
| 2 | public Socket(InetAddress host, int port) throws IOException 創(chuàng)建一個(gè)流套接字并將其連接到指定 IP 地址的指定端口號(hào)。 |
| 3 | public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. 創(chuàng)建一個(gè)套接字并將其連接到指定遠(yuǎn)程主機(jī)上的指定遠(yuǎn)程端口。 |
| 4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. 創(chuàng)建一個(gè)套接字并將其連接到指定遠(yuǎn)程地址上的指定遠(yuǎn)程端口。 |
| 5 | public Socket() 通過(guò)系統(tǒng)默認(rèn)類型的 SocketImpl 創(chuàng)建未連接套接字 |
當(dāng) Socket 構(gòu)造方法返回,并沒(méi)有簡(jiǎn)單的實(shí)例化了一個(gè) Socket 對(duì)象,它實(shí)際上會(huì)嘗試連接到指定的服務(wù)器和端口。
下面列出了一些感興趣的方法,注意客戶端和服務(wù)器端都有一個(gè) Socket 對(duì)象,所以無(wú)論客戶端還是服務(wù)端都能夠調(diào)用這些方法。
| 序號(hào) | 方法描述 |
| 1 | public void connect(SocketAddress host, int timeout) throws IOException 將此套接字連接到服務(wù)器,并指定一個(gè)超時(shí)值。 |
| 2 | public InetAddress getInetAddress() ?返回套接字連接的地址。 |
| 3 | public int getPort() 返回此套接字連接到的遠(yuǎn)程端口。 |
| 4 | public int getLocalPort() 返回此套接字綁定到的本地端口。 |
| 5 | public SocketAddress getRemoteSocketAddress() 返回此套接字連接的端點(diǎn)的地址,如果未連接則返回?null。 |
| 6 | public InputStream getInputStream() throws IOException 返回此套接字的輸入流。 |
| 7 | public OutputStream getOutputStream() throws IOException 返回此套接字的輸出流。 |
| 8 | public void close() throws IOException 關(guān)閉此套接字。 |
?
InetAddress 類的方法
這個(gè)類表示互聯(lián)網(wǎng)協(xié)議(IP)地址。下面列出了 Socket 編程時(shí)比較有用的方法:
| 序號(hào) | 方法描述 |
| 1 | static InetAddress getByAddress(byte[] addr) 在給定原始 IP 地址的情況下,返回?InetAddress?對(duì)象。 |
| 2 | static InetAddress getByAddress(String host, byte[] addr) 根據(jù)提供的主機(jī)名和 IP 地址創(chuàng)建 InetAddress。 |
| 3 | static InetAddress getByName(String host) 在給定主機(jī)名的情況下確定主機(jī)的 IP 地址。 |
| 4 | String getHostAddress()? 返回 IP 地址字符串(以文本表現(xiàn)形式)。 |
| 5 | String getHostName()? ?獲取此 IP 地址的主機(jī)名。 |
| 6 | static InetAddress getLocalHost() 返回本地主機(jī)。 |
| 7 | String toString() 將此 IP 地址轉(zhuǎn)換為?String。 |
?
?實(shí)例
Socket 服務(wù)端實(shí)例:
//GreetingServer.javapackage seven;import java.net.*; import java.io.*;public class GreetingServer extends Thread {private ServerSocket serverSocket;public GreetingServer(int port) throws IOException{serverSocket = new ServerSocket(port);serverSocket.setSoTimeout(9999);}public void run(){while(true){try{System.out.println("Wating for you ..." + serverSocket.getLocalPort());Socket server = serverSocket.accept();System.out.println("connected " + server.getRemoteSocketAddress());DataInputStream in = new DataInputStream(server.getInputStream());System.out.println(in.readUTF());DataOutputStream out = new DataOutputStream(server.getOutputStream());out.writeUTF("The end....." + server.getLocalSocketAddress());server.close();} catch(SocketTimeoutException e){System.out.println("Time out error.");break;} catch(IOException e){e.printStackTrace();break;}}}public static void main(String[] args){int port = Integer.parseInt(args[0]);try {Thread t = new GreetingServer(port);t.start();} catch (IOException e) {e.printStackTrace();}}}?
Socket 客戶端實(shí)例:
//GreetingClient.javapackage seven;import java.net.*; import java.io.*;public class GreetingClient {public static void main(String[] args){String serverName = args[0];int port = Integer.parseInt(args[1]);try {System.out.println(serverName + " " + port);Socket client = new Socket(serverName, port);System.out.println(client.getRemoteSocketAddress());OutputStream outToServer = client.getOutputStream();DataOutputStream out = new DataOutputStream(outToServer);out.writeUTF("S" + client.getLocalSocketAddress());InputStream inFormServer = client.getInputStream();DataInputStream in = new DataInputStream(inFormServer);System.out.println("s" + in.readUTF());client.close();} catch (IOException e) {e.printStackTrace();}}}?
?
轉(zhuǎn)載于:https://www.cnblogs.com/suoning/p/6243163.html
總結(jié)
以上是生活随笔為你收集整理的一起学 Java(四) File、Try 、序列化、MySQL、Socket的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: js字符串与数组的处理
- 下一篇: struts2常用标签