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