生活中,你確定經歷過這樣的場景。當你編輯一個文本文件,忘記了 ctrl+s ,可能文件就白白編輯了。當你電腦上插入一個U盤,能夠把一個視頻,拷貝到你的電腦硬盤裏。那麼數據都是在哪些設備上的呢?鍵盤、內存、硬盤、外接設備等等。java
咱們把這種數據的傳輸,能夠看作是一種數據的流動,按照流動的方向,之內存爲基準,分爲 輸入input 和 輸出output ,即流向內存是輸入流,流出內存的輸出流。數組
Java中I/O操做主要是指使用 java.io 包下的內容,進行輸入、輸出操做。輸入也叫作讀取數據,輸出也叫作做寫出數據。app
根據數據的流向分爲:輸入流和輸出流。ide
格局數據的類型分爲:字節流和字符流。函數
一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時一 樣如此。因此,字節流能夠傳輸任意文件數據。在操做流的時候,咱們要時刻明確,不管使用什麼樣的流對象,底層傳輸的始終爲二進制數據。學習
java.io.OutputStream 抽象類是表示字節輸出流的全部類的超類,將指定的字節信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。測試
public void close()
:關閉此輸出流並釋放與此流相關聯的任何系統資源。public void flush()
:刷新此輸出流並強制任何緩衝的輸出字節被寫出。public void write(byte[] b)
:將 b.length字節從指定的字節數組寫入此輸出流。public void write(byte[] b, int off, int len)
:從指定的字節數組寫入 len字節,從偏移量 off開始輸出到此輸出流。public abstract void write(int b)
:將指定的字節輸出流。 OutputStream 有不少子類,咱們從最簡單的一個子類開始。優化
java.io.FileOutputStream
類是文件輸出流,用於將數據寫出到文件。this
構造方法編碼
public FileOutputStream(File file)
:建立文件輸出流以寫入由指定的 File對象表示的文件。public FileOutputStream(String name)
: 建立文件輸出流以指定的名稱寫入文件。寫出字節數據
FileOutputStream fos = new FileOutputStream("a.txt"); // 【write(int b)】 // 寫入的十進制會轉換成二進制存儲到a.txt // 讀取文件時,文件會按照指定的編碼格式轉換爲對應的內容 fos.write(97); // 寫入→97→110 0001→內存→讀取→110 0001→ASCII→a fos.write(98); // 【 write(byte[] b)】 byte[]bs = {97,98,99,101,102}; fos.write(bs); // 【字符串轉換字節數組getBytes()】 fos.write("你好".getBytes()); // 【write(byte[] b, int off, int len)指定長度的字節數組】 fos.write("xyz".getBytes(),0,2); fos.close();
數據追加續寫
問題:
解決方案
代碼
FileOutputStream fos = new FileOutputStream("a.txt",true); fos.write("我是新追加的數據".getBytes()); fos.close();
寫出換行
系統中的換行
代碼
FileOutputStream fos = new FileOutputStream("b.txt",true); for (int i = 0; i < 10; i++) { fos.write(("\r\n第" + i +"行數據:" + i*100).getBytes() ); } fos.close();
java.io.InputStream
抽象類是表示字節輸入流的全部類的超類,能夠讀取字節信息到內存中。它定義了字節輸入 流的基本共性功能方法。
public void close()
:關閉此輸入流並釋放與此流相關聯的任何系統資源。
public abstract int read()
: 從輸入流讀取數據的下一個字節。
public int read(byte[] b)
: 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。
使用數組讀取,每次讀取多個字節,減小了系統間的IO操做次數,從而提升了讀寫的效率,建議開發中使
用。
close方法,當完成流的操做時,必須調用此方法,釋放系統資源。
java.io.FileInputStream 類是文件輸入流,從文件中讀取字節。
構造方法
FileInputStream(File file)
: 經過打開與實際文件的鏈接來建立一個 FileInputStream ,該文件由文件系 統中的 File對象 fifile命名。FileInputStream(String name)
: 經過打開與實際文件的鏈接來建立一個 FileInputStream ,該文件由文件 系統中的路徑名 name命名。讀取字節數據代碼
// 建立字節輸入流對象 FileInputStream fis = new FileInputStream("day07_IO//a.txt"); //【一次讀取一個字節】 // 循環讀取文件中的字節 int len = 0; while ((len=fis.read())!=-1){ System.out.print((char)len); } // 結果:ABC // 【一次讀取多個字節】 // 將字節轉換爲字符串new Strig(bytes[]bts,int offset,int length); byte[]bts = new byte[10]; int len2 = 0; while ((len2=fis.read(bts))!=-1){ System.out.println(new String(bts,0,len2)); } fis.close();
原理
代碼
public static void main(String[] args) throws IOException { long s = System.currentTimeMillis(); // 建立輸入流對象-用來讀取本地文件 FileInputStream fis = new FileInputStream("D:\\test.jpg"); // 建立輸出流對象-用來寫入本地文件 FileOutputStream fos = new FileOutputStream("day07_IO\\test_copy.jpg"); // 建立字節數組,一次從本地讀取多個字節 byte[]bts = new byte[1024]; int len = 0; // 表示讀取的有效字節個數 // 循環讀取本地數據 while ((len=fis.read(bts))!=-1){ // 把實際讀取的字節寫入本地文件 fos.write(bts,0,len); } // 關閉輸出流資源 fos.close(); // 關閉輸入流資源 fis.close(); long e = System.currentTimeMillis(); System.out.println("複製成功!"); System.out.println("共耗時" + (e-s)+"毫秒"); }
當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是由於
一箇中文字符可能佔用多個字節存儲。因此Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文
件。
public void close()
:關閉此流並釋放與此流相關聯的任何系統資源。public int read()
: 從輸入流讀取一個字符。public int read(char[] cbuf)
: 從輸入流中讀取一些字符,並將它們存儲到字符數組 cbuf中 。java.io.FileReader
類是讀取字符文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區
注意事項
字符編碼:字節與字符的對應規則。Windows系統的中文編碼默認是GBK編碼表。 idea中UTF-8
字節緩衝區:一個字節數組,用來臨時存儲字節數據。
構造函數
代碼
public static void main(String[] args) throws IOException { FileReader reader = new FileReader("day07_IO//a.txt"); // 【一次讀取一個字符】 int len = 0; while ((len = reader.read())!=-1) { System.out.print((char)len); } // 【一次讀取多個字符】 char[]chs = new char[1024]; int len = 0; while ((len = reader.read(chs))!=-1) { System.out.print(new String(chs,0,len)); // new String(char[]chars,int offset,int count); } reader.close(); }
java.io.Writer 抽象類是表示用於寫出字符流的全部類的超類,將指定的字符信息寫出到目的地。它定義了字節
輸出流的基本共性功能方法。
void write(int c)
寫入單個字符。void write(char[] cbuf)
寫入字符數組。abstract void write(char[] cbuf, int off, int len)
寫入字符數組的某一部分,offff數組的開始索引,len 寫的字符個數。void write(String str)
寫入字符串。void write(String str, int off, int len)
寫入字符串的某一部分,offff字符串的開始索引,len寫的字符個 數。void flush()
刷新該流的緩衝。void close()
關閉此流,但要先刷新它。java.io.FileWriter
類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。
構造函數:
FileWriter(File file)
: 建立一個新的 FileWriter,給定要讀取的File對象。FileWriter(String fileName)
: 建立一個新的 FileWriter,給定要讀取的文件的名稱。代碼:
public static void main(String[] args) throws IOException { // 建立輸出字符流對象 FileWriter fw = new FileWriter("day07_IO\\b.txt"); fw.write("你好"); fw.flush(); // flush將緩衝區的數據刷新到文件中,可繼續寫入 fw.write("我好"); fw.flush(); fw.write("你們好"); fw.close();// close 將緩衝區中的數據刷新到文件中,而且會釋放輸出流對象,後繼沒法繼續輸出 fw.write("真好"); // 異常 // 建立輸出流對象,向指定的文件中追加寫入數據 FileWriter fw2 = new FileWriter("day07_IO\\b.txt",true); for (int i = 0; i < 10; i++) { fw2.write("你好,新的世界!" + i + "\r\n"); } fw2.close(); }
注意事項:
處理方式:try-catch-finally
代碼:
public static void main(String[] args) { // 建立輸出流對象,向指定的文件中追加寫入數據 FileWriter fw2 = null; try{ fw2 = new FileWriter("day07_IO\\b.txt",true); for (int i = 0; i < 10; i++) { fw2.write("你好,新的世界!" + i + "\r\n"); } }catch (IOException e) { e.printStackTrace(); }finally { if(fw2!=null){ try { fw2.close(); } catch (IOException e) { e.printStackTrace(); } } } }
處理方式:JDK7優化後的 try-with-resource 語句,該語句確保了每一個資源在語句結束時關閉。所謂的資源 (resource)是指在程序完成後,必須關閉的對象。
try (建立流對象語句,若是多個,使用';'隔開) { // 讀寫數據 } catch (IOException e) { e.printStackTrace(); }
代碼:
public static void main(String[] args) { // 建立輸出流對象,向指定的文件中追加寫入數據 try(FileWriter fw2 = new FileWriter("day07_IO\\b.txt",true)){ for (int i = 0; i < 100; i++) { fw2.write("你好,新的世界!" + i + "\r\n"); } }catch (IOException e) { e.printStackTrace(); } }
JDK9中 try-with-resource 的改進,對於引入對象的方式,支持的更加簡潔。被引入的對象,一樣能夠自動關閉, 無需手動close
格式
// 被final修飾的對象 final Resource resource1 = new Resource("resource1"); // 普通對象 Resource resource2 = new Resource("resource2"); // 引入方式:直接引入 try (resource1; resource2) { // 使用對象 } catch (IOException e) { e.printStackTrace(); }
代碼
public static void main(String[] args) throws IOException { // 建立輸出流對象,向指定的文件中追加寫入數據 FileWriter fw2 = new FileWriter("day07_IO\\b.txt",true); try(fw2){ for (int i = 0; i < 100; i++) { fw2.write("你好,新的世界!" + i + "\r\n"); } }catch (IOException e) { e.printStackTrace(); } }
java.util.Properties
繼承於 Hashtable ,來表示一個持久的屬性集。它使用鍵值結構存儲數據,每一個鍵及其
對應值都是一個字符串。該類也被許多Java類使用,好比獲取系統屬性時, System.getProperties 方法就是返回
一個 Properties 對象。
構造方法:public Properties()
:建立一個空的屬性列表。
基本的存儲方法
public Object setProperty(String key, String value)
: 保存一對屬性。public String getProperty(String key)
:使用此屬性列表中指定的鍵搜索屬性值。public Set<String> stringPropertyNames()
:全部鍵的名稱的集合。與流相關的方法
public void load(InputStream inStream)
: 從字節輸入流中讀取鍵值對。
代碼
public static void main(String[] args) throws IOException { // 獲取系統相關的信息 System.out.println(System.getProperties()); // 建立一個屬性集合 Properties pro = new Properties(); pro.setProperty("張三","180"); pro.setProperty("李四","189"); pro.setProperty("王五","178"); pro.setProperty("趙六","188"); // 讀取屬性集合中的數據 Set set = pro.keySet(); for (Object o : set) { System.out.println(pro.get(o)); } // 把集合中臨時的數據輸出到硬盤中 // pro.store(new FileWriter("day07_IO\\data.txt"),"save data"); // 讀取本地文件中的數據(鍵值對的方式)到屬性集合中 Properties pro2 = new Properties(); pro2.load(new FileReader("day07_IO\\data.txt")); System.out.println(pro2); }
緩衝流,也叫高效流,是對4個基本的 FileXxx 流的加強,因此也是4個流,按照數據類型分類:
緩衝流的基本原理,是在建立流對象時,會建立一個內置的默認大小的緩衝區數組,經過緩衝區讀寫,減小系統IO次數,從而提升讀寫的效率。
構造方法
public BufferedInputStream(InputStream in)
:建立一個 新的緩衝輸入流。public BufferedOutputStream(OutputStream out)
: 建立一個新的緩衝輸出流。代碼測試
基本方式一次讀寫一個字節
public static void main(String[] args) throws IOException { long s = System.currentTimeMillis(); // 建立字節輸入流,讀取本地文件數據 FileInputStream fis = new FileInputStream("D:\\test.jpg"); // 建立字節輸出流,向本地文件寫入數據 FileOutputStream fos = new FileOutputStream("day08_IO\\test01.jpg"); // 定義變量表示讀取的字節 int len = 0; // 循環遍歷讀取本地文件 while ((len=fis.read())!=-1) { // 把讀取的字節寫入本地 fos.write(len); } // 關閉輸出流 fos.close(); // 關閉輸入流 fis.close(); long e = System.currentTimeMillis(); System.out.println("共耗時:" + (e-s) + "毫秒"); // 161毫秒 }
基本方式一次讀寫多個字節
public static void main(String[] args) throws IOException { long s = System.currentTimeMillis(); // 建立字節輸入流,讀取本地文件數據 FileInputStream fis = new FileInputStream("D:\\test.jpg"); // 建立字節輸出流,向本地文件寫入數據 FileOutputStream fos = new FileOutputStream("day08_IO\\test02.jpg"); // 定義變量表示讀取的有序字節個數 int len = 0; // 定義字節數組,表示一次要讀取的字節數 byte[]bts = new byte[1024]; // 循環遍歷讀取本地文件 while ((len=fis.read(bts))!=-1) { // 把讀取的字節寫入本地 fos.write(bts,0,len); } // 關閉輸出流 fos.close(); // 關閉輸入流 fis.close(); long e = System.currentTimeMillis(); System.out.println("共耗時:" + (e-s) + "毫秒"); // 共耗時:7毫秒 }
緩衝流方式默認讀寫方式
public static void main(String[] args) throws IOException { long s = System.currentTimeMillis(); // 建立字節緩衝流輸入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\test.jpg")); // 建立字節緩衝流輸出流f BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day08_IO\\test03.jpg")); // 循環讀取本地數據 int len = 0; while ((len = bis.read())!=-1){ bos.write(len); } bos.close(); bis.close(); long e = System.currentTimeMillis(); System.out.println("共耗時:" + (e-s) + "毫秒"); // 共耗時:8毫秒 }
緩衝流方式指定字節讀取
public static void main(String[] args) throws IOException { long s = System.currentTimeMillis(); // 建立字節緩衝流輸入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\test.jpg")); // 建立字節緩衝流輸出流f BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day08_IO\\test04.jpg")); // 循環讀取本地數據 int len = 0; byte[]bts = new byte[1024]; while ((len = bis.read(bts))!=-1){ bos.write(bts,0,len); } bos.close(); bis.close(); long e = System.currentTimeMillis(); System.out.println("共耗時:" + (e-s) + "毫秒"); // 共耗時:6毫秒 }
構造方法
public BufferedReader(Reader in)
:建立一個 新的緩衝輸入流。public BufferedWriter(Writer out)
: 建立一個新的緩衝輸出流。特有方法:字符緩衝流的基本方法與普通字符流調用方式一致,再也不闡述,咱們來看它們具有的特有方法。
public String readLine()
: 讀一行文字。public void newLine()
: 寫一行行分隔符,由系統屬性定義符號。代碼:
public static void main(String[] args) throws IOException { // 建立字符緩衝輸出流 BufferedWriter bw = new BufferedWriter( new FileWriter("day08_IO\\01.txt")); for (int i = 0; i < 100; i++) { bw.write("貴在堅持!不僅是說說!" + i); bw.newLine(); } bw.close(); // 建立字符緩衝輸入流 BufferedReader br = new BufferedReader(new FileReader("day08_IO\\01.txt")); String line; while ((line=br.readLine())!=null){ System.out.println(line); } br.close(); }
需求:讀取本地文件中的文本,並排序後從新寫入本地新的文件中
2.JavaScript 1.Java 4.PHP 6.C# 7.C 3.C++ 5.VB
代碼:
public static void main(String[] args) throws IOException { // 建立HashMap對象存放讀取的本地數據 HashMap<String,String > map = new HashMap<>(); // 建立字符緩衝區輸入流,逐行讀取本地數據 BufferedReader br = new BufferedReader(new FileReader("day08_IO\\02.txt")); String line; while ((line=br.readLine())!=null) { // 分割 String[]strs = line.split("\\."); map.put(strs[0],strs[1]); } br.close(); // 建立字符輸出流 BufferedWriter bw = new BufferedWriter(new FileWriter("day08_IO\\03.txt")); for (int i = 1; i <= map.size(); i++) { bw.write(i +"."+ map.get(String.valueOf(i))); bw.newLine(); } bw.close(); }
計算機中儲存的信息都是用二進制數表示的,而咱們在屏幕上看到的數字、英文、標點符號、漢字等字符是二進制數轉換以後的結果。按照某種規則,將字符存儲到計算機中,稱爲編碼 。反之,將存儲在計算機中的二進制數按照某種規則解析顯示出來,稱爲解碼 。好比說,按照A規則存儲,一樣按照A規則解析,那麼就能顯示正確的文本f符號。反之,按照A規則存儲,再按照B規則解析,就會致使亂碼現象。
字符編碼Character Encoding : 就是一套天然語言的字符與二進制數之間的對應規則。
字符集charset:也叫編碼表。是一個系統支持的全部字符的集合,包括各國家文字、標點符號、圖形符號、數字等。
計算機要準確的存儲和識別各類字符集符號,須要進行字符編碼,一套字符集必然至少有一套字符編碼常見字符集有ASCII字符集、GBK字符集、Unicode字符集等。可見,當指定了編碼,它所對應的字符集天然就指定了,因此編碼纔是咱們最終要關心的。
ASCII字符集
ISO-8859-1字符集
GBxxx字符集
GB18030:最新的中文碼錶。收錄漢字70244個,採用多字節編碼,每一個字能夠由1個、2個或4個字節組成。支持中國國內少數民族的文字,同時支持繁體漢字以及日韓漢字等。
Unicode字符集
在IDEA中,使用 FileReader 讀取項目中的文本文件。因爲IDEA的設置,都是默認的 UTF-8 編碼,因此沒有任何問題。可是,當讀取Windows系統中建立的文本文件時,因爲Windows系統的默認是GBK編碼,就會出現亂碼。
public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\a.txt"); int len = 0; while((len=fr.read())!=-1){ System.out.print((char)len); } fr.close(); } // 結果:��� 亂碼
那麼如何讀取GBK編碼的文件呢?
轉換流 java.io.InputStreamReader
,是Reader的子類,是從字節流到字符流的橋樑。它讀取字節,並使用指定的字符集將其解碼爲字符。它的字符集能夠由名稱指定,也能夠接受平臺的默認字符集。
構造方法
InputStreamReader(InputStream in)
: 建立一個使用默認字符集的字符流。InputStreamReader(InputStream in, String charsetName)
: 建立一個指定字符集的字符流。代碼
public static void main(String[] args) throws IOException { InputStreamReader fr = new InputStreamReader(new FileInputStream("D:\\a.txt"),"gbk"); int len = 0; while((len=fr.read())!=-1){ System.out.print((char)len); } fr.close(); } // 結果:你好
轉換流 java.io.OutputStreamWriter ,是Writer的子類,是從字符流到字節流的橋樑。使用指定的字符集將字符 編碼爲字節。它的字符集能夠由名稱指定,也能夠接受平臺的默認字符集。
構造函數
OutputStreamWriter(OutputStream in)
: 建立一個使用默認字符集的字符流。OutputStreamWriter(OutputStream in, String charsetName)
: 建立一個指定字符集的字符流。代碼
public static void main(String[] args) throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day08_IO\\04.txt"),"gbk"); osw.write("你好"); osw.close(); }
Java 提供了一種對象序列化的機制。用一個字節序列能夠表示一個對象,該字節序列包含該 對象的數據 、 對象的 類型 和 對象中存儲的屬性 等信息。字節序列寫出到文件以後,至關於文件中持久保存了一個對象的信息。 反之,該字節序列還能夠從文件中讀取回來,重構對象,對它進行反序列化。 對象的數據 、 對象的類型 和 對象中 存儲的數據 信息,均可以用來在內存中建立對象。看圖理解序列化:
java.io.ObjectOutputStream
類,將Java對象的原始數據類型寫出到文件,實現對象的持久存儲。
構造方法
public ObjectOutputStream(OutputStream out)
: 建立一個指定OutputStream的ObjectOutputStream。序列化操做
一個對象要想序列化,必須知足兩個條件:
該類必須實現java.io.Serializable
接口, Serializable
是一個標記接口,不實現此接口的類將不會使任何狀態序列化或反序列化,會拋出 NotSerializableException
。
該類的全部屬性必須是可序列化的。若是有一個屬性不須要可序列化的,則該屬性必須註明是瞬態的,使用 transient
關鍵字修飾。
代碼:
public class Person implements Serializable { // 實現Serializable,表示可序列化 private String name; private int age; private transient int height; // 該屬性不會被序列化 public Person(String name, int age, int height) { this.name = name; this.age = age; this.height = height; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } @Override public String toString() { return "姓名:" + name + ",年齡:"+ age + ",身高:" + height; } }
寫出對象方法
public final void writeObject (Object obj) : 將指定的對象寫出
代碼
public static void main(String[] args) throws IOException { // 建立一我的類對象 Person p = new Person("張三",18,180); // 建立一個序列化輸出流對象 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("day08_IO\\person.txt")); // 把指定的對象序列化後寫入本地文件 os.writeObject(p); os.close(); System.out.println("save a Object success"); }
ObjectInputStream反序列化流,將以前使用ObjectOutputStream序列化的原始數據恢復爲對象。
構造方法
public ObjectInputStream(InputStream in);
: 建立一個指定InputStream的ObjectInputStream。
反序列化操做1
若是能找到一個對象的class文件,咱們能夠進行反序列化操做,調用 ObjectInputStream 讀取對象的方法:
代碼:
public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream os = new ObjectInputStream(new FileInputStream("day08_IO\\person.txt")); Person p = (Person) os.readObject(); System.out.println(p); // 姓名:張三,年齡:18,身高:0 os.close(); } // 對於JVM能夠反序列化對象,它必須是可以找到class文件的類。若是找不到該類的class文件,則拋出一個ClassNotFoundException 異常。
反序列化操做2
另外,當JVM反序列化對象時,能找到class文件,可是class文件在序列化對象以後發生了修改,那麼反序列化操 做也會失敗,拋出一個 InvalidClassException 異常。發生這個異常的緣由以下:
解決方案
代碼
public class Person implements Serializable { // 實現Serializable,表示可序列化 // 定義序列化版本號 private static final long serialVersionUID = 10L; private String name; public int age; private transient int height; // 該屬性不會被序列化 public Person(String name, int age, int height) { this.name = name; this.age = age; this.height = height; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } @Override public String toString() { return "姓名:" + name + ",年齡:"+ age + ",身高:" + height; } }
平時咱們在控制檯打印輸出,是調用 print 方法和 println 方法完成的,這兩個方法都來自於 java.io.PrintStream 類,該類可以方便地打印各類數據類型的值,是一種便捷的輸出方式。
構造方法
public PrintStream(String fileName)
: 使用指定的文件名建立一個新的打印流。System.out 就是 PrintStream 類型的,只不過它的流向是系統規定的,打印在控制檯上。不過,既然是流對象, 咱們就能夠玩一個"小把戲",改變它的流向。
代碼
public static void main(String[] args) throws IOException { // 打印在控制檯 System.out.println("你好"); // 建立打印流,流向指定的本地文件 PrintStream ps = new PrintStream(new FileOutputStream("day08_IO\\print.txt")); // 設置System.out的打印流向指向ps System.setOut(ps); // 後續打印在print.txt文件中 System.out.println("你好1"); System.out.println("你好2"); System.out.println("你好3"); ps.close(); }