上海 網(wǎng)站建設 500強關鍵詞搜索優(yōu)化外包
?、File類
概念:代表物理盤符中的?個?件或者?件夾。
常見方法:
方法名 | 描述 |
createNewFile() | 創(chuàng)建?個新文件。 |
mkdir() | 創(chuàng)建?個新?錄。 |
delete() | 刪除?件或空?錄。 |
exists() | 判斷File對象所對象所代表的對象是否存在。 |
getAbsolutePath() | 獲取?件的絕對路徑。 |
getName() | 取得名字。 |
getParent() | 獲取?件/?錄所在的?錄。 |
isDirectory() | 是否是?錄。 |
isFile() | 是否是?件。 |
length() | 獲得?件的?度。 |
listFiles() | 列出?錄中的所有內容 |
示例:
//?件的相關操作
File f = new File("d:/aaa/bbb.java");
System.out.println("?件絕對路徑:"+f.getAbsolutePath());
System.out.println("?件構造路徑:"+f.getPath());
System.out.println("?件名稱:"+f.getName());
System.out.println("?件?度:"+f.length()+"字節(jié)");//創(chuàng)建?件 createNewFile()
File file=new File("d:\\file.txt");
//System.out.println(file.toString());
if(!file.exists()) {boolean b=file.createNewFile();System.out.println("創(chuàng)建結果:"+b);
}
System.out.println("是否時?件:"+file.isFile());//?件夾的相關操作
File f2 = new File("d:/aaa");
System.out.println("?錄絕對路徑:"+f2.getAbsolutePath());
System.out.println("?錄構造路徑:"+f2.getPath());
System.out.println("?錄名稱:"+f2.getName());
System.out.println("?錄?度:"+f2.length());//遍歷?件夾
File dir2=new File("d:\\圖?");
String[] files=dir2.list();
System.out.println("--------------------------------");
for (String string : files) {System.out.println(string);
}
FileFilter接口
FileFilter:?件過濾器接?
boolean accept(File pathname)。
當調?File類中的listFiles()?法時,?持傳?FileFilter接?接?實現(xiàn)類,對獲取?件進?過濾,只有滿足條件的?件的才可出現(xiàn)在listFiles()的返回值中。
示例:
public class DiGuiDemo {public static void main(String[] args) {File f = new File("d:\\QF\\test");printDir(dir);}public static void printDir(File dir) {// 匿名內部類?式,創(chuàng)建過濾器?類對象File[] files = dir.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {return pathname.getName().endsWith(".java")||pathname.isDirectory();}});// 循環(huán)打印for (File file : files) {if (file.isFile()) {System.out.println("?件名:" + file.getAbsolutePath());} else {printDir2(file);}}}
}
?、什么是IO
?活中,你肯定經(jīng)歷過這樣的場景。當你編輯?個?本?件,忘記了ctrl+s ,可能?件就??編輯了。當你電腦上插??個U盤,可以把?個視頻,拷?到你的電腦硬盤?。那么數(shù)據(jù)都是在哪些設備上的呢?鍵盤、內存、硬盤、外接設備等等。
我們把這種數(shù)據(jù)的傳輸,可以看做是?種數(shù)據(jù)的流動,按照流動的?向,以內存為基準,分為輸?input 和輸出output ,即流向內存是輸?流,流出內存的輸出流。
Java中I/O操作主要是指使?java.io包下的內容,進?輸?、輸出操作。輸?也叫做讀取數(shù)據(jù),輸出也叫做作寫出數(shù)據(jù)。
三、IO分類
按照流的流向分,可以分為輸入流和輸出流;
按照操作單元劃分,可以劃分為字節(jié)流和字符流;
按照流的角色劃分為節(jié)點流和處理流。
Java Io流共涉及40多個類,這些類看上去很雜亂,但實際上很有規(guī)則,而且彼此之間存在非常緊密的聯(lián)系,
Java I0流的40多個類都是從如下4個抽象類基類中派生出來的。
InputStream/Reader: 所有的輸入流的基類,前者是字節(jié)輸入流,后者是字符輸入流。
OutputStream/Writer: 所有輸出流的基類,前者是字節(jié)輸出流,后者是字符輸出流。
按操作方式分類結構圖:
按操作對象分類結構圖:
?
四、字節(jié)流
?切皆為字節(jié)
?切?件數(shù)據(jù)(?本、圖?、視頻等)在存儲時,都是以?進制數(shù)字的形式保存,都?個?個的字節(jié),那么傳輸時?樣如此。所以,字節(jié)流可以傳輸任意?件數(shù)據(jù)。在操作流的時候,我們要時刻明確,?論使?什么樣的流對象,底層傳輸?shù)氖冀K為?進制數(shù)據(jù)。
字節(jié)輸出流
java.io.OutputStream抽象類是表示字節(jié)輸出流的所有類的超類,將指定的字節(jié)信息寫出到?的地。它定義了字節(jié)輸出流的基本共性功能?法。
public void close() :關閉此輸出流并釋放與此流相關聯(lián)的任何系統(tǒng)資源。
public void flush() :刷新此輸出流并強制任何緩沖的輸出字節(jié)被寫出。
public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數(shù)組寫?此輸出流。
public void write(byte[] b, int off, int len) :從指定的字節(jié)數(shù)組寫? len字節(jié),從偏移量 off開始輸出到此輸出流。
public abstract void write(int b) :將指定的字節(jié)輸出流。
FileOutputStream類
構造?法:
public FileOutputStream(File file):創(chuàng)建?件輸出流以寫?由指定的 File對象表示的?件。
public FileOutputStream(String name): 創(chuàng)建?件輸出流以指定的名稱寫??件。
1、寫出字節(jié):write(int b) ?法,每次可以寫出?個字節(jié)數(shù)據(jù)
2、寫出字節(jié)數(shù)組:write(byte[] b),每次可以寫出數(shù)組中的數(shù)據(jù)
3、寫出指定?度字節(jié)數(shù)組:write(byte[] b, int off, int len) ,每次寫出從off索引開始,len個字節(jié)
示例:
?
// 使?File對象創(chuàng)建流對象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
// 使??件名稱創(chuàng)建流對象
FileOutputStream fos = new FileOutputStream("b.txt");
// 使??件名稱創(chuàng)建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 寫出數(shù)據(jù):雖然參數(shù)為int類型四個字節(jié),但是只會保留?個字節(jié)的信息寫出
fos.write(97); // 寫出第1個字節(jié)
fos.write(98); // 寫出第2個字節(jié)
fos.write(99); // 寫出第3個字節(jié)
// 關閉資源
fos.close();
// 使??件名稱創(chuàng)建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串轉換為字節(jié)數(shù)組
byte[] b = "你好中國".getBytes();
// 寫出字節(jié)數(shù)組數(shù)據(jù)
fos.write(b);
// 關閉資源
fos.close();
// 使??件名稱創(chuàng)建流對象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串轉換為字節(jié)數(shù)組
byte[] b = "abcde".getBytes();
// 寫出從索引2開始,2個字節(jié)。索引2是c,兩個字節(jié),也就是cd。
fos.write(b,2,2);
// 關閉資源
fos.close();
字節(jié)輸?流
java.io.InputStream抽象類是表示字節(jié)輸?流的所有類的超類,可以讀取字節(jié)信息到內存中。它定義了字節(jié)輸?流的基本共性功能?法。
public void close() :關閉此輸?流并釋放與此流相關聯(lián)的任何系統(tǒng)資源。
public abstract int read(): 從輸?流讀取數(shù)據(jù)的下?個字節(jié)。
public int read(byte[] b): 從輸?流中讀取?些字節(jié)數(shù),并將它們存儲到字節(jié)數(shù)組 b中 。
FileInputStream類
構造?法:
FileInputStream(File file): 通過打開與實際?件的連接來創(chuàng)建?個 FileInputStream ,該?件
由?件系統(tǒng)中的 File對象 file命名。
FileInputStream(String name): 通過打開與實際?件的連接來創(chuàng)建?個 FileInputStream ,該
?件由?件系統(tǒng)中的路徑名 name命名。
1、讀取字節(jié):read?法,每次可以讀取?個字節(jié)的數(shù)據(jù),提升為int類型,讀取到?件末尾,返回-1
2、使?字節(jié)數(shù)組讀取:read(byte[] b),每次讀取b的?度個字節(jié)到數(shù)組中,返回讀取到的有效字節(jié)個數(shù),讀取到末尾時,返回-1
示例:
// 使?File對象創(chuàng)建流對象
File file = new File("a.txt");
FileInputStream fos = new FileInputStream(file);
// 使??件名稱創(chuàng)建流對象
FileInputStream fos = new FileInputStream("b.txt");
// 使??件名稱創(chuàng)建流對象
FileInputStream fis = new FileInputStream("read.txt");
// 讀取數(shù)據(jù),返回?個字節(jié)
int read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
// 讀取到末尾,返回-1
read = fis.read();
System.out.println( read);
// 關閉資源
fis.close();
// 使??件名稱創(chuàng)建流對象
FileInputStream fis = new FileInputStream("read.txt");
// 定義變量,保存數(shù)據(jù)
int b ;
// 循環(huán)讀取
while ((b = fis.read())!=-1) {System.out.println((char)b);
}
// 關閉資源
fis.close();
// 使??件名稱創(chuàng)建流對象.
FileInputStream fis = new FileInputStream("read.txt"); // ?件中為abcde
// 定義變量,作為有效個數(shù)
int len ;
// 定義字節(jié)數(shù)組,作為裝字節(jié)數(shù)據(jù)的容器
byte[] b = new byte[2];
// 循環(huán)讀取
while (( len= fis.read(b))!=-1) {// 每次讀取后,把數(shù)組的有效字節(jié)部分,變成字符串打印System.out.println(new String(b,0,len));// len 每次讀取的有效字節(jié)個數(shù)
}
// 關閉資源
fis.close();
綜合案例:圖?復制
//1創(chuàng)建流
//1.1?件字節(jié)輸?流
FileInputStream fis=new FileInputStream("d:\\001.jpg");
//1.2?件字節(jié)輸出流
FileOutputStream fos=new FileOutputStream("d:\\002.jpg");
//2?邊讀,?邊寫
byte[] buf=new byte[1024];
int count=0;
while((count=fis.read(buf))!=-1) {fos.write(buf,0,count);
}
//3關閉
fis.close();
fos.close();
System.out.println("復制完畢");
五、字符流
字符輸?流
java.io.Reader 抽象類是表示?于讀取字符流的所有類的超類,可以讀取字符信息到內存中。它定義了字符輸?流的基本共性功能?法。
public void close() :關閉此流并釋放與此流相關聯(lián)的任何系統(tǒng)資源。
public int read() : 從輸?流讀取?個字符。
public int read(char[] cbuf) : 從輸?流中讀取?些字符,并將它們存儲到字符數(shù)組cbuf中 。
FileReader類
構造方法
FileReader(File file) : 創(chuàng)建?個新的 FileReader ,給定要讀取的File對象。
FileReader(String fileName) : 創(chuàng)建?個新的 FileReader ,給定要讀取的?件的名稱。
構造時使?系統(tǒng)默認的字符編碼和默認字節(jié)緩沖區(qū)。
1. 字符編碼:字節(jié)與字符的對應規(guī)則。Windows系統(tǒng)的中?編碼默認是GBK編碼表。idea中UTF-8
2. 字節(jié)緩沖區(qū):?個字節(jié)數(shù)組,?來臨時存儲字節(jié)數(shù)據(jù)。
示例:
// 使?File對象創(chuàng)建流對象
File file = new File("a.txt");
FileReader fr = new FileReader(file);
// 使??件名稱創(chuàng)建流對象
FileReader fr = new FileReader("b.txt");
// 使??件名稱創(chuàng)建流對象
FileReader fr = new FileReader("read.txt");
// 定義變量,保存有效字符個數(shù)
int len ;
// 定義字符數(shù)組,作為裝字符數(shù)據(jù)的容器
char[] cbuf = new char[2];
// 循環(huán)讀取
while ((len = fr.read(cbuf))!=-1) {System.out.println(new String(cbuf,0,len));
}
// 關閉資源
fr.close();
字符輸出流
java.io.Writer 抽象類是表示?于寫出字符流的所有類的超類,將指定的字符信息寫出到?的地。
它定義了字符輸出流的基本共性功能?法。
void write(int c) 寫?單個字符。
void write(char[] cbuf) 寫?字符數(shù)組。
abstract void write(char[] cbuf, int off, int len) 寫?字符數(shù)組的某?部分,off數(shù)組的開始索引,len寫的字符個數(shù)。
void write(String str) 寫?字符串。
void write(String str, int off, int len) 寫?字符串的某?部分,off字符串的開始索引,len寫的字符個數(shù)。
void flush() 刷新該流的緩沖。
void close() 關閉此流,但要先刷新它。
FileWriter類
FileWriter(File file) : 創(chuàng)建?個新的 FileWriter,給定要讀取的File對象。
FileWriter(String fileName) : 創(chuàng)建?個新的 FileWriter,給定要讀取的?件的名稱。
構造時使?系統(tǒng)默認的字符編碼和默認字節(jié)緩沖區(qū)。
1、寫出字符: write(int b) ?法,每次可以寫出?個字符數(shù)據(jù)
2、寫出字符數(shù)組 : write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以寫出字符數(shù)組中的數(shù)據(jù),?法類似FileOutputStream
3、寫出字符串: write(String str) 和 write(String str, int off, int len),每次可以寫出字符串中的數(shù)據(jù),更為?便
因為內置緩沖區(qū)的原因,如果不關閉輸出流,?法寫出字符到?件中。但是關閉的流對象,是?法繼續(xù)寫出數(shù)據(jù)的。如果我們既想寫出數(shù)據(jù),?想繼續(xù)使?流,就需要flush ?法了。
// 使?File對象創(chuàng)建流對象
File file = new File("fw.txt");
FileWriter fw = new FileWriter(file);
// 使??件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("fw.txt");
// 使??件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("fw.txt");
// 寫出數(shù)據(jù)
fw.write(97); // 寫出第1個字符
fw.write('b'); // 寫出第2個字符
fw.write('C'); // 寫出第3個字符
fw.write(30000); // 寫出第4個字符,中?編碼表中30000對應?個漢字。
/*
【注意】關閉資源時,與FileOutputStream不同。
如果不關閉,數(shù)據(jù)只是保存到緩沖區(qū),并未保存到?件。
*/
// fw.close();
// 使??件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("fw.txt");
// 寫出數(shù)據(jù),通過flush
fw.write('刷'); // 寫出第1個字符
fw.flush();
fw.write('新'); // 繼續(xù)寫出第2個字符,寫出成功
fw.flush();
// 寫出數(shù)據(jù),通過close
fw.write('關'); // 寫出第1個字符
fw.close();
fw.write('閉'); // 繼續(xù)寫出第2個字符,【報錯】java.io.IOException: Stream
closed
fw.close();
// 使??件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("fw.txt");
// 字符串轉換為字節(jié)數(shù)組
char[] chars = "你好中國".toCharArray();
// 寫出字符數(shù)組
fw.write(chars);
// 寫出從索引2開始,2個字節(jié)。索引2是'中',兩個字節(jié),也就是'中國'。
fw.write(b,2,2); //中國
// 關閉資源
fos.close();
// 使??件名稱創(chuàng)建流對象
FileWriter fw = new FileWriter("fw.txt");
// 字符串
String msg = "你好中國";
// 寫出字符數(shù)組
fw.write(msg); //你好中國
// 寫出從索引2開始,2個字節(jié)。索引2是'中',兩個字節(jié),也就是'中國'。
fw.write(msg,2,2); // 中國
// 關閉資源
fos.close();
六、緩沖流
概述
緩沖流,也叫?效流,是對4個基本的 FileXxx 流的增強,所以也是4個流,按照數(shù)據(jù)類型分類:
字節(jié)緩沖流: BufferedInputStream , BufferedOutputStream
字符緩沖流: BufferedReader , BufferedWriter
緩沖流的基本原理,是在創(chuàng)建流對象時,會創(chuàng)建?個內置的默認大小的緩沖區(qū)數(shù)組,通過緩沖區(qū)讀寫,減少系統(tǒng)IO次數(shù),從?提?讀寫的效率。
字節(jié)緩沖流
構造?法:
public BufferedInputStream(InputStream in) :創(chuàng)建?個 新的緩沖輸?流。
public BufferedOutputStream(OutputStream out) : 創(chuàng)建?個新的緩沖輸出流。
示例:
// 創(chuàng)建字節(jié)緩沖輸?流
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("bis.txt"));
// 創(chuàng)建字節(jié)緩沖輸出流
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("bos.txt"));
效率PK
基本流示例:
public static void main(String[] args) {// 記錄開始時間long start = System.currentTimeMillis();// 創(chuàng)建流對象try (FileInputStream fis = new FileInputStream("jdk8.exe");FileOutputStream fos = new FileOutputStream("copy.exe")){// 讀寫數(shù)據(jù)int b;while ((b = fis.read()) != -1) {fos.write(b);}} catch (IOException e) {e.printStackTrace();}// 記錄結束時間long end = System.currentTimeMillis();System.out.println("普通流復制時間:"+(end - start)+" 毫秒");}
緩沖流示例:
public static void main(String[] args) {// 記錄開始時間long start = System.currentTimeMillis();// 創(chuàng)建流對象try (BufferedInputStream bis = new BufferedInputStream(newFileInputStream("jdk8.exe"));BufferedOutputStream bos = new BufferedOutputStream(newFileOutputStream("copy.exe"));){// 讀寫數(shù)據(jù)//int b;//while ((b = bis.read()) != -1) {//bos.write(b);//}// 讀寫數(shù)據(jù)int len;byte[] bytes = new byte[8*1024];while ((len = bis.read(bytes)) != -1) {bos.write(bytes, 0 , len);}} catch (IOException e) {e.printStackTrace();}// 記錄結束時間long end = System.currentTimeMillis();System.out.println("緩沖流復制時間:"+(end - start)+" 毫秒");}
字符緩沖流
構造方法
public BufferedReader(Reader in) :創(chuàng)建?個 新的緩沖輸?流。
public BufferedWriter(Writer out) : 創(chuàng)建?個新的緩沖輸出流。
示例:
// 創(chuàng)建字符緩沖輸?流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 創(chuàng)建字符緩沖輸出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
特有方法
字符緩沖流的基本?法與普通字符流調??式?致,不再闡述,我們來看它們具備的特有?法。
BufferedReader: public String readLine() : 讀???字。
BufferedWriter: public void newLine() : 寫???分隔符,由系統(tǒng)屬性定義符號。
示例1:
// 創(chuàng)建流對象
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
// 定義字符串,保存讀取的???字
String line = null;
// 循環(huán)讀取,讀取到最后返回null
while ((line = br.readLine())!=null) {System.out.print(line);System.out.println("------");
}
// 釋放資源
br.close();
示例2:
// 創(chuàng)建流對象
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
// 寫出數(shù)據(jù)
bw.write("hello");
// 寫出換?
bw.newLine();
bw.write("world");
bw.newLine();
bw.write("!");
bw.newLine();
// 釋放資源
bw.close();
七、轉換流
在IDEA中,使? FileReader 讀取項?中的?本?件。由于IDEA的設置,都是默認的 UTF-8編碼,所以沒有任何問題。但是,當讀取Windows系統(tǒng)中創(chuàng)建的?本?件時,由于Windows系統(tǒng)的默認是GBK編碼,就會出現(xiàn)亂碼。
示例:
public class ReaderDemo {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("E:\\File_GBK.txt");int read;while ((read = fileReader.read()) != -1) {System.out.print((char)read);}fileReader.close();}
}
輸出結果:
���
那么如何讀取GBK編碼的?件呢?
InputStreamReader類
轉換流 java.io.InputStreamReader ,是Reader的?類,是從字節(jié)流到字符流的橋梁。它讀取字節(jié),并使?指定的字符集將其解碼為字符。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。
構造方法
InputStreamReader(InputStream in) : 創(chuàng)建?個使?默認字符集的字符流。
InputStreamReader(InputStream in, String charsetName) : 創(chuàng)建?個指定字符集的字符流。
示例:
// 定義?件路徑,?件為gbk編碼
String FileName = "E:\\file_gbk.txt";
// 創(chuàng)建流對象,默認UTF8編碼
InputStreamReader isr = new InputStreamReader(new
FileInputStream(FileName));
// 創(chuàng)建流對象,指定GBK編碼
InputStreamReader isr2 = new InputStreamReader(new
FileInputStream(FileName) , "GBK");
// 定義變量,保存字符
int read;
// 使?默認編碼字符流讀取,亂碼
while ((read = isr.read()) != -1) {System.out.print((char)read); // ��?�
}
isr.close();
// 使?指定編碼字符流讀取,正常解析
while ((read = isr2.read()) != -1) {System.out.print((char)read);// ?家好
}
isr2.close();
OutputStreamWriter類
轉換流 java.io.OutputStreamWriter ,是Writer的?類,是從字符流到字節(jié)流的橋梁。使?指定
的字符集將字符編碼為字節(jié)。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。
構造?法
OutputStreamWriter(OutputStream in) : 創(chuàng)建?個使?默認字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName) : 創(chuàng)建?個指定字符集的字符流。
示例:
// 定義?件路徑
String FileName = "out.txt";
// 創(chuàng)建流對象,默認UTF8編碼
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream(FileName));
// 寫出數(shù)據(jù)
osw.write("你好"); // 保存為6個字節(jié)
osw.close();
// 定義?件路徑
String FileName2 = "out2.txt";
// 創(chuàng)建流對象,指定GBK編碼
OutputStreamWriter osw2 = new OutputStreamWriter(new
FileOutputStream(FileName2),"GBK");
// 寫出數(shù)據(jù)
osw2.write("你好");// 保存為4個字節(jié)
osw2.close();
?、序列化
概述
Java 提供了?種對象序列化的機制。??個字節(jié)序列可以表示?個對象,該字節(jié)序列包含該 對象的數(shù)據(jù) 、 對象的類型 和 對象中存儲的屬性 等信息。字節(jié)序列寫出到?件之后,相當于?件中持久保存了?個對象的信息。
反之,該字節(jié)序列還可以從?件中讀取回來,重構對象,對它進?反序列化。 對象的數(shù)據(jù) 、 對象的類型 和 對象中存儲的數(shù)據(jù)信息,都可以?來在內存中創(chuàng)建對象。
ObjectOutputStream類
java.io.ObjectOutputStream 類,將Java對象的原始數(shù)據(jù)類型寫出到?件,實現(xiàn)對象的持久存儲。
序列化操作
?個對象要想序列化,必須滿?兩個條件:
????????必須實現(xiàn)Serializable接?。
????????必須保證其所有屬性均可序列化。(transient修飾為臨時屬性,不參與序列化)
寫出對象?法
????????public final void writeObject (Object obj) : 將指定的對象寫出。
示例:
public class Employee implements java.io.Serializable {public String name;public String address;public transient int age; // transient瞬態(tài)修飾成員,不會被序列化public void addressCheck() {System.out.println("Address check : " + name + " -- " + address);}
}
public class SerializeDemo{public static void main(String [] args) {Employee e = new Employee();e.name = "zhangsan";e.address = "guangzhou";e.age = 20;try {// 創(chuàng)建序列化流對象ObjectOutputStream out = new ObjectOutputStream(newFileOutputStream("employee.txt"));// 寫出對象out.writeObject(e);// 釋放資源out.close();fileOut.close();System.out.println("序列化完成"); // 姓名,地址被序列化,年齡沒有被序列化。} catch(IOException i) {i.printStackTrace();}}
}
ObjectInputStream類
ObjectInputStream反序列化流,將之前使?ObjectOutputStream序列化的原始數(shù)據(jù)恢復為對象。
反序列化操作
如果能找到?個對象的class?件,我們可以進?反序列化操作,調? ObjectInputStream 讀取對象的?法,
public final Object readObject () : 讀取?個對象。
public class DeserializeDemo {public static void main(String [] args) {Employee e = null;try {// 創(chuàng)建反序列化流FileInputStream fileIn = new FileInputStream("employee.txt");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("Name: " + e.name); // zhangsanSystem.out.println("Address: " + e.address); // beiqingluSystem.out.println("age: " + e.age); // 0}
}
注意:
對于JVM可以反序列化對象,它必須是能夠找到class?件的類。如果找不到該類的class?件,則拋出?個ClassNotFoundException 異常。
當JVM反序列化對象時,能找到class?件,但是class?件在序列化對象之后發(fā)?了修改,那么反序列化操作也會失敗,拋出?個 InvalidClassException 異常。
發(fā)?這個異常的原因,該類的序列版本號與從流中讀取的類描述符的版本號不匹配 ,serialVersionUID 該版本號的?的在于驗證序列化的對象和對應類是否版本匹配。
serialVersionUID是?個?常重要的字段,因為 Java 的序列化機制是通過在運?時判斷類的
serialVersionUID來驗證版本?致性的。在進?反序列化時,JVM 會把傳來的字節(jié)流中的
serialVersionUID與本地相應實體(類)的serialVersionUID進??較,如果相同就認為是?致的,可
以進?反序列化,否則就會出現(xiàn)序列化版本不?致的異常。
?般來說,定義serialVersionUID的?式有兩種,分別為:
采?默認的1L,具體為private static final long serialVersionUID = 1L;
在可兼容的前提下,可以保留舊版本號,如果不兼容,或者想讓它不兼容,就??遞增版本號。
1->2->3.....
根據(jù)類名、接?名、成員?法及屬性等來?成?個64位的哈希字段,例如 private static final long
serialVersionUID = XXXL;
這種?式適?于這樣的場景:
開發(fā)者認為每次修改類后就需要?成新的版本號,不想向下兼容,操作就是刪除原有serialVesionUid
聲明語句,再?動?成?下。
第?種能夠保證每次更改類結構后改變版本號,但還是要??去?成
public class Employee implements java.io.Serializable {// 加?序列版本號private static final long serialVersionUID = 1L;public String name;public String address;// 添加新的屬性 ,重新編譯, 可以反序列化,該屬性賦為默認值.public int eid;public void addressCheck() {System.out.println("Address check : " + name + " -- " + address);}
}
九、Properties屬性類
常用方法
public Object setProperty(String key, String value) : 保存?對屬性。
public String getProperty(String key) :使?此屬性列表中指定的鍵搜索屬性值。
public Set<String> stringPropertyNames() :所有鍵的名稱的集合。
public void load(InputStream inStream) : 從字節(jié)輸?流中讀取鍵值對。
示例1:
// 創(chuàng)建屬性集對象
Properties properties = new Properties();
// 添加鍵值對元素
properties.setProperty("filename", "a.txt");
properties.setProperty("length", "123");
properties.setProperty("location", "D:\\a.txt");
// 打印屬性集對象
System.out.println(properties);
// 通過鍵,獲取屬性值
System.out.println(properties.getProperty("filename"));
System.out.println(properties.getProperty("length"));
System.out.println(properties.getProperty("location"));
// 遍歷屬性集,獲取所有鍵的集合
Set<String> strings = properties.stringPropertyNames();
// 打印鍵值對
for (String key : strings ) {System.out.println(key+" -- "+properties.getProperty(key));
}
示例2:
// 創(chuàng)建屬性集對象
Properties pro = new Properties();
// 加載?本中信息到屬性集
pro.load(new FileInputStream("read.txt"));
// 遍歷集合并打印
Set<String> strings = pro.stringPropertyNames();
for (String key : strings ) {System.out.println(key+" -- "+pro.getProperty(key));
}
小貼士:?本中的數(shù)據(jù),必須是鍵值對形式,可以使?空格、等號、冒號等符號分隔。