第十四章、IO流
阿新 • • 發佈:2020-12-13
IO流
1. 位元組流
定義:是按照位元組進行操作的,每次讀取一個位元組 位元組流抽象基類: InputStream(位元組輸入流)/OutputStream(位元組輸出流) 子類: (1).FileInputStream public int read() 從此輸入流中讀取一個數據位元組。 public int read(byte[] b) 從此輸入流中將最多 b.length 個位元組的資料讀入一個 byte 陣列中。 public int read(byte[] b,int off,int len) 從此輸入流中將最多 len 個位元組的資料讀入一個 byte 陣列中。off:目標陣列 b 中的起始偏移量。 (2).FileOutputStream public void write(int b) public void write(byte[] b) public void write(byte[] b,int off,int len) 指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入此檔案輸出流。 (3).BufferedInputStream:位元組緩衝輸入流 (4).BufferedOutputStream:位元組緩衝輸出流
-
FileInputStream(位元組輸入流)使用方法
package demo1; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; public class InputStreamDemo { public static void main(String[] args) throws Exception { // 1.建立位元組輸入流物件 InputStream is = new FileInputStream("鬥破蒼穹.txt"); // 2.對檔案進行讀取 System.out.println("----------第一種讀取方式-----------"); // read()方法 當檔案讀取到末尾的時候返回-1 long startTime = System.currentTimeMillis();int num = 0; while((num = is.read()) != -1){ System.out.print((char)num); } long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); System.out.println("----------第二種讀取方式-----------"); long startTime = System.currentTimeMillis(); // 緩衝區 比作一個可以放1024本書的書架 byte[] by = new byte[1024]; int num = 0; String str = new String(); while((num = is.read(by)) != -1){ // 將讀取到的位元組序列轉換成字元序列 str = new String(by,0,num); } System.out.println(str); long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); System.out.println("----------第三種讀取方式-----------"); long startTime = System.currentTimeMillis(); // 緩衝區 比作一個可以放1024本書的書架 byte[] by = new byte[1024]; int num = 0; String str = new String(); while((num = is.read(by,0,by.length)) != -1){ // 將讀取到的位元組序列轉換成字元序列 str = new String(by,0,num); } System.out.println(str); long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); // 關閉流並釋放資源 is.close(); } }
-
FileOutputStream(位元組輸出流)使用方法
package demo1; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; public class OutputStreamDemo { public static void main(String[] args) throws Exception { // 建立位元組流輸出物件 如果存在就不會建立檔案 // OutputStream os = new FileOutputStream("鬥破蒼穹.txt"); // 預設寫入資料時會覆蓋原來的資料 // 向檔案中追加內容 OutputStream os = new FileOutputStream("鬥破蒼穹.txt",true); // 追加 // 第一種方式寫入:public void write(int b) os.write(97); // 第二種方式寫入:public void write(byte[] b) for (int i = 0; i < 3; i++) { os.write("helloworld\n".getBytes()); } // 第三種方式寫入:public void write(byte[] b,int off,int len) os.write("helloworld".getBytes(), 0, 3); // 釋放資源 // 關閉此檔案輸出流並釋放與此流有關的所有系統資源 os.close(); // 為什麼一定要close呢? // A.讓流物件變成垃圾,這樣就可以被垃圾回收機制回收了 // B.通知系統去釋放該檔案相關資源 } }
-
FileInputStream/FileOutputStream案例
package demo1; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; /* * 1.實現對.txt結尾的檔案進行復制 * 2.實現對音訊檔案進行復制 * * * 檔案複製的過程 * 1.先讀取檔案 * 2.再向指定目錄輸出檔案 */ public class InToOutDemo { public static void main(String[] args) throws Exception { // 1.先讀取檔案 FileInputStream fis = new FileInputStream("鬥破蒼穹.txt"); // 2.再向指定目錄輸出檔案 FileOutputStream fos = new FileOutputStream("E:\\豆豆.txt"); byte[] by = new byte[1024]; int num = 0; // 讀取檔案 while((num = fis.read(by)) != -1){ // 美都區一次向指定檔案中寫入一次 fos.write(by,0,num); fos.flush(); // 重新整理緩衝區 } // 關閉流 fis.close(); fos.close(); } }
-
BufferedInputStream(位元組緩衝輸入流)使用方法
package demo2; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; public class bufferedInputStreamDemo { public static void main(String[] args) throws Exception { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("鬥破蒼穹.txt")); byte[] by = new byte[1024]; int num = 0; // 讀取資料 while((num = bis.read(by)) != -1){ System.out.println(new String(by, 0, num)); } // 釋放資源 bis.close(); } }
-
BufferedOutputStream(位元組緩衝輸出流)使用方法
package demo2; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class bufferedOutputStreamDemo { public static void main(String[] args) throws Exception { // 複雜構造方法寫法(屬於脫褲子放屁) FileOutputStream fos = new FileOutputStream("鬥破蒼穹.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); // 簡單寫法 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("鬥破蒼穹.txt")); bos.write("hello world".getBytes()); // 釋放資源 bos.close(); } }
-
BufferedInputStream/BufferedOutputStream案例
package demo2; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; /* * 需求:實現對音訊檔案複製 * * 位元組流四種方式複製檔案 * 基本位元組流一次讀寫一個位元組:38549毫秒 * 基本位元組流一次讀寫一個位元組陣列:61毫秒 * 高效位元組流一次讀寫一個位元組:329毫秒 * 高效位元組流一次讀寫一個位元組陣列:37毫秒 */ public class CopyMp4Demo { public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis(); method1("D:\\復活-喬任樑.mp3", "復活.mp3"); method2("D:\\復活-喬任樑.mp3", "復活.mp3"); method3("D:\\復活-喬任樑.mp3", "復活.mp3"); method4("D:\\復活-喬任樑.mp3", "復活.mp3"); long endTime = System.currentTimeMillis(); System.out.println("總耗時:"+(endTime - startTime)); } // 基本位元組流一次讀寫一個位元組 public static void method1(String src,String dest) throws Exception{ FileInputStream fis = new FileInputStream(src); FileOutputStream fos = new FileOutputStream(dest); int num = 0; while((num = fis.read()) != -1){ fos.write(num); } fis.close(); fos.close(); } // 基本位元組流一次讀寫一個位元組陣列: public static void method2(String src,String dest) throws Exception{ FileInputStream fis = new FileInputStream(src); FileOutputStream fos = new FileOutputStream(dest); int num = 0; byte[] by = new byte[1024]; while((num = fis.read(by)) != -1){ fos.write(by,0,num); } fis.close(); fos.close(); } // 高效位元組流一次讀寫一個位元組: public static void method3(String src,String dest) throws Exception{ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest)); int num = 0; while((num = bis.read()) != -1){ bos.write(num); } bis.close(); bos.close(); } // 高效位元組流一次讀寫一個位元組陣列: public static void method4(String src,String dest) throws Exception{ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest)); int num = 0; byte[] by = new byte[1024]; while((num = bis.read(by)) != -1){ bos.write(by,0,num); } bis.close(); bos.close(); } }
2. 字元流
定義:是按照字元進行操作的,每次讀取一個字元
字元流抽象基類:
Reader(字元輸入流)/Writer(字元輸出流)
子類:
(1).FileReader
public int read()
讀取單個字元
public int read(char[] b)
將字元讀入陣列
public int read(char[] b,int off,int len)
將字元讀入陣列的某一部分。
(2).FileWriter
public void write(String str)
public void write(String str,int off,int len)
public void write(int c)
public void writer(char[] cbuf)
public void write(char[] b,int off,int len)
指定 char 陣列中從偏移量 off 開始的 len 個位元組寫入此檔案輸出流。
(3).BufferedReader:字元緩衝輸入流
(4).BufferedWriter:字元緩衝輸出流
-
FileReader(字元輸入流)使用方法
package demo3; import java.io.FileReader; import java.io.IOException; import java.io.Reader; public class ReaderDemo { public static void main(String[] args) throws IOException { Reader re = new FileReader("鬥破蒼穹.txt"); int num = 0; char[] ch = new char[1024]; while((num = re.read(ch)) != -1){ String str = new String(ch,0,num); System.out.println(str); } re.close(); } }
-
FileWriter(字元輸出流)使用方法
package demo3; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; public class WriterDemo { public static void main(String[] args) throws IOException { // 1.建立字元流輸出流 Writer w = new FileWriter("鬥破蒼穹.txt"); w.write("第一章 世界之大,唯我獨尊\n"); w.write("第二章 別bb了,趕緊上車\n"); // 注意:如果不關閉流或者不重新整理緩衝區,那麼資料會一直存在記憶體中 w.flush(); w.close(); } }
-
FileReader/FileWriter案例
package demo3; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; /* * 字元流實現檔案複製 */ public class ReadToWriteDemo { public static void main(String[] args) throws IOException { // 1.利用字元流讀取檔案 Reader r = new FileReader("鬥破蒼穹.txt"); // 2.利用字元流寫入檔案 Writer w = new FileWriter("鬥破2.txt"); int num = 0; // 讀取 每次讀取一個字元(2個位元組) while((num = r.read()) != -1){ // 寫入指定檔案 w.write(num); w.flush(); // 重新整理緩衝區 } r.close(); w.close(); } }
-
BufferedWriter/BufferedReader使用方法
package demo4; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* * 利用你緩衝區市西南對文字檔案的複製 * * BufferedWriter基本用法 * BufferedReader基本用法 * 字元緩衝流複製文字檔案 * * 特殊功能 * BufferedWriter * void newLine() * BufferedReader * void readLine() * 字元緩衝流特殊功能複製文字檔案 */ public class BufferedWriterToBufferedReader { public static void main(String[] args) throws IOException { // 建立字元緩衝輸入流 讀取檔案 BufferedReader br = new BufferedReader(new FileReader("鬥破蒼穹.txt")); // 建立字元緩衝輸入流 寫入檔案 BufferedWriter bw = new BufferedWriter(new FileWriter("新鬥破蒼穹.txt")); String str = null; // newLine() 按行讀取,依次讀取一個文字行 // 讀到末尾使返回null while((str = br.readLine()) != null){ // 寫入指定檔案 bw.write(str); // 換行 bw.newLine(); // 重新整理快取區 bw.flush(); } // 釋放資源 br.close(); bw.close(); } }
3. 位元組流和字元流區別
位元組流在操作時本身不會用到緩衝區(記憶體),是檔案本身直接操作的,而字元流在操作時使用了緩衝區,通過快取區再操作檔案。
下面以兩個寫檔案的操作為主進行比較,位元組和字元流操作完成後都不關閉輸出流。
4. PrintStream流
(1)基本概念
java.io.PrintStream類用於方便地列印各種格式的資料。
(2)常用的方法
PrintStream(OutputStream out)
- 根據引數指定的引用構造物件
- 其中OutputStream類是抽象類,實參需要傳遞子類的物件。
void print(String s)
- 用於列印引數指定的字串。
void println(String x)
- 用於列印字串並終止該行。
-
PrintStream流使用方法
package demo5; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; public class TestPrintStream { public static void main(String[] args){ // 1.構造PrintStream型別的物件與E:\\a.txt檔案關聯 PrintStream ps; try { ps = new PrintStream(new FileOutputStream("E:\\a.txt")); // 2.向輸出流中寫入字串內容 ps.print("hello"); System.out.println("寫入資料成功!"); // 3.關閉流並釋放有關的資源 ps.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
-
PrintStream流案例
package demo5; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.Date; import java.text.SimpleDateFormat; /* * 練習:使用PrintStream和BufferedReader類來生成聊天記錄 * 要求:不斷提示使用者要輸入傳送的內容,判斷是否為"bye",若是則結束 * 輸入:若不是"bye",則寫入檔案E:\\a.txt */ public class TestChatMsg { public static void main(String[] args) throws IOException{ try { // System.in 是InputStream型別的,代表鍵盤輸入 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintStream ps = new PrintStream(new FileOutputStream("E:\\a.txt")); boolean flg = true; while(true){ // 1提示使用者輸入要傳送的內容並記錄到變數中 System.out.println("請"+(flg?"張三":"李四")+"輸入要傳送的內容:"); String str = br.readLine(); // 2.判斷使用者輸入的內容是否為"bye",若是則結束輸入 if(str.equalsIgnoreCase("bye")){ System.out.println("聊天結束!"); break; } // 獲取當前的系統時間 Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String format = sdf.format(d); ps.println(format+(flg?"張三:":"李四:")+str); flg = !flg; } br.close(); ps.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
5. 記憶體操作流
操作位元組陣列
ByteArrayInputStream
ByteArrayOutputStream
操作字元陣列
CharArrayReader
CharArrayWrite
操作字串
StringReader
StringWriter
package demo7;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/*
* 演示記憶體操作流
* 記憶體操作流一般用於處理臨時檔案,因為臨時檔案不需要儲存,使用後就可以刪除
*/
public class TestByteArray {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write("hello world".getBytes());
byte[] bs = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bs);
int num = 0;
while((num = bis.read()) != -1){
System.out.println((char)num);
}
bos.close();
bis.close();
}
}
6. 序列化流
序列化流:指把Java物件轉換為位元組序列的過程為物件的
ObjectOutputStream
writeObject(Object obj) 方法可以對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。
反序列化流:指把位元組序列恢復為Java物件的過程稱為物件的反序列化
ObjectInputStream
readObject()方法源輸入流讀取位元組序列,再把它們反序列化成為一個物件,並將其返回。
使用transient關鍵字宣告不需要序列化的成員變數
注意:只有實現了Serializable或Externalizable介面的類的物件才能被序列化,否則丟擲異常。
-
實體物件
package demo8; import java.io.Serializable; /* * Goods實體類 */ public class Goods implements Serializable{ private static final long serialVersionUID = -3195823797427025499L; private int id; private String name; // transient 被他修飾的變數不參與序列化 private transient double price; public int getId() { return id; } public Goods() { super(); } public Goods(int id, String name, double price) { super(); this.id = id; this.name = name; this.price = price; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Goods [id=" + id + ", name=" + name + ", price=" + price + "]"; } }
-
實現類
package demo8; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /* * 演示序列化與反序列化 * * 序列化:ObjectOutputStream * 反序列化:ObjectInputStream * * 需求: * 1.建立Goods實體類 * 2.建立序列化流,將Goods物件序列化到專案object.txt檔案中,做到資料持久化儲存 * 3.利用反序列化將物件讀取並打印出來 * * 注意:使用序列化流被序列化的物件一定要實現序列化介面(Serializable) */ public class TestObject { public static void main(String[] args) throws Exception { Goods goods = new Goods(1001, "葵花寶典", 12.12); // 建立序列化流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")); // 將Goods物件序列化到專案下object.txt中持久化儲存 oos.writeObject(goods); // java.io.NotSerializableException:demo8.goods 物件類序列化異常 oos.close(); // 建立反序列化流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt")); // 讀取檔案中的物件資訊 Goods g = (Goods)ois.readObject(); ois.close(); System.out.println(g); } }
7. 練習
- 在D盤根目錄下建立一個資料夾temp1,並建立300個檔案,檔名從x000.txt到x299.txt,每個檔案裡寫入一個10000以內的隨機數。
- 刪除D:\temp1下奇數號的檔案,如x001.txt、x003.txt…..x299.txt,留下偶數號的所有檔案。
- 讀D:\temp1下所有的檔案,計算其中所有數字的和,顯示最終的計算結果。
- 使用BufferReader和BufferWriter,讀data.txt檔案,並在所有行的資料前加上“行號+空格”後寫到data1.txt檔案中。
- 建立一個元素是Book的ArrayList物件bookList1,並插入10個物件,資料隨意。對這個ArrayList物件bookList1實現序列化,其中abs屬性不參與序列化,存入檔案D:\serial\book.dat。