目錄
一、轉換流
二、字節緩沖流
三、字符緩沖流
四、序列化流與反序列化流
五、打印流
六、標準輸入、輸出流
七、IO流總結
一、轉換流
1. OutputStreamWriter 類
(1) 概述
java.io.OutputStreamWriter
繼承Writer
類;就是一個字符輸出流,寫文本文件;- 是字符通向字節的橋梁,將 字符流 轉成 字節流
- write():字符,字符數組,字符串
(2) 構造方法
OutputStreamWriter(OuputStream out)
:接收所有的字節輸出流
字節輸出流目前只有: FileOutputStream
OutputStreamWriter(OutputStream out, String charsetName)
String charsetName:傳遞 編碼表名字:GBK、UTF-8
public class OutputStreamWriterDemo {public static void main(String[] args) throws IOException {writeUTF();}//轉換流對象OutputStreamWriter寫文本,采用UTF-8編碼表寫入public static void writeUTF()throws IOException{//創建字節輸出流,綁定文件FileOutputStream fos = new FileOutputStream("c:\\utf.txt");//創建轉換流對象,構造方法保證字節輸出流,并指定編碼表是UTF-8OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8"); //GBK可以不寫osw.write("你好");osw.close(); //使用close()連刷新帶關閉}
}
2. InputStreamReader 類
(1) 概述
java.io.InputStreamReader
繼承 Reader;是 字符輸入流,讀取文本文件- 字節流向字符的橋梁,將 字節流 轉為 字符流
- 讀取的方法:read() 讀取1個字符,讀取字符數組
(2) 構造方法
InputStreamReader(InputStream in)
:接收所有的 字節輸入流
可以傳遞的字節輸入流: FileInputStream
InputStreamReader(InputStream in,String charsetName)
: 傳遞編碼表的名字
public class InputStreamReaderDemo {public static void main(String[] args) throws IOException {readUTF();}//轉換流,InputSteamReader讀取文本,采用UTF-8編碼表,讀取文件utfpublic static void readUTF()throws IOException{//創建字節輸入流,傳遞文本文件FileInputStream fis = new FileInputStream("c:\\utf.txt");//創建轉換流對象,構造方法中,包裝字節輸入流,同時寫編碼表名InputStreamReader isr = new InputStreamReader(fis,"UTF-8");char[] ch = new char[1024];int len = isr.read(ch);System.out.println(new String(ch,0,len));isr.close();}
}
###3. 轉換流子類父類的區別
- 繼承關系
OutputStreamWriter 的子類: FileWriter
InputStreamReader 的子類:FileReader - 區別
- OutputStreamWriter 和 InputStreamReader 是字符和字節的橋梁:也可以稱之為字符轉換流。字符轉換流原理:字節流 + 編碼表
- FileWriter 和 FileReader:作為子類,僅作為操作字符文件的便捷類存在。當操作的字符文件,使用的是默認編碼表時可以不用父類,而直接用子類就完成操作了,簡化了代碼。
- 以下三句話功能相同
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));//默認字符集。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),“GBK”);//指定GBK字符集。
FileReader fr = new FileReader(“a.txt”);
注意:一旦要指定其他編碼時,絕對不能用子類,必須使用字符轉換流。什么時候用子類呢?
條件:1、操作的是文件。2、使用默認編碼。
二、字節緩沖流
1. 概述
- 可提高IO流的讀寫速度
- 分為字節緩沖流與字符緩沖流
2. 字節輸出緩沖流 BufferedOutputStream
java.io.BufferedOuputStream
作用: 提高原有輸出流的寫入效率- BufferedOuputStream 繼承 OutputStream
- 方法:寫入 write 字節,字節數組
- 構造方法:
BufferedOuputStream(OuputStream out)
:可以傳遞任意的字節輸出流,傳遞的是哪個字節流,就對哪個字節流提高效率
public class BufferedOutputStreamDemo {public static void main(String[] args)throws IOException {//創建字節輸出流,綁定文件//FileOutputStream fos = new FileOutputStream("c:\\buffer.txt");//創建字節輸出流緩沖流的對象,構造方法中,傳遞字節輸出流BufferedOutputStream bos = newBufferedOutputStream(new FileOutputStream("c:\\buffer.txt"));bos.write(55);byte[] bytes = "HelloWorld".getBytes();bos.write(bytes);bos.write(bytes, 3, 2);bos.close();}
}
3. 字節輸入緩沖流 BufferedInputStream
BufferedInputStream
,繼承 InputStream ,標準的字節輸入流- 讀取方法: read() ,單個字節,字節數組
- 構造方法:
BufferedInputStream(InputStream in)
:可以傳遞任意的字節輸入流,傳遞是誰,就提高誰的效率 - 可以傳遞的字節輸入流 FileInputStream
public class BufferedInputStreamDemo {public static void main(String[] args) throws IOException{//創建字節輸入流的緩沖流對象,構造方法中包裝字節輸入流,包裝文件BufferedInputStream bis = newBufferedInputStream(new FileInputStream("c:\\buffer.txt"));byte[] bytes = new byte[1024];int len = 0 ;while((len = bis.read(bytes))!=-1){System.out.print(new String(bytes,0,len));}bis.close();}
}
4. 四種文件復制方式的效率比較
- 結論:
- 字節流讀寫單個字節 :125250 毫秒
- 字節流讀寫字節數組 :193 毫秒
- 字節流緩沖區流讀寫單個字節:1210 毫秒
- 字節流緩沖區流讀寫字節數組 :73 毫秒
- 代碼
public class Copy {public static void main(String[] args)throws IOException {long s = System.currentTimeMillis();copy_4(new File("c:\\q.exe"), new File("d:\\q.exe"));long e = System.currentTimeMillis();System.out.println(e-s);}/** 方法,實現文件復制* 4. 字節流緩沖區流讀寫字節數組*/public static void copy_4(File src,File desc)throws IOException{BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));int len = 0 ;byte[] bytes = new byte[1024];while((len = bis.read(bytes))!=-1){bos.write(bytes,0,len);}bos.close();bis.close();}/** 方法,實現文件復制* 3. 字節流緩沖區流讀寫單個字節*/public static void copy_3(File src,File desc)throws IOException{BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));int len = 0 ;while((len = bis.read())!=-1){bos.write(len);}bos.close();bis.close();}/** 方法,實現文件復制* 2. 字節流讀寫字節數組*/public static void copy_2(File src,File desc)throws IOException{FileInputStream fis = new FileInputStream(src);FileOutputStream fos = new FileOutputStream(desc);int len = 0 ;byte[] bytes = new byte[1024];while((len = fis.read(bytes))!=-1){fos.write(bytes,0,len);}fos.close();fis.close();}/** 方法,實現文件復制* 1. 字節流讀寫單個字節*/public static void copy_1(File src,File desc)throws IOException{FileInputStream fis = new FileInputStream(src);FileOutputStream fos = new FileOutputStream(desc);int len = 0 ;while((len = fis.read())!=-1){fos.write(len);}fos.close();fis.close();}
}
三、字符緩沖流
1. 字符輸出緩沖流 BufferedWriter
java.io.BufferedWriter
繼承 Writer- 寫入方法: write () ,單個字符,字符數組,字符串
- 構造方法:
BufferedWriter(Writer w)
:傳遞任意字符輸出流,傳遞誰,就高效誰 - 能傳遞的字符輸出流: FileWriter, OutputStreamWriter
public class BufferedWrierDemo {public static void main(String[] args) throws IOException{//創建字符輸出流,封裝文件FileWriter fw = new FileWriter("c:\\buffer.txt");BufferedWriter bfw = new BufferedWriter(fw);bfw.write(100);bfw.flush();bfw.write("你好".toCharArray());bfw.flush();bfw.write("你好");bfw.flush();bfw.write("我好好");bfw.flush();bfw.write("大家都好");bfw.flush();bfw.close();}
}
2. 字符輸出緩沖流 BufferedWriter—特有方法 newLine
void newLine()
: 寫換行- newLine():文本中換行, \r\n也是文本換行
- 方法具有平臺無關性
windows \r\n ; Linux \n
- newLine()運行結果和操作系統是相互關聯的
- JVM: 安裝的是 Windows 版本,newLine()寫的就是 \r\n;安裝的是 Linux 版本,newLine() 寫的就是**\n**
3.字符輸入流緩沖流 BufferedReader
(1)概述
java.io.BufferedReader
繼承 Reader,從字符輸入流中讀取文本,緩沖各個字符,從而實現字符、數組和行的高效讀取
讀取功能: read(), 單個字符,字符數組
構造方法:BufferedReader(Reader r)
:可以任意的字符輸入流,有:FileReaderInputStreamReader
(2)BufferedReader 自己的功能
String readLine()
: 讀取文本行 \r\n ,讀取一個文本行,包含該行內容的字符串,不包含任何行終止符,如果已到達流末尾,則返回 null
獲取內容的方法一般都有返回值
int:沒有返回的都是 負數
引用類型: 找不到返回 null
boolean: 找不到返回 false
public class BufferedReaderDemo {public static void main(String[] args) throws IOException {int lineNumber = 0;//創建字符輸入流緩沖流對象,構造方法傳遞字符輸入流,包裝數據源文件BufferedReader bfr = new BufferedReader(new FileReader("c:\\a.txt"));//調用緩沖流的方法 readLine()讀取文本行//循環讀取文本行, 結束條件 readLine()返回nullString line = null;while((line = bfr.readLine())!=null){lineNumber++;System.out.println(lineNumber+" "+line);}bfr.close();}
}
4. 字符流緩沖區流復制文本文件
/** 使用緩沖區流對象,復制文本文件* 數據源 BufferedReader+FileReader 讀取* 數據目的 BufferedWriter+FileWriter 寫入* 讀取文本行, 讀一行,寫一行,寫換行*/
public class Copy_1 {public static void main(String[] args) throws IOException{BufferedReader bfr = new BufferedReader(new FileReader("c:\\w.log")); BufferedWriter bfw = new BufferedWriter(new FileWriter("d:\\w.log"));//讀取文本行, 讀一行,寫一行,寫換行String line = null;while((line = bfr.readLine())!=null){bfw.write(line);bfw.newLine();bfw.flush();}bfw.close();bfr.close();}
}
四、序列化流與反序列化流
1. 概述
- 對象的序列化:對象中的數據,以流的形式,寫入到文件中保存過程稱為寫出對象,
ObjectOutputStream
將對象寫道文件中,實現序列化 - 對象的反序列化:在文件中,以流的形式,將對象讀出來,讀取對象,
ObjectInputStream
將文件對象讀取出來
2. 實現
ObjectOutputStream
: 寫對象,實現序列化- 構造方法:
ObjectOutputStream(OutputSteam out)
:傳遞任意的 字節輸出流 void writeObject(Object obj)
:寫出對象
- 構造方法:
ObjectInputStream
:讀取對象,實現反序列化- 構造方法:
ObjectInputStream(InputStream in)
:傳遞任意的 字節輸入流,輸入流封裝文件,必須是序列化的文件
- 構造方法:
Object readObject()
: 讀取對象
//定義類
public class Person implements Serializable{//省略}
}public class ObjectStreamDemo {public static void main(String[] args)throws IOException, ClassNotFoundException {writeObject();readObject();}//ObjectOutputStreampublic static void writeObject() throws IOException{//創建字節輸出流,封裝文件FileOutputStream fos = new FileOutputStream("c:\\person.txt");//創建寫出對象的序列化流的對象,構造方法傳遞字節輸出流ObjectOutputStream oos = new ObjectOutputStream(fos);Person p = new Person("lisi",25);//調用序列化流的方法writeObject,寫出對象oos.writeObject(p);oos.close();//ObjectInputStreampublic static void readObject() throws IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("c:\\person.txt");//創建反序列化流,構造方法中,傳遞字節輸入流ObjectInputStream ois = new ObjectInputStream(fis);//調用反序列化流的方法 readObject()讀取對象Object obj =ois.readObject();System.out.println(obj);ois.close();}
}
3. 細節
(1)transient 瞬態關鍵字
- 作用: 被
transient
修飾的屬性不會被序列化 transient
關鍵字只能修飾成員變量
(2)靜態不能序列化
- 原因:序列化是把對象數據進行持久化存儲;靜態的東西不屬于對象,而屬于類
(3)Serializable 接口
- 作用:給需要序列化的類上加標記。該標記中沒有任何抽象方法;只有實現了
Serializable
接口的類的對象才能被序列化
4. 序列化中的序列號沖突問題
-
問題產生: 當一個類實現Serializable接口后,創建對象并將對象寫入文件,之后更改了源代碼 (比如:將成員變量的修飾符有private改成public),再次從文件中讀取對象時會報異常
-
原因:一旦修改了源碼,重新編譯產生class文件,會根據類的成員重新計算序列號,這樣新編譯的class文件中的序列號,與原來文件中的序列號就不同了
-
解決:需要做一個終身不變的序列號! 需要在序列化中自定義序列號
private static final long serialVersionUID = 1478652478456L;
// 這樣每次編譯類時生成的 serialVersionUID 值都是固定的
//類自定義了序列號,編譯器就不會計算序列號
五、打印流
1. 概述
- 打印流添加輸出數據的功能,使它們能夠方便地打印各種數據值表示形式.
2. 打印流根據流的分類
- 字節打印流 PrintStream
- 字符打印流 PrintWriter
3. 方法
void print(String str)
: 輸出任意類型的數據,void println(String str)
: 輸出任意類型的數據,自動寫入換行操作
4. 特點
- 此流不負責數據源,只負責數據目的
- 可以操作任意類型的數據。(boolean, int, long, float, double)
- 打印流,可以開啟自動刷新功能
滿足兩個條件:- 使用特定的構造方法,打開打印流的自動刷新,輸出的數據目的必須是流對象:OutputStreamWriter
- 必須調用 println,printf,format三個方法中的一個,啟用自動刷新
- 為其他輸出流,添加功能
- 永遠不會拋出 IOException,但是可能拋出別的異常
5. 構造方法
- 就是打印流的輸出目的端
- PrintStream構造方法
- 接收File類型,接收字符串文件名,接收字節輸出流OutputStream
- PrintWriter構造方法
- 接收File類型,接收字符串文件名,接收字節輸出流OutputStream, 接收字符輸出流Writer
6. 打印字符數組
- println數組,只有打印字符數組時是打印內容,其余均打印數組的地址
- 因為api中定義了打印字符數組的方法,其底層是在遍歷數組中的元素,而其他打印數組的方法,都是將數組對象編程Object,其底層再將對象編程String,調用了
String s = String.valueOf(x)
;方法
7. 利用打印流,完成文本文件的復制
/** 打印流實現文本復制* 讀取數據源 BufferedReader+File 讀取文本行* 寫入數據目的 PrintWriter+println 自動刷新*/
public class PrintWriterDemo1 {public static void main(String[] args) throws IOException{BufferedReader bfr = new BufferedReader(new FileReader("c:\\a.txt"));PrintWriter pw = new PrintWriter(new FileWriter("d:\\a.txt"),true);String line = null;while((line = bfr.readLine())!=null){pw.println(line);}pw.close();bfr.close();}
}
六、標準輸入、輸出流
1. 概述
- 標準輸入流:
System.in
默認指鍵盤輸入 - 標準輸出流:
System.out
向顯示器輸出
2. 繼承關系
- PrintStream extends FilterOutputStream
- FilterOutputStream extends OutputStream
3. 案例
public class StandardIO {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String s;// 標準輸入流的read方法,讀取鍵盤數據的時候,當當前沒有鍵盤輸入數據的時候// read會阻塞當前線程,使得不能結束,只有自定義協議,才能結束標準輸入流while((s = br.readLine()) != null) {//自定協議,當用戶輸入886結束接收用戶輸入if("886".equals(s)) {break;}System.out.println("輸出:" + s);}br.close();}
}
七、IO流總結
- 字節流
- 字節輸入流 InputStream
- FileInputStream 操作文件的字節輸入流
- BufferedInputStream高效的字節輸入流
- ObjectInputStream 反序列化流
- 字節輸出流 OutputStram
- FileOutputStream 操作文件的字節輸出流
- BufferedOutputStream 高效的字節輸出流
- ObjectOuputStream 序列化流
- PrintStream 字節打印流
- 字節輸入流 InputStream
- 字符流
- 字符輸入流 Reader
- FileReader 操作文件的字符輸入流
- BufferedReader 高效的字符輸入流
- InputStreamReader 輸入操作的轉換流(把字節流封裝成字符流)
- 字符輸出流 Writer
- FileWriter 操作文件的字符輸出流
- BufferedWriter 高效的字符輸出流
- OutputStreamWriter 輸出操作的轉換流(把字節流封裝成字符流)
- PrintWriter 字符打印流
- 字符輸入流 Reader
- 方法:
- 讀數據方法:
- read() 一次讀一個字節或字符的方法
- read(byte[] char[]) 一次讀一個數組數據的方法
- readLine() 一次讀一行字符串的方法(BufferedReader類特有方法)
- readObject() 從流中讀取對象(ObjectInputStream特有方法)
- 寫數據方法:
- write(int) 一次寫一個字節或字符到文件中
- write(byte[] char[]) 一次寫一個數組數據到文件中
- write(String) 一次寫一個字符串內容到文件中
- writeObject(Object ) 寫對象到流中(ObjectOutputStream類特有方法)
- newLine() 寫一個換行符號(BufferedWriter類特有方法)
- 讀數據方法:
- 向文件中寫入數據的過程
1,創建輸出流對象
2,寫數據到文件
3,關閉輸出流 - 從文件中讀數據的過程
1, 創建輸入流對象
2, 從文件中讀數據
3, 關閉輸入流 - 文件復制的過程
1, 創建輸入流(數據源)
2, 創建輸出流(目的地)
3, 從輸入流中讀數據
4, 通過輸出流,把數據寫入目的地
5, 關閉流
File類
- 方法
- 獲取文件名稱 getName()
- 獲取文件絕對路徑 getAbsolutePath()
- 獲取文件大小 length()
- 獲取當前文件夾中所有File對象 File[] listFiles()
- 判斷是否為文件 isFile()
- 判斷是否為文件夾 isDirectory()
- 創建文件夾 mkdir() mkdirs()
- 創建文件 createNewFile()
- 異常
- try…catch…finally捕獲處理異常
- throws 聲明異常
- throw 拋出異常對象
- 異常的分類
- 編譯期異常 Exception
- 運行期異常 RuntimeException
- 注意:
- 編譯期異常,必須處理,不然無法編譯通過
- 運行期異常,程序運行過程中,產生的異常信息
- 實現文件內容的自動追加
- 構造方法
- FileOutputStream(File file, boolean append)
- FileOutputStream(String fileName, boolean append)
- FileWriter(File, boolean append)
- FileWriter(String fileName, boolean append)
- 構造方法
- 實現文件內容的自動刷新
- 構造方法
- PrintStream(OutputStream out, boolean autoFlush)
- PrintWriter(OutputStream out, boolean autoFlush)
- 構造方法
- 異常
- try…catch…finally捕獲處理異常
- throws 聲明異常
- throw 拋出異常對象
- 異常的分類
- 編譯期異常 Exception
- 運行期異常 RuntimeException
- 注意:
- 編譯期異常,必須處理,不然無法編譯通過
- 運行期異常,程序運行過程中,產生的異常信息
- 實現文件內容的自動追加
- 構造方法
- FileOutputStream(File file, boolean append)
- FileOutputStream(String fileName, boolean append)
- FileWriter(File, boolean append)
- FileWriter(String fileName, boolean append)
- 構造方法
- 實現文件內容的自動刷新
- 構造方法
- PrintStream(OutputStream out, boolean autoFlush)
- PrintWriter(OutputStream out, boolean autoFlush)
- 構造方法