1.基本概念
(1)16種流介紹
(2)Input_OutputStream繼承結構圖
(3)Reader_Writer繼承結構圖
2.基本操作
2.1.基本讀操作- read()方法
(1)

1 /* 2 java.io.InputStream 3 java.io.FileInputStream 4 按照字節方式讀取 5 */ 6 import java.io.*; 7 class FileInputStreamtest 8 { 9 public static void main(String[] args) 10 { 11 FileInputStream fis = null; 12 try{ 13 //文件路徑 14 //String filePath="text1.txt";//相對路徑,在當前路徑下 15 // String filePath="D:\\Sourcecode\\Editplus\\java\\file\\text1.txt"; 16 String filePath="D:/Sourcecode/Editplus/java/file/text1.txt"; 17 fis = new FileInputStream(filePath); 18 //讀 19 int i1 = fis.read();//以字節方式讀,只能讀取一個字母 20 System.out.println(i1);//輸出字母對應的ASSICK值 21 22 }catch(FileNotFoundException e){ 23 e.printStackTrace(); 24 }catch(IOException e){ 25 e.printStackTrace(); 26 }finally{ 27 //保證流一定釋放,使用try..catch語句 28 if(fis!=null){ 29 try{ 30 fis.close(); 31 }catch(IOException e){ 32 e.printStackTrace(); 33 } 34 } 35 36 } 37 } 38 }
(2)

1 import java.io.*; 2 class FileInputStreamtest02 3 { 4 public static void main(String[] args) throws Exception 5 { 6 FileInputStream fis = new FileInputStream("text1.txt"); 7 int temp =0; 8 while((temp=fis.read())!=-1){ 9 System.out.println(temp); 10 } 11 fis.close(); 12 } 13 }
(3)

1 /* 2 int read(byte[] bytes) 3 讀取之前在內存中准備一個byte數組,每次讀取多個字節存儲到byte數組中,一次讀取多個字節。 4 效率高 5 text1.txt文件中的內容為abcdefg 6 */ 7 import java.io.*; 8 class FileInputStreamtest03 9 { 10 public static void main(String[] args) throws Exception 11 { 12 FileInputStream fis = new FileInputStream("text1.txt"); 13 byte[] bytes = new byte[3];//每次讀3個字節 14 15 int i1 = fis.read(bytes); 16 System.out.println(new String(bytes));//abc 17 int i2 = fis.read(bytes); 18 System.out.println(new String(bytes));//def 19 int i3 = fis.read(bytes); 20 System.out.println(new String(bytes));//gef 21 System.out.println(new String(bytes,0,i3));//g 22 int i4 = fis.read(bytes); 23 24 //int類型的i表示每次讀取的字節數 25 System.out.println(i1);//3 26 System.out.println(i2);//3 27 System.out.println(i3);//1 28 System.out.println(i4);//-1 29 30 } 31 }
(4)

1 /* 2 循環讀取 3 text1.txt文件中的內容為abcdefg 4 */ 5 import java.io.*; 6 class FileInputStreamtest04 7 { 8 public static void main(String[] args) throws Exception 9 { 10 FileInputStream fis = new FileInputStream("text1.txt"); 11 byte[] bytes = new byte[1024];//每次讀3個字節 12 int temp =0; 13 while((temp=fis.read(bytes))!=-1){ 14 System.out.print(new String(bytes,0,temp)); 15 } 16 fis.close(); 17 } 18 }
2.2.available()方法和skip()方法

1 import java.io.*; 2 /* 3 available()方法:返回流中剩余的字節數 4 skip(n)方法:跳過n個字節不讀取 5 text1.txt文件中的內容為abcdefg 6 */ 7 class FileInputStreamtest05 8 { 9 public static void main(String[] args) throws Exception 10 { 11 FileInputStream fis = new FileInputStream("text1.txt"); 12 System.out.println(fis.available());//7 13 System.out.println(fis.read());//97 14 System.out.println(fis.available());//6 15 fis.skip(2);//跳過兩個字節不讀取 16 System.out.println(fis.read());//100 17 fis.close(); 18 19 } 20 }
2.3.寫入數據的方法

1 /* 2 java.io.OutputStream 3 java.io.FileOutputStream;文件字節輸出流 4 將計算機內存中的數據寫入硬盤文件中 5 */ 6 import java.io.*; 7 class FileOutputStreamtest01 8 { 9 public static void main(String[] args) 10 { 11 FileOutputStream fos=null; 12 try{ 13 //fos= new FileOutputStream("text2.txt");//多次運行,會覆蓋源文件內容 14 fos= new FileOutputStream("text2.txt",true);//追加寫入 15 //寫入 16 String msg = "Hello World"; 17 //將String轉換成byte數組 18 byte[] bytes = msg.getBytes(); 19 fos.flush();//強制寫入,保證數據完全寫入硬盤,與、需要刷新 20 //fos.write(bytes);//強制寫入,寫入全部 21 fos.write(bytes,0,3);//寫入3個,將byte數組部分寫入 22 23 }catch(Exception e){ 24 e.printStackTrace(); 25 }finally{ 26 if(fos!=null){ 27 try{ 28 fos.close(); 29 }catch(Exception e){ 30 e.printStackTrace(); 31 } 32 } 33 34 } 35 } 36 }
2.4.文件的復制粘貼
FileInputStream FileOutputStream

1 /* 2 文件的復制粘貼 3 */ 4 import java.io.*; 5 class Copy01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileInputStream fis = new FileInputStream("text1.txt"); 10 FileOutputStream fos = new FileOutputStream("text2.txt"); 11 //讀,寫 12 byte[] bytes = new byte[1024]; 13 int temp = 0; 14 while((temp=fis.read(bytes))!=-1){ 15 fos.write(bytes,0,temp); 16 } 17 fis.close(); 18 fos.close(); 19 20 } 21 }
fileReader,FileWriter

1 /* 2 文件復制,只能復制純文本文件 3 */ 4 import java.io.*; 5 class Copy02 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileReader fr = new FileReader("text1.txt");//一個已經存在的文件 10 FileWriter fw = new FileWriter("text4.txt");//運行后復制出一個文件 11 char [] chars = new char[1024]; 12 int temp =0; 13 while((temp=fr.read(chars)) != -1){ 14 fw.write(chars,0,temp); 15 } 16 fw.flush(); 17 fr.close(); 18 fw.close(); 19 } 20 }
2.5.FileWriter()方法寫入文件

1 /* 2 java.io.Writer; 3 java.io.OutputStream;轉換流 4 java.io.FileWriter文件字符輸出流 5 */ 6 import java.io.*; 7 class FileWritertest01 8 { 9 public static void main(String[] args) throws Exception 10 { 11 FileWriter fw = new FileWriter("text3.txt",true); 12 fw.write("寫入文件");//直接寫入字符串 13 char [] chars = {'寫','入','文','件','{','。','、',}; 14 fw.write(chars,0,6); 15 fw.flush(); 16 fw.close(); 17 } 18 } 19 /* 20 運行結果: 21 寫入文件寫入文件{。 22 */
2.6.BufferedReader帶有緩沖區的字符輸入流

1 /* 2 readLine() 方法一次讀取一行文本 3 */ 4 import java.io.*; 5 class BufferedReadertest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 BufferedReader br = new BufferedReader(new FileReader("BufferedReadertest01.java")); 10 String temp = null; 11 while((temp=br.readLine())!=null){ 12 System.out.println(temp); 13 } 14 br.close(); 15 } 16 }

1 /* 2 readLine() 方法一次讀取一行文本 3 */ 4 import java.io.*; 5 class BufferedReadertest02 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileInputStream fis = new FileInputStream("BufferedReadertest01.java");//文件字節輸入流 10 InputStreamReader brs = new InputStreamReader(fis); //將字節流轉換成字符流 11 BufferedReader br = new BufferedReader(brs);//brs是字符流 12 //將上面的語句合並 13 // BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("BufferedReadertest01.java"))); 14 String temp = null; 15 while((temp=br.readLine())!=null){ 16 System.out.println(temp); 17 } 18 br.close(); 19 } 20 }
3.文件輸入/輸出流
1.FileinputStream 與FileOutputStream類將文件讀出與寫入。
2.FileReader和FileWriter將文件讀出與寫入。
二者的區別:
使用FileOutputStream類向文件中寫入數據與使用FileinputStream類從文件中將內容讀出來都存在一點不足,即這兩個類都只有提供了對字節或字節數組的讀取方法,由於漢子在文件中占用兩個字節,如果使用字節流,讀取不好可能會出現亂碼的情況,此時采用字符流Reader或Writer類即可避免這種現象。
FileReader和FileWriter字符流對應了FileinputStream 與FileOutputStream類,FileReader流順序地讀取文件,只要不關閉流,每次調用read()方法就順序地讀取源文件中其余內容,直到源的末尾或流被關閉。

1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 5 public class FileTest3 { 6 7 public static void main(String[] args) { 8 File file = new File("D:/Sourcecode/Java/file/word1.txt"); 9 try{ 10 FileOutputStream out = new FileOutputStream(file); 11 byte buy[] ="風住塵香花已盡,日晚倦梳頭。物是人非事事休,欲語淚先流。".getBytes(); 12 out.write(buy); 13 out.close(); 14 }catch(Exception e){ 15 e.printStackTrace(); 16 } 17 try{ 18 FileInputStream inputStream = new FileInputStream(file); 19 byte byt[] = new byte[1024]; 20 int len =inputStream.read(byt); 21 System.out.print("文件中的信息是: "+ new String(byt,0,len)); 22 inputStream.close(); 23 }catch(Exception e){ 24 e.printStackTrace(); 25 } 26 } 27 28 }

1 import java.awt.*; 2 import java.awt.event.*; 3 import java.io.*; 4 5 import javax.swing.*; 6 7 public class Ftest extends JFrame { // 創建類,繼承Jframe類 8 private JScrollPane scrollPane; 9 private static final long serialVersionUID = 1L; 10 private JPanel jContentPane = null; // 創建面板對象 11 private JTextArea jTextArea = null; // 創建文本域對象 12 private JPanel controlPanel = null; // 創建面板對象 13 private JButton openButton = null; // 創建按鈕對象 14 private JButton closeButton = null; // 創建按鈕對象 15 16 private JTextArea getJTextArea() { 17 if (jTextArea == null) { 18 jTextArea = new JTextArea(); 19 } 20 return jTextArea; 21 } 22 23 private JPanel getControlPanel() { 24 if (controlPanel == null) { 25 FlowLayout flowLayout = new FlowLayout(); 26 flowLayout.setVgap(1); 27 controlPanel = new JPanel(); 28 controlPanel.setLayout(flowLayout); 29 controlPanel.add(getOpenButton(), null); 30 controlPanel.add(getCloseButton(), null); 31 } 32 return controlPanel; 33 } 34 35 private JButton getOpenButton() { 36 if (openButton == null) { 37 openButton = new JButton(); 38 openButton.setText("寫入文件"); // 修改按鈕的提示信息 39 openButton 40 .addActionListener(new java.awt.event.ActionListener() { 41 // 按鈕的單擊事件 42 public void actionPerformed(ActionEvent e) { 43 // 創建文件對象 44 File file = new File("word.txt"); 45 try { 46 // 創建FileWriter對象 47 FileWriter out = new FileWriter(file); 48 // 獲取文本域中文本 49 String s = jTextArea.getText(); 50 out.write(s); // 將信息寫入磁盤文件 51 out.close(); // 將流關閉 52 } catch (Exception e1) { 53 e1.printStackTrace(); 54 } 55 } 56 }); 57 } 58 return openButton; 59 } 60 61 private JButton getCloseButton() { 62 if (closeButton == null) { 63 closeButton = new JButton(); 64 closeButton.setText("讀取文件"); // 修改按鈕的提示信息 65 closeButton 66 .addActionListener(new java.awt.event.ActionListener() { 67 // 按鈕的單擊事件 68 public void actionPerformed(ActionEvent e) { 69 File file = new File("word.txt"); // 創建文件對象 70 try { 71 // 創建FileReader對象 72 FileReader in = new FileReader(file); 73 char byt[] = new char[1024]; // 創建char型數組 74 int len = in.read(byt); // 將字節讀入數組 75 // 設置文本域的顯示信息 76 jTextArea.setText(new String(byt, 0, len)); 77 in.close(); // 關閉流 78 } catch (Exception e1) { 79 e1.printStackTrace(); 80 } 81 } 82 }); 83 } 84 return closeButton; 85 } 86 87 public Ftest() { 88 super(); 89 initialize(); 90 } 91 92 private void initialize() { 93 this.setSize(300, 200); 94 this.setContentPane(getJContentPane()); 95 this.setTitle("JFrame"); 96 } 97 98 private JPanel getJContentPane() { 99 if (jContentPane == null) { 100 jContentPane = new JPanel(); 101 jContentPane.setLayout(new BorderLayout()); 102 jContentPane.add(getScrollPane(), BorderLayout.CENTER); 103 jContentPane.add(getControlPanel(), BorderLayout.SOUTH); 104 } 105 return jContentPane; 106 } 107 108 public static void main(String[] args) { // 主方法 109 Ftest thisClass = new Ftest(); // 創建本類對象 110 thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 111 thisClass.setVisible(true); // 設置該窗體為顯示狀態 112 } 113 /** 114 * @return 115 */ 116 protected JScrollPane getScrollPane() { 117 if (scrollPane == null) { 118 scrollPane = new JScrollPane(); 119 scrollPane.setViewportView(getJTextArea()); 120 } 121 return scrollPane; 122 } 123 }
4.帶緩存的輸入輸出流
由於Java中的字符是Unicode編碼,是雙字節的,writeBytes只是將字符串中的每一個字符的低字節內容寫入目標設備中,而writeChars將字符串的每一個字符的兩個字節的內容都寫到目標設備中,WriterUTF將字符串按照UTF編碼后的字節長度寫入目標設備,然后才是每一字節的UTF編碼。
DataInputStream類只提供了一個readUTF()方法返回字符串,這是因為要在一個連續的字節流讀取一個字符串,如果沒有特殊的標記作為一個字符串的結尾,並且不知道這個字符串的長度,就無法知道讀取到什么位置才是這個字符串的結束,DataOutputStream類中只有writeUTF()方法向目標設備中寫入字符串的長度,所以也能准確的讀回寫入的字符串。
例:

1 public class Dataintandout { 2 3 public static void main(String[] args) { 4 try{ 5 //創建FileOutputStream對象 6 FileOutputStream fStream = new FileOutputStream("D:/Sourcecode/Java/file/word4.txt"); 7 //創建DataOutputStream對象 8 DataOutputStream dStream = new DataOutputStream(fStream); 9 dStream.writeUTF("使用writeUTF()方法寫入數據:不是無心惜落花,落花無意戀春花"); 10 dStream.writeChars("使用writeChars()方法寫入數據:今朝春去誰家落,把酒臨風千種恨"); 11 dStream.writeBytes("使用writeBytes()方法寫入數據:昨日寒鴉一片愁,柳塘新綠卻溫柔"); 12 dStream.close(); 13 //創建FileInputStream對象 14 FileInputStream fileInputStream = new FileInputStream("D:/Sourcecode/Java/file/word4.txt"); 15 //創建DataInputStream對象 16 DataInputStream dataInputStream = new DataInputStream(fileInputStream); 17 System.out.println(dataInputStream.readUTF());//將文件輸出 18 }catch(Exception e){ 19 e.printStackTrace(); 20 } 21 } 22 23 }
運行結果:使用writeUTF()方法寫入數據:不是無心惜落花,落花無意戀春花
打開文本內容如下:
盡管在記事本中出現亂碼的情況,但在控制台屏幕上仍然能正確顯示內容。但如果使用writeChars()方法和writeBytes()方法寫入字符串,就不能正確讀出。
帶緩存的輸入輸出流
緩存是I/o的一種性能優化,帶緩存為I/o流增加了內存緩存區,有了緩存區,使得在流上執行skip(),mark(),reset()方法成為可能。
4.1.BufferedinputStream與BufferedOutputStream類
1. BufferedinputStream有兩種構造方法:
(1)BufferedinputStream(inputStream in)
(2)BufferedinputStream(inputStream in,int size)
第一種形式的構造方法創建了一個帶有32個字節的緩存流,第二種形式的構造方法按指定的大小來創建緩存區。一個最優的緩存區的大小,取決於它所在的操作系統,可用的內存空間以及機器配置。從構造方法可以看出,BufferedinputStream對象位於InputStream類對象之前
2.BufferedOutputStream類有兩種構造方法
(1)BufferedOutputStream(OutputStream in)
(2)BufferedOutputStream(OutputStream in,int size)
第一種構造方法創建了一個有32個字節的緩存區域,第二種構造方法以指定的大小來創建緩存區
注意:flush()方法是用於即使在緩存區域沒有存滿的情況下,也將緩存區的內容強制寫入到外設,習慣上稱這個過程為刷新,flush()方法只對使用緩存區的OutputStream類的子類有效,當調用close()方法時,系統在關閉之前,也將緩存區中的信息刷新到磁盤文件中。
4.2.BufferedReader與BufferedWriter類
BufferedReader類常用的方法如下。
(1)read()方法:讀取單個字符。
(2)readLine()方法:讀取一個文本行,並將其返回為字符串。若無數據可讀,則返回null。BufferedWriter類中的方法都返回void,常用的方法如下:
a、 write(String s,int off, int len)方法:寫入字符串的某一部分。
b、flush()方法:刷新該流得緩存。
c、newline()方法:寫入一個行分隔符。
例:

1 package file; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileReader; 7 import java.io.FileWriter; 8 9 public class Student { 10 public static void main(String []args){ 11 String contet[] = {"夜夜思君情斷腸,緣何人不雙,夜夜痴迷空自傷,月隨人彷徨"}; 12 //創建文件對象 13 File file = new File("D:/Sourcecode/Java/file/word2.txt"); 14 try{ 15 //創建FileWriter類對象 16 FileWriter fw = new FileWriter(file); 17 //創建bufferWriter類對象 18 BufferedWriter buffw = new BufferedWriter(fw); 19 for(int k = 0;k < contet.length;k++){ 20 buffw.write(contet[k]);//將字符串數組中的元素寫入到磁盤文件中 21 buffw.newLine();//將數組中的單個元素以單行的形式寫入文件 22 } 23 buffw.close(); //將BufferReader流關閉 24 fw.close(); //將FileWriter流關閉 25 }catch(Exception e){ 26 e.printStackTrace(); 27 } 28 try{ 29 //創建FileReader類對象 30 FileReader fr = new FileReader(file); 31 //創建BufferReader類對象 32 BufferedReader bufr = new BufferedReader(fr); 33 String s = null;//創建字符串對象 34 int i = 0; 35 //如果文件文本行數不為空,則進入循環 36 while((s = bufr.readLine()) != null){ 37 i++; 38 System.out.println("第"+i+"行"+s); 39 } 40 bufr.close(); 41 fr.close(); 42 43 }catch(Exception e){ 44 e.printStackTrace(); 45 } 46 } 47 }
運行結果:
第1行夜夜思君情斷腸,緣何人不雙,
第2行夜夜痴迷空自傷,月隨人彷徨
5.序列化和反序列化-對象流
5.1.序列化-ObjectOutputStream
序列化就是將堆中的Java對象存入到硬盤中。

1 import java.io.Serializable;//可序列化的,沒有任何方法的標識接口 2 class User implements Serializable 3 { 4 String name; 5 User(String name){ 6 this.name = name; 7 } 8 public String toString(){ 9 return "User[name="+name+"]"; 10 } 11 }
注: User 實現了 Serializable 接口, JVM會給該類添加自動一個屬性:序列化版本號。(可以自定義一個序列化版本號,則系統不會再成序列化版本號,
也不會出現版本號不相同的情況)
例:自定義序列化版本號
static final long seriaVersionUID="xxxxxxxxx";
如果不讓某個屬性參與序列化,可以使用transient關鍵字修飾;
transient String name;

1 /* 2 java.io.ObjectOutputStream;序列化Java對象到硬盤 3 java.io.ObjectInputStream;將硬盤中的數據反序列化到jvm內存 4 */ 5 import java.io.*; 6 class ObjectOutputStreamtest01 7 { 8 public static void main(String[] args) throws Exception 9 { 10 //創建Java對象 11 User u1 = new User("Java對象"); 12 //創建輸出流(序列化流)jvm中的java對象狀態保存到硬盤中 13 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("text6.txt")); 14 //寫 15 oos.writeObject(u1); 16 oos.flush(); 17 oos.close(); 18 } 19 }
5.2.反序列化-ObjectInputStream
反序列化就是將硬盤中的對象恢復到內存中。

1 /* 2 反序列化 3 */ 4 import java.io.*; 5 class ObjectInputStreamtest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 //創建反序列化流 10 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("text6.txt")); 11 //反序列化 12 Object o = ois.readObject(); 13 System.out.println(o); 14 ois.close(); 15 } 16 } 17 /* 18 User[name=Java對象] 19 請按任意鍵繼續. . . 20 */
6.File
6.1.特點
Java.io.File;File類和流無關,不能通過該類完成文件的讀和寫,File是文件和目錄路徑名的抽象表示形式,File代表的是硬盤上的文件夾和文件名。
6.2.常用方法

1 import java.io.*; 2 /* 3 判斷指定路徑或文件是否存在,不存在則創建 4 */ 5 class Filetest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 //相對路徑 10 File f1 = new File("text1.txt"); 11 //絕對路徑 12 File f2 = new File("D:\\Sourcecode\\Editplus\\java"); 13 14 System.out.println(f1.exists());//true 15 System.out.println(f2.exists());//true 16 17 File f3 = new File("D:\\Sourcecode\\Editplus\\java\\AA"); 18 System.out.println(f3.exists());//false 19 //如果不存在則創建 20 if(!f3.exists()){ 21 //創建目錄 22 //f3.mkdir(); 23 //創建文件 24 f3.createNewFile(); 25 } 26 File f4 = new File("D:/a/b/c"); 27 if(!f4.exists()){ 28 //創建多重目錄 29 f4.mkdirs(); 30 } 31 } 32 }