1. File類
File類在java中表示(帶路徑的)文件或者目錄
1).File常用屬性和方法
1 public static void main(String[] args) { 2 3 4 5 // 給定路徑創建File對象 6 7 // File file = new File("D:"+File.separator+"javatest"+File.separator+"a.txt"); 8 9 File file = new File("d:\\javatest\\b.mp3"); 10 11 System.out.println(file); 12 13 14 15 // 文件基本屬性 16 17 System.out.println(file.canExecute()); 18 19 System.out.println(file.canRead()); 20 21 System.out.println(file.canWrite()); 22 23 24 25 // 文件的創建、刪除 26 27 if(!file.exists()) { 28 29 30 31 booleanr; 32 33 try { 34 35 r = file.createNewFile(); 36 37 if(r) { 38 39 System.out.println("文件創建成功"); 40 41 } 42 43 } catch (IOExceptione) { 44 45 e.printStackTrace(); 46 47 } 48 49 } 50 51 52 53 // 刪除文件 54 55 file.delete(); 56 57 }
創建文件時會拋出檢查時異常IOException
2).File的路徑相關
1 public static void main(String[] args) { 2 3 4 5 File file = new File("d:\\javatest\\a"); 6 7 // File file = new File("a.txt"); 8 9 10 11 // 獲取file的絕對路徑 12 13 System.out.println(file.getAbsolutePath()); 14 15 // 獲取file的創建時的路徑字符串 16 17 System.out.println(file.getPath()); 18 19 // 獲取文件或者目錄的名字 20 21 System.out.println(file.getName()); 22 23 // 獲取文件或者目錄的父目錄 24 25 System.out.println(file.getParent()); 26 27 28 29 }
注意:如果file是相對路徑,相對路徑的當前路徑是工程目錄(java17)
3). 目錄的創建
1 public static void main(String[] args) { 2 3 4 5 File file = new File("d:\\javatest\\c\\d\\e"); 6 7 8 9 if(!file.exists()) { 10 11 booleanr; 12 13 14 15 try { 16 17 // 一次只能創建一個目錄 18 19 // r = file.mkdir(); 20 21 r = file.mkdirs(); 22 23 if(r) { 24 25 System.out.println("目錄創建成功"); 26 27 } 28 29 } catch (Exception e) { 30 31 e.printStackTrace(); 32 33 } 34 35 36 37 } 38 39 }
4).目錄的遍歷
list():返回一個file表示的目錄中的子目錄或者文件,字符串數組類型
listFiles():返回一個file表示的目錄中的子目錄或者文件,File數組類型
1 public static void main(String[] args) { 2 3 4 5 // 需求:遍歷d:\javatest目錄 6 7 // list() 8 9 Filefile= newFile("d:\\javatest"); 10 11 12 13 14 15 /* 16 17 String[] list = file.list(); 18 19 20 21 for (String str : list) { 22 23 System.out.print(str); 24 25 File f = new File(file.getPath()+"\\"+str); 26 27 if(f.isDirectory()) { 28 29 System.out.println(" 目錄"); 30 31 }else { 32 33 System.out.println(" 文件"); 34 35 } 36 37 }*/ 38 39 40 41 42 43 // listFiles(); 44 45 File[] listFiles = file.listFiles(); 46 47 for (Filef :listFiles) { 48 49 System.out.print(f.getName()); 50 51 if(f.isDirectory()) { 52 53 System.out.println(" 目錄"); 54 55 }else { 56 57 System.out.println(" 文件"); 58 59 } 60 61 } 62 63 }
2. IO流
1). 流
流(stream):流是一連串流動的數據(字節、字符),以先進先出的方式發送的信息的通道中。
2). 輸入流和輸出流
輸入流
數據從源數據源流入程序的過程稱為輸入流。可以理解為從源數據源讀取數據到程序的過程
![]()
|
輸出流
數據從程序流出到目的地的過程稱為輸出流。可以理解為把數據從程序寫入目的地的過程
![]()
|
注:數據源一般指提供數據的原始媒介,一般常見有文件、數據庫、雲端、其他硬件等能提供數據的媒介。
3). 流的分類
按照流向分為輸入流和輸出流
按照處理單元分為字節流和字符流
按照功能分為節點流和轉換流。
![]()
|
3 . InputStream/OutputStream
InputStream 是所有字節輸入流的抽象父類,提供了
read 讀取一個字節
read(byte[] buf) 讀取一定量的字節到緩沖區數組buf中。
OutputStream 是所有字節輸出流的抽象父類,提供了
write() 寫入一個字節
write(byte[] buf) 寫入一定量的字節到輸出流
FileInputStream文件字節輸入流,專門用於從文件中讀取字節到程序內存中。
FileOutputStream文件字節輸出流,專門用於從內存中寫入字節到文件中。
需求:從文件讀取一個字節
1 public static void main(String[] args) { 2 3 4 5 // 需求:讀取一個文件中的一個字節 6 7 File file = new File("d:\\javatest\\a.txt"); 8 9 10 11 // 【1】創建管道 12 13 FileInputStreamin = null; 14 15 16 17 try { 18 19 in = newFileInputStream(file); 20 21 22 23 // 【2】從管道讀取一個字節 24 25 /* 26 27 int t; 28 29 t = in.read(); 30 31 t = in.read(); 32 33 t = in.read(); 34 35 t = in.read(); 36 37 */ 38 39 // System.out.println(t); 40 41 42 43 // 循環讀取一個字節 44 45 intt; 46 47 StringBuildersb = newStringBuilder(); 48 49 while( (t=in.read()) != -1 ) { 50 51 sb.append((char)t); 52 53 } 54 55 56 57 System.out.println(sb.toString()); 58 59 60 61 62 63 64 65 } catch (FileNotFoundExceptione) { 66 67 e.printStackTrace(); 68 69 } catch(IOExceptione) { 70 71 e.printStackTrace(); 72 73 } 74 75 76 77 // 【3】關閉流管道 78 79 try { 80 81 in.close(); 82 83 } catch (IOExceptione) { 84 85 e.printStackTrace(); 86 87 } 88 89 }
一次讀取多個字節
1 public static void main(String[] args) { 2 3 4 5 // 需求:一次讀取多個字節 6 7 File file = new File("d:\\javatest\\a.txt"); 8 9 10 11 // 【1】創建管道 12 13 FileInputStreamin = null; 14 15 16 17 try { 18 19 in = newFileInputStream(file); 20 21 22 23 // 【2】從管道讀取多個字節到緩沖區 24 25 /* 26 27 byte[] buf = new byte[5]; 28 29 intlen; 30 31 len = in.read(buf); 32 33 len = in.read(buf); 34 35 len = in.read(buf); 36 37 len = in.read(buf); 38 39 40 41 for(byte b:buf) { 42 43 System.out.print((char)b+"\t"); 44 45 } 46 47 System.out.println(len); 48 49 */ 50 51 52 53 // 通過循環讀取文件 54 55 byte[] buf = newbyte[5]; 56 57 intlen; 58 59 StringBuildersb = newStringBuilder(); 60 61 while( (len=in.read(buf)) != -1 ) { 62 63 // 讀取的內容是原始二進制流,需要根據編碼的字符集解碼成對於字符 64 65 String str = new String(buf,0,len); 66 67 sb.append(str); 68 69 } 70 71 System.out.println(sb.toString()); 72 73 74 75 76 77 78 79 80 81 } catch (FileNotFoundExceptione) { 82 83 e.printStackTrace(); 84 85 } catch(IOExceptione) { 86 87 e.printStackTrace(); 88 89 } 90 91 92 93 // 【3】關閉流管道 94 95 try { 96 97 in.close(); 98 99 } catch (IOExceptione) { 100 101 e.printStackTrace(); 102 103 } 104 105 }
需求:按照指定編碼寫入文件
1 public static void main(String[] args) { 2 3 4 5 6 7 File file = new File("d:\\javatest\\c.txt"); 8 9 10 11 FileOutputStreamout = null; 12 13 14 15 try { 16 17 // 【1】創建輸出流管道 18 19 out = newFileOutputStream(file); 20 21 22 23 // 【2】寫入數據到管道中 24 25 // 一次寫入一個字節 26 27 /* 28 29 out.write(97); 30 31 out.write(98); 32 33 out.write(99); 34 35 */ 36 37 38 39 // 一次寫入多個字節 40 41 String str = "hello world"; 42 43 // gbk 44 45 /* 46 47 byte[] buf = str.getBytes(); 48 49 out.write(buf); 50 51 */ 52 53 54 55 byte[] buf = str.getBytes("UTF-8"); 56 57 out.write(buf); 58 59 60 61 System.out.println("寫入完成!"); 62 63 64 65 } catch (FileNotFoundExceptione) { 66 67 e.printStackTrace(); 68 69 } catch (IOExceptione) { 70 71 e.printStackTrace(); 72 73 } 74 75 76 77 // 【3】關閉流 78 79 try { 80 81 out.close(); 82 83 } catch (IOExceptione) { 84 85 e.printStackTrace(); 86 87 } 88 89 }
注意:
[1]字符串寫入文件時一定會存在編碼問題
[2]使用utf8編碼寫入文件時,如果不含中文時,win系統會對文件的編碼造成誤判。
[3]通過字節流寫入文件時,向管道寫入一個字節,該字節立即寫入文件中。
總結
InputStream/OutputStream用於字節的讀寫。主要用於讀取二進制文件(圖片、音頻、視頻),也可以讀取文件性文件。
需求:請把d:\\javatest\\logo.png 復制到工程目錄中,並顯示復制進度。
public static void main(String[] args) throwsFileNotFoundException,IOException { File oriFile = new File("d:\\javatest\\logo.jpg"); File toFile = new File("logo.jpg"); longtotalLen = oriFile.length(); // 文件大小 longcpyedLen = 0; // 已復制完成的大小 floatprogress = 0.0f; FileInputStreamin = newFileInputStream(oriFile); FileOutputStreamout = newFileOutputStream(toFile); // 一次讀取1kb byte[] buf = newbyte[512]; intlen; while( (len=in.read(buf)) != -1) { out.write(buf, 0, len); cpyedLen += len; progress = cpyedLen*1.0f/totalLen; System.out.println(progress); } in.close(); out.close(); System.out.println("復制完成!"); }
4.Reader/Writer
Reader 是字符輸入流的抽象父類,提供了
read一次讀取一個字符
read(char[] cbuf)一次讀取多個字符到字符緩沖區cbuf,返回長度表示讀取的字符個數。
Writer是字符輸出流的抽象父類,提供了
write
write(char[] cbuf)
write(string)
FileReader文件字符輸入流,專門用於讀取默認字符編碼文本性文件。
FileWriter文件字符輸出流,專門用於寫入默認字符編碼的文本性文件。為了提高效率,FileWriter內部存在一個字節緩沖區,用於對待寫入的字符進行統一編碼到字節緩沖區,一定要在關閉流之前,調用flush方法刷新緩沖區。
需求:一次讀取一個字符/多個字符到cbuf
1 public static void main(String[] args) throwsIOException { 2 3 4 5 File file = new File("d:\\javatest\\d.txt"); 6 7 8 9 FileReaderreader = newFileReader(file); 10 11 12 13 // 【1】一次讀取一個字符 14 15 /* 16 17 int c; 18 19 c = reader.read(); 20 21 c = reader.read(); 22 23 c = reader.read(); 24 25 c = reader.read(); 26 27 c = reader.read(); 28 29 System.out.println((char)c); 30 31 */ 32 33 34 35 // 【2】一次讀取多個字符到cbuf中 36 37 /* 38 39 char[] cbuf = new char[2]; 40 41 intlen; 42 43 len = reader.read(cbuf); 44 45 len = reader.read(cbuf); 46 47 len = reader.read(cbuf); 48 49 len = reader.read(cbuf); 50 51 System.out.println(Arrays.toString(cbuf)); 52 53 System.out.println(len); 54 55 */ 56 57 58 59 char[] cbuf = newchar[2]; 60 61 intlen; 62 63 StringBuildersb = newStringBuilder(); 64 65 while( (len=reader.read(cbuf)) != -1 ) { 66 67 sb.append(cbuf,0,len); 68 69 } 70 71 72 73 System.out.println(sb); 74 75 }
需求:寫入字符到文件中
1 public static void main(String[] args) throwsIOException { 2 3 4 5 6 7 File file = new File("d:\\javatest\\f.txt"); 8 9 10 11 FileWriterwriter = newFileWriter(file); 12 13 14 15 // 【1】一次寫入一個字符 16 17 /*writer.write('中'); 18 19 writer.write('國');*/ 20 21 22 23 // 【2】一次寫入多個字符 24 25 /*char[] cbuf = {'h','e','l','l','o','中','國'}; 26 27 writer.write(cbuf);*/ 28 29 30 31 // 【3】一次寫入一個字符串 32 33 String str = "hello你好"; 34 35 writer.write(str); 36 37 38 39 40 41 // 刷新字節緩沖區 42 43 writer.flush(); 44 45 46 47 // 關閉流通道 48 49 writer.close(); 50 51 52 53 System.out.println("寫入完成"); 54 55 }
5. 轉換流
InputStreamReader繼承於Reader,是字節流通向字符流的橋梁,可以把字節流按照指定編碼解碼成字符流。
OutputStreamWriter繼承於Writer,是字符流通向字節流的橋梁,可以把字符流按照指定的編碼編碼成字節流。
1.5.1 轉換流工作原理
![]()
|
需求:寫入utf8文件
1 /** 2 3 * 把一個字符串以utf8編碼寫入文件 4 5 */ 6 7 publicclass Test01 { 8 9 public static void main(String[] args) throwsIOException { 10 11 12 13 14 15 String str = "hello中國"; 16 17 File file = new File("d:\\javatest\\g.txt"); 18 19 20 21 // 【1】創建管道 22 23 FileOutputStreamout = newFileOutputStream(file); 24 25 OutputStreamWriterwriter = newOutputStreamWriter(out, "utf8"); 26 27 28 29 // 【2】寫入管道 30 31 writer.write(str); 32 33 34 35 // 【3】刷新緩沖區 36 37 writer.flush(); 38 39 40 41 // 【4】關閉管道 42 43 out.close(); 44 45 writer.close(); 46 47 48 49 System.out.println("寫入完成"); 50 51 } 52 53 }
需求:讀取utf8文件
1 /** 2 3 * 讀取utf8編碼的文本文件 4 5 */ 6 7 public class Test01 { 8 9 public static void main(String[] args) throwsIOException { 10 11 12 13 File file = new File("d:\\javatest\\g.txt"); 14 15 16 17 // 【1】建立管道 18 19 FileInputStreamin = newFileInputStream(file); 20 21 InputStreamReaderreader = newInputStreamReader(in, "UTF-8"); 22 23 24 25 char[] cbuf = newchar[2]; 26 27 intlen; 28 29 30 31 StringBuildersb = newStringBuilder(); 32 33 while( (len=reader.read(cbuf))!=-1 ) { 34 35 sb.append(cbuf, 0, len); 36 37 } 38 39 System.out.println(sb.toString()); 40 41 42 43 } 44 45 }
注意:
[1]win平台默認的utf8編碼的文本性文件帶有BOM,java轉換流寫入的utf8文件不帶BOM。所以用java讀取手動創建的utf8文件會出現一點亂碼(?hello中國,?是bom導致的)《詳情見下篇文章》
[2]一句話:用字符集編碼,一定用字符集解碼!!
總結:
FileReader = InputStreamReader + GBK
1 packagecn.sxt07.outputstreamwriter; 2 3 4 5 importjava.io.File; 6 7 importjava.io.FileInputStream; 8 9 importjava.io.FileReader; 10 11 importjava.io.IOException; 12 13 importjava.io.InputStreamReader; 14 15 16 17 /** 18 19 * 讀取一個gbk編碼的文本性文件 20 21 */ 22 23 publicclass Test02 { 24 25 public static void main(String[] args) throwsIOException { 26 27 28 29 30 31 File file = new File("d:\\javatest\\f.txt"); 32 33 34 35 // 【1】建立管道 36 37 /* 38 39 * FileInputStream in = new FileInputStream(file); 40 41 * InputStreamReader reader = newInputStreamReader(in, "GBK"); 42 43 */ 44 45 46 47 FileReaderreader = newFileReader(file); 48 49 50 51 char[] cbuf = newchar[2]; 52 53 intlen; 54 55 56 57 StringBuildersb = newStringBuilder(); 58 59 while( (len=reader.read(cbuf))!=-1 ) { 60 61 sb.append(cbuf, 0, len); 62 63 } 64 65 66 67 reader.close(); 68 69 70 71 System.out.println(sb.toString()); 72 73 } 74 75 }
6. BufferedReader/BufferedWriter
BufferedReader繼承於Reader,提供了
read
read(char[] cbuf)
readLine() 用於讀取一行文本,實現對文本的高效讀取。
BufferedReader初始化時需要一個reader,本質上BufferedReader在reader的基礎上增加readLine()的功能。
BufferedWriter繼承於Writer,提供了
write
write(char[] cbuf)
write(string)
newLine() 寫入一個行分隔符。
需求:讀取一首詩
1 public static void main(String[] args) throwsIOException { 2 3 4 5 // 按行讀取gbk文本性文件 6 7 8 9 File file = new File("d:\\javatest\\i.txt"); 10 11 12 13 // 【1】創建管道 14 15 FileReaderreader = newFileReader(file); 16 17 BufferedReaderbr = newBufferedReader(reader); 18 19 20 21 // 【2】讀取一行 22 23 /* 24 25 String line = br.readLine(); 26 27 line = br.readLine(); 28 29 line = br.readLine(); 30 31 line = br.readLine(); 32 33 */ 34 35 36 37 String line; 38 39 while( (line=br.readLine()) != null) { 40 41 System.out.println(line); 42 43 } 44 45 }
需求:以gbk編碼寫入一首詩到文件
1 public static void main(String[] args) throwsIOException { 2 3 4 5 File file = new File("d:\\javatest\\j.txt"); 6 7 8 9 // 【1】創建gbk管道 10 11 FileWriterwriter = newFileWriter(file); 12 13 BufferedWriterbw = newBufferedWriter(writer); 14 15 16 17 // 【2】寫入一行 18 19 bw.write("窗前明月光,"); 20 21 bw.newLine(); 22 23 24 25 bw.write("疑似地上霜。"); 26 27 28 29 // for win 30 31 // bw.write("\r\n"); 32 33 34 35 // for unix/linux/mac 36 37 // bw.write("\n"); 38 39 40 41 bw.write("舉頭望明月,"); 42 43 bw.newLine(); 44 45 46 47 // 【3】flush 48 49 bw.flush(); 50 51 52 53 // 【4】關閉管道 54 55 bw.close(); 56 57 writer.close(); 58 59 }
需求:以utf8編碼高效寫入文件
1 /** 2 3 * 以utf8寫入一首詩 4 5 * @author Administrator 6 7 * 8 9 */ 10 11 public class Test02 { 12 13 public static void main(String[] args) throwsIOException { 14 15 16 17 File file = new File("d:\\javatest\\j-utf8.txt"); 18 19 20 21 // 【1】創建utf8管道 22 23 FileOutputStream out = newFileOutputStream(file); 24 25 OutputStreamWriter writer = newOutputStreamWriter(out, "UTF-8"); 26 27 BufferedWriter bw = newBufferedWriter(writer); 28 29 30 31 // 【2】寫入一行 32 33 bw.write("窗前明月光,"); 34 35 bw.newLine(); 36 37 38 39 bw.write("疑似地上霜。"); 40 41 42 43 // for win 44 45 bw.write("\r\n"); 46 47 48 49 // for unix/linux/mac 50 51 // bw.write("\n"); 52 53 54 55 bw.write("舉頭望明月,"); 56 57 bw.newLine(); 58 59 60 61 // 【3】flush 62 63 bw.flush(); 64 65 66 67 // 【4】關閉管道 68 69 bw.close(); 70 out.close(); 71 writer.close(); 72 73 } 74 75 }
需求:以utf-8編碼高效讀取文件
1 package bufferedreader; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileInputStream; 7 import java.io.FileNotFoundException; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.io.InputStreamReader; 11 import java.io.OutputStreamWriter; 12 13 //以utf-8讀取一首詩 14 public class Test01 { 15 public static void main(String[]args) throws FileNotFoundException,IOException{ 16 File file=new File("f:\\javatest\\f.txt"); 17 18 FileInputStream in=new FileInputStream(file); 19 InputStreamReader reader=new InputStreamReader(in,"utf-8"); 20 BufferedReader br=new BufferedReader(reader); 21 22 String line; 23 while( (line=br.readLine())!=null){ 24 System.out.println(line); 25 } 26 27 28 in.close(); 29 reader.close(); 30 br.close(); 31 32 33 } 34 }
7. 標准輸入輸出流
1) 標准輸入流
源數據源是標准輸入設備(鍵盤、鼠標、觸摸屏)等輸入設備。在java中用System.in 得到一個InputStream字節輸入流。
需求:在控制台輸入一句話,然后原樣輸出
1 public static void main(String[] args) throws IOException { 2 3 // 需求:輸入一句話,然原樣輸出 4 5 InputStream in = System.in; 6 7 8 9 byte[] buf = newbyte[1024]; 10 11 intlen; 12 13 // buf中包含回車和換行 14 15 len = in.read(buf); 16 17 18 19 String str = new String(buf, 0, len); 20 21 // System.out.println(Arrays.toString(buf)); 22 23 System.out.println(str); 24 25 }
注意:
標准輸入流以字節流流入內存,如果在控制台中輸入字符,字符以默認編碼(win簡體:gbk)編碼成字節進入標准輸入流。
1 public static void main(String[] args) throws IOException { 2 3 // 需求:從控制台高效讀取一行數據。把一首詩寫入文件。 4 5 6 7 InputStream in = System.in; 8 9 InputStreamReader reader = new InputStreamReader(in, "GBK"); 10 11 BufferedReader br = new BufferedReader(reader); 12 13 14 15 File file = new File("d:\\javatest\\k.txt"); 16 17 FileWriter writer = new FileWriter(file); 18 19 BufferedWriter bw = new BufferedWriter(writer); 20 21 22 23 String end = "bye"; 24 25 while(true) { 26 27 String line = br.readLine(); 28 29 if(line.equals(end)) { 30 31 break; 32 33 } 34 35 36 37 bw.write(line); 38 39 // bw.newLine(); 40 41 } 42 43 44 45 bw.flush(); 46 47 48 49 bw.close(); 50 51 writer.close(); 52 53 54 55 }
2) 標准輸出流(PrintStream)
數據目的地是標准輸出設備(顯示器)等輸出設備。在java中用System.out得到一個PrintStream 字節輸出流(字節打印流)。提供了更強大的
println
打印方法用於打印各種數據類型。
需求:讀取文件,顯示到標准輸出設備
1 public static void main(String[] args) throws IOException { 2 3 4 5 Filefile = new File("d:\\javatest\\k.txt"); 6 7 8 9 FileReader reader = new FileReader(file); 10 11 BufferedReader br = new BufferedReader(reader); 12 13 14 15 PrintStreamps = System.out; 16 17 18 19 String line; 20 21 while( (line=br.readLine())!=null ) { 22 23 ps.println(line); 24 25 } 26 27 }
PrintStream 打印的所有字符都使用平台的默認字符編碼轉換為字節。
1 public static void main(String[] args) throws IOException { 2 3 4 5 6 7 String str = "hello中國"; 8 9 byte[] buf = str.getBytes("utf-8"); 10 11 12 13 PrintStream ps = System.out; 14 15 ps.write(buf); 16 17 18 19 }
8. 字符打印流PrintWriter
PrintWriter繼承Writer
數據目的地是標准輸出設備(顯示器)等輸出設備。在java中用System.out得到一個PrintSWriter 字符輸出流(字符打印流)。提供了更強大的
println
writer(String str)
打印方法用於打印各種數據類型。
9. Scanner
通過scanner掃描文件、字節流等
1 public static void main(String[] args) throws IOException { 2 3 4 5 // 掃描平台默認編碼的文件 6 7 /*File file = new File("d:\\javatest\\j.txt"); 8 9 Scanner sc = new Scanner(file); 10 11 */ 12 13 14 15 // 掃描指定編碼的文件 16 17 Scanner sc = new Scanner(new FileInputStream(new File("d:\\javatest\\j-utf8.txt")), "UTF-8"); 18 19 20 21 String line; 22 23 while (sc.hasNextLine()) { 24 25 line = sc.nextLine(); 26 27 System.out.println(line); 28 29 } 30 31 32 33 }
10. 序列化
把內存中的對象永久保存到硬盤的過程稱為對象序列化,也叫做持久化。
把硬盤持久化的內存恢復的內存的過程稱為對象反序列化。
1) Serializable
類通過實現 java.io.Serializable 接口以啟用其序列化功能。未實現此接口的類將無法使其任何狀態序列化或反序列化,並拋出異常
Exception in thread "main" java.io.NotSerializableException: cn.sxt05.serializable.Student at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) at cn.sxt05.serializable.Test01.main(Test01.java:22) |
Serializable接口沒有方法或字段,僅用於標識可序列化的語義
public class Student implements Serializable{ // 。。。 |
2) 序列化對象
ObjectOutputStream繼承於OutputStream,專門用於把對象序列化到本地。提供了
writeXXX
writeObject() 用於寫入一個對象
1 public static void main(String[] args) throws IOException { 2 3 4 5 Studentstu = new Student("001", "大狗", 20, Gender.男); 6 7 8 9 /** 10 11 * 方案1:取stu所有的屬性,通過特定的字符串(-),把各個屬性值連接起來 12 13 * 001-大狗-20-男 14 15 */ 16 17 18 19 File file = new File("d:\\javatest\\l.txt"); 20 21 FileOutputStream out = new FileOutputStream(file); 22 23 ObjectOutputStream oos = new ObjectOutputStream(out); 24 25 26 27 oos.writeObject(stu); 28 29 30 31 oos.close(); 32 33 out.close(); 34 35 }
3) 反序列化對象
ObjectInputStream繼承於InputStream ,專門用於把本地持久化內容反序列化到內存,提供了
readXXX
readObject() 用於讀取一個序列化內容並返回一個對象。
1 public static void main(String[] args) throws IOException, ClassNotFoundException { 2 3 4 5 File file = new File("d:\\javatest\\l.txt"); 6 7 8 9 10 11 FileInputStream in = new FileInputStream(file); 12 13 ObjectInputStreamois = newObjectInputStream(in); 14 15 16 17 Student student = (Student) ois.readObject(); 18 19 System.out.println(student.getId()); 20 21 System.out.println(student.getName()); 22 23 System.out.println(student.getAge()); 24 25 System.out.println(student.getGender()); 26 27 28 29 ois.close(); 30 31 in.close(); 32 33 }
4) 序列化版本
當序列化完成后,后期升級程序中的類(Student),此時再反序列化時會出現異常。
Exception in thread "main" java.io.InvalidClassException: cn.sxt05.serializable.Student; local class incompatible: stream classdesc serialVersionUID = -6288733824962181189, local class serialVersionUID = 1690603786167234505 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1876) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1745) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427) at cn.sxt05.serializable.Test02.main(Test02.java:16) |
異常原因:序列化流的serialVersionUID和升級后類的版本不匹配。
解決方案:給Student類加序列化版本號,有兩種方式
![]()
|
default serial version ID 生成默認的serial version ID 一般值都是1L。
generatedserialversion ID根據當前類的屬性、方法生成一個唯一ID。
public class Student implements Serializable { private static final long serialVersionUID = -1003763572517930507L;
5) transient
開發過程中,如果想忽略某些字段不讓其序列化時,可以使用transient修飾。
1 public class Student implements Serializable { 2 3 4 5 private static final long serialVersionUID = 7222966748321328300L; 6 7 8 9 private String id; 10 11 private transient String name; 12 13 private transient int age; 14 15 private Gender gender; 16 17 private String phone;
11. DataInputStream/DataOutputStream
DataOutputStream 繼承OutputStream,專門用於把基本java數據類型寫入輸出流。提供了writeXXX 寫入基本java數據類型。
DataInputStream繼承於InputStream,允許應用程序以與機器無關方式從底層輸入流中讀取基本 Java 數據類型。
DataInputStream/DataOutputStream特別適合讀取/寫入在網絡傳輸過程中的數據流。
寫入基本java數據類型
1 public static void main(String[] args) throws IOException { 2 3 4 5 File file = new File("d:\\javatest\\n.txt"); 6 7 FileOutputStream out= new FileOutputStream(file); 8 9 DataOutputStreamdos = newDataOutputStream(out); 10 11 12 13 dos.writeInt(10); 14 15 dos.writeUTF("hello中國"); 16 17 18 19 dos.close(); 20 21 out.close(); 22 23 24 25 System.out.println("寫入完成"); 26 27 28 29 }
讀取基本java數據類型
1 public static void main(String[] args) throws IOException { 2 3 4 5 File file = new File("d:\\javatest\\n.txt"); 6 7 FileInputStream in = new FileInputStream(file); 8 9 DataInputStream dis = new DataInputStream(in); 10 11 12 13 inta = dis.readInt(); 14 15 String str = dis.readUTF(); 16 17 18 19 System.out.println(a); 20 21 System.out.println(str); 22 23 24 25 }
注意:
以什么順序寫入基本java數據類型,就以什么順序讀取基本java數據類型。