第11天 IO流
今日內容介紹
字節流
緩衝流
今日學習目標
可以使用字節輸出流寫出數據到文件
可以使用字節輸入流讀取數據到程序
可以理解讀取數據read(byte[])方法的原理
可以使用字節流完成文件的複製
可以使用字節緩衝流讀取數據到程序
可以使用字節緩衝流寫出數據到文件
可以完成單級文件夾複製
第1章 IO
1.1 IO概述
回想以前寫過的程序,數據都是在內存中,一旦程序運行結束,這些數據都沒有了,等下次再想使用這些數據,但是已經沒有了。那怎麼辦呢?能不能把運算完的數據都保存下來,下次程序啓動的時候,再把這些數據讀出來繼續使用呢?其實要把數據持久化存儲,就須要把內存中的數據存儲到內存之外的其餘持久化設備(硬盤、光盤、U盤等 ROM)上。
當須要把內存中的數據存儲到持久化設備上這個動做稱爲輸出(寫)Output操做。
當把持久設備上的數據讀取到內存中的這個動做稱爲輸入(讀)Input操做。
所以咱們把這種輸入和輸出動做稱爲IO操做。數組
1.2 IO流流向分類
按照流向分:輸入流與輸出流,每一個IO流對象均要綁定一個IO資源
分類關係以下:
字節輸入流 InputStream 抽象類
FileInputStream 操做文件的字節輸入流
字節輸出流 OutputStream 抽象類
FileOutputStream 操做文件的字節輸出流
按照傳輸方式:分爲字節流和字符流
字符流 按照字符的方式讀寫
字節流 按照字節的方式讀寫
1.3 一切均爲字節
在數據傳輸過程當中,一切數據(文本、圖像、聲音等)最終存儲的均爲一個個字節,即二進制數字。因此數據傳輸過程當中使用二進制數據能夠完成任意數據的傳遞。
爲何打開一個文本文件 咱們看到的不是0101001這些數據?
咱們向一個文件中存儲必定的數據(一些數字),若是使用文本方式打開,則會以文本的方式解釋數據。若是以視頻的方式打開,則會以視頻的方式解釋數據。音頻、可行執行文件等亦是如此。因此,在文件傳輸過程當中,咱們要時刻明確,傳輸的始終爲二進制數據。函數
第2章 字節流
既然一切數據都是字節,那麼字節流如何操做呢,那麼接下來咱們進行字節流的學習.
2.1 字節輸出流OutputStream
OutputStream此抽象類,是表示輸出字節流的全部類的超類。操做的數據都是字節,定義了輸出字節流的基本共性功能方法。
輸出流中定義都是寫write方法,以下圖:學習
2.1.1 FileOutputStream類
OutputStream有不少子類,其中子類FileOutputStream可用來寫入數據到文件。
FileOutputStream類,即文件輸出流,是用於將數據寫入 File的輸出流。spa
構造方法code
2.1.2 FileOutputStream類寫入數據到文件中(三個方法)
將數據寫到文件中,
步驟
1.建立輸出流對象
2.調用輸出流對象的寫數據方法
3.釋放資源
代碼演示:視頻
public class FileOutputStreamDemo { public static void main(String[] args) throws IOException { //需求:將數據寫入到文件中。 //建立存儲數據的文件。 File file = new File("c:\\file.txt"); //建立一個用於操做文件的字節輸出流對象。一建立就必須明確數據存儲目的地。 //輸出流目的是文件,會自動建立。若是文件存在,則覆蓋。 FileOutputStream fos = new FileOutputStream(file); //調用父類中的write方法。 byte[] data = "abcde".getBytes(); fos.write(data); //關閉流資源。 fos.close(); } }
2.1.3 給文件中續寫和換行
咱們直接new FileOutputStream(file)這樣建立對象,寫入數據,會覆蓋原有的文件,那麼咱們想在原有的文件中續寫內容怎麼辦呢?
繼續查閱FileOutputStream的API。發如今FileOutputStream的構造函數中,能夠接受一個boolean類型的值,若是值true,就會在文件末位繼續添加。
構造方法對象
給文件中續寫數據和換行,代碼演示:blog
public class FileOutputStreamDemo2 { public static void main(String[] args) throws Exception { File file = new File("c:\\file.txt"); FileOutputStream fos = new FileOutputStream(file, true); String str = "\r\n"+"itcast"; fos.write(str.getBytes()); fos.close(); } }
2.2 字節輸入流InputStream
經過前面的學習,咱們能夠把內存中的數據寫出到文件中,那如何想把內存中的數據讀到內存中,咱們經過InputStream能夠實現。InputStream此抽象類,是表示字節輸入流的全部類的超類。,定義了字節輸入流的基本共性功能方法。內存
int read():讀取一個字節並返回,沒有字節返回-1.
int read(byte[]): 讀取必定量的字節數,並存儲到字節數組中,返回讀取到的字節數。
2.2.1 FileInputStream類
InputStream有不少子類,其中子類FileInputStream可用來讀取文件內容。
FileInputStream 從文件系統中的某個文件中得到輸入字節。資源
構造方法
2.2.2 FileInputStream類讀取數據read方法(只讀純英文,有空介紹一下讀中文問題)
在讀取文件中的數據時,調用read方法,實現從文件中讀取數據
從文件中讀取數據,代碼演示:
public class FileInputStreamDemo { public static void main(String[] args) throws IOException { File file = new File("c:\\file.txt"); //建立一個字節輸入流對象,必須明確數據源,其實就是建立字節讀取流和數據源相關聯。 FileInputStream fis = new FileInputStream(file); //讀取數據。使用 read();一次讀一個字節。 int ch = 0; while((ch=fis.read())!=-1){ System.out.println("ch="+(char)ch); } // 關閉資源。 fis.close(); } }
2.2.3 讀取數據read(byte[])方法
在讀取文件中的數據時,調用read方法,每次只能讀取一個,太麻煩了,因而咱們能夠定義數組做爲臨時的存儲容器,這時能夠調用重載的read方法,一次能夠讀取多個字符。
public class FileInputStreamDemo2 { public static void main(String[] args) throws IOException { /* * 演示第二個讀取方法, read(byte[]); */ File file = new File("c:\\file.txt"); // 建立一個字節輸入流對象,必須明確數據源,其實就是建立字節讀取流和數據源相關聯。 FileInputStream fis = new FileInputStream(file); //建立一個字節數組。 byte[] buf = new byte[1024];//長度能夠定義成1024的整數倍。 int len = 0; while((len=fis.read(buf))!=-1){ System.out.println(new String(buf,0,len)); } fis.close(); } }
2.3 字節流練習
既然會了文件的讀和寫操做了,那麼咱們就要在這個基礎上進行更爲複雜的操做。使用讀寫操做完成文件的複製。
2.3.1 複製文件
原理;讀取一個已有的數據,並將這些讀到的數據寫入到另外一個文件中。
public class CopyFileTest { public static void main(String[] args) throws IOException { //1,明確源和目的。 File srcFile = new File("c:\\YesDir\test.JPG"); File destFile = new File("copyTest.JPG"); //2,明確字節流 輸入流和源相關聯,輸出流和目的關聯。 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //3, 使用輸入流的讀取方法讀取字節,並將字節寫入到目的中。 int ch = 0; while((ch=fis.read())!=-1){ fos.write(ch); } //4,關閉資源。 fos.close(); fis.close(); } }
上述代碼輸入流和輸出流之間是經過ch這個變量進行數據交換的。
上述複製文件有個問題,每次都從源文件讀取一個,而後在寫到指定文件,接着再讀取一個字符,而後再寫一個,一直這樣下去。效率極低。
2.3.2 臨時數組方式複製文件
上述代碼複製文件效率過低了,而且頻繁的從文件讀數據,和寫數據,能不能一次多把文件中多個數據都讀進內容中,而後在一次寫出去,這樣的速度必定會比前面代碼速度快。
public class CopyFileByBufferTest { public static void main(String[] args) throws IOException { File srcFile = new File("c:\\YesDir\test.JPG"); File destFile = new File("copyTest.JPG"); // 明確字節流 輸入流和源相關聯,輸出流和目的關聯。 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //定義一個緩衝區。 byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len);// 將數組中的指定長度的數據寫入到輸出流中。 } // 關閉資源。 fos.close(); fis.close(); } }
第3章 緩衝流
在咱們學習字節流與字符流的時候,你們都進行過讀取文件中數據的操做,讀取數據量大的文件時,讀取的速度會很慢,很影響咱們程序的效率,那麼,我想提升速度,怎麼辦?
Java中提升了一套緩衝流,它的存在,可提升IO流的讀寫速度
緩衝流,根據流的分類分類字節緩衝流與字符緩衝流。
在基礎班咱們已經學習過字符緩衝流了,那麼今天學習一下字節緩衝流。
3.1 字節緩衝流
字節緩衝流根據流的方向,共有2個
寫入數據到流中,字節緩衝輸出流 BufferedOutputStream
讀取流中的數據,字節緩衝輸入流 BufferedInputStream
它們的內部都包含了一個緩衝區,經過緩衝區讀寫,就能夠提升了IO流的讀寫速度
3.1.1 字節緩衝輸出流BufferedOutputStream
經過字節緩衝流,進行文件的讀寫操做 寫數據到文件的操做
構造方法
public BufferedOutputStream(OutputStream out)建立一個新的緩衝輸出流,以將數據寫入指定的底層輸出流。
public class BufferedOutputStreamDemo01 { public static void main(String[] args) throws IOException { //寫數據到文件的方法 write(); } /* * 寫數據到文件的方法 * 1,建立流 * 2,寫數據 * 3,關閉流 */ private static void write() throws IOException { //建立基本的字節輸出流 FileOutputStream fileOut = new FileOutputStream("abc.txt"); //使用高效的流,把基本的流進行封裝,實現速度的提高 BufferedOutputStream out = new BufferedOutputStream(fileOut); //2,寫數據 out.write("hello".getBytes()); //3,關閉流 out.close(); } }
3.1.2 字節緩衝輸入流 BufferedInputStream
剛剛咱們學習了輸出流實現了向文件中寫數據的操做,那麼,如今咱們完成讀取文件中數據的操做
構造方法
public BufferedInputStream(InputStream in)
/* * 從文件中讀取數據 * 1,建立緩衝流對象 * 2,讀數據,打印 * 3,關閉 */ private static void read() throws IOException { //1,建立緩衝流對象 FileInputStream fileIn = new FileInputStream("abc.txt"); //把基本的流包裝成高效的流 BufferedInputStream in = new BufferedInputStream(fileIn); //2,讀數據 int ch = -1; while ( (ch = in.read()) != -1 ) { //打印 System.out.print((char)ch); } //3,關閉 in.close(); }
3.1.3 複製單級文件夾
/* * 數據源:e:\\demo * 目的地:e:\\test * * 分析: * A:封裝目錄 * B:獲取該目錄下的全部文本的File數組 * C:遍歷該File數組,獲得每個File對象 * D:把該File進行復制 */ public class CopyFolderDemo { public static void main(String[] args) throws IOException { // 封裝目錄 File srcFolder = new File("e:\\demo"); // 封裝目的地 File destFolder = new File("e:\\test"); // 若是目的地文件夾不存在,就建立 if (!destFolder.exists()) { destFolder.mkdir(); } // 獲取該目錄下的全部文本的File數組 File[] fileArray = srcFolder.listFiles(); // 遍歷該File數組,獲得每個File對象 for (File file : fileArray) { // System.out.println(file); // 數據源:e:\\demo\\e.mp3 // 目的地:e:\\test\\e.mp3 String name = file.getName(); // e.mp3 File newFile = new File(destFolder, name); // e:\\test\\e.mp3 copyFile(file, newFile); } } private static void copyFile(File file, File newFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(newFile)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read(bys)) != -1) { bos.write(bys, 0, len); } bos.close(); bis.close(); } }
歡迎關注菜鳥永恆,天天進步一小點。