1.基本IO操做 java
有時候咱們編寫的程序除了自身會定義一些數據信息外,還須要引用外界的數據,或是將自身的數據發送到外界,這時咱們須要使用輸入與輸出。數組
1)輸入與輸出 緩存
2)節點流與處理流app
按照流是否直接與特定的地方(如磁盤、內存、設備等)相連,分爲節點流和處理流兩類。ide
處理流的構造方法老是要帶一個其餘的流對象作參數,一個流對象通過其餘流的屢次包裝,稱爲流的連接。this
3)IS和OS經常使用方法編碼
InputStream是全部字節輸入流的父類,其定義了基礎的讀取方法,以下:spa
OutputStream是全部字節輸出流的父類,其定義了基礎的寫出方法,以下:code
4)建立FOS對象(重寫模式)對象
FileOutputStream是文件的字節輸出流,使用該流能夠以字節爲單位將數據寫入文件。
注意點:若指定的文件已經包含內容,那麼當使用FOS對其寫入數據時,會將該文件中原有的數據所有清楚。
案例1:FOS覆蓋方式寫文件
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("fos.txt");
String str = "Hello,World";
byte[] date = str.getBytes();
fos.write(date);
System.out.println("寫出完畢");
fos.close();
}
}
5)建立FOS對象(追加模式)
若想在文件的原有數據以後追加新數據,則須要如下構造方法建立FOS:
以上兩個構造方法中,第二個參數若爲true,那麼經過該FOS寫出的數據都是在文件末尾追加的。
案例2:FOS追加模式寫文件
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("fos.txt",true);
String str = "Hello,World";
byte[] date = str.getBytes();
fos.write(date);
System.out.println("寫出完畢");
fos.close();
}
}
6)建立FIS對象
FileInputStream是文件的字節輸入流,咱們使用該流能夠以字節爲單位從文件中讀取數據。FileInputStream有兩個經常使用的構造方法,以下:
案例3:FIS讀取文件數據
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
int d = -1;
while((d=fis.read())!=-1){
System.out.print((char)d);
}
fis.close();
}
}
/*
* 運行結果:
* Hello,WorldHello,World
*/
7)read()和write(int d)方法
FileInputStream繼承自InputStream,其提供了以字節爲單位讀取文件數據的方法read。
FileOutputStream繼承自OutputStream,其提供了以字節爲單位向文件寫數據的方法write。
8)read(byte[] d)和write(byte[] d)方法
FileInputStream也支持批量讀取字節數據的方法:
FileOutputStream也支持批量寫出字節數據的方法:
2.緩衝流
1)BOS基本工做原理
在向硬件設備作寫出操做時,增大寫出次數無疑會下降寫出效率,爲此咱們可使用緩衝輸出流來一次性批量寫出若干數據減小寫出次數來提升寫出效率。BufferedOutputStream緩衝輸出流內部維護着一個緩衝區,每當咱們向該流寫數據時,都會先將數據存入緩衝區,當緩衝區已滿時,緩衝流會將數據一次性所有寫出。
案例4:BOS演示
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
//建立緩衝字節輸出流
FileOutputStream fos = new FileOutputStream("fos.txt");
//全部字節被存入緩衝區,等待一次性寫出
BufferedOutputStream bos = new BufferedOutputStream(fos);
String str = "Hello Java";
byte[] date = str.getBytes();
bos.write(date);
//關閉流以前,緩衝輸出流會將緩衝區內容一次性寫出
bos.close();
System.out.println("寫出完畢");
}
}
2)BOS的flush方法
使用緩衝輸出流能夠提升寫出效率,可是這也存在一個問題,就是寫出數據缺少即時性。有時須要在執行完某些寫出操做後,就但願將這些數據確實寫出,而不是在緩衝區中保存知道緩衝區滿後才寫出。這就須要flush方法了。
案例5:flush演示
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("fos.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); String str = "Hello Java"; byte[] date = str.getBytes(); bos.write(date); bos.flush(); //強制將緩衝區已緩存數據一次性寫出 System.out.println("寫出完畢"); bos.close(); } }
3)BIS基本工做原理
在讀取數據時若以字節爲單位讀取數據,會致使讀取次數過於頻繁從而大大下降讀取效率。爲此咱們能夠經過提升一次讀取的字節數量減小讀寫次數來提升讀取的效率。BufferedInputStream是緩衝字節輸入流。其內部維護着一個緩衝區(字節數組),使用該流在讀取一個字節時,該流會盡量多的一次性讀取若干字節並存入緩衝區,而後逐一的將字節返回,直到緩衝區中的數據被所有讀取完畢,會再次讀取若干字節從而反覆,這樣就減小了讀取的次數,提升了讀取效率。
BIS是一個處理流,該流爲咱們提供了緩衝功能。
案例6:BIS演示
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
//建立緩衝字節輸入流
FileInputStream fis = new FileInputStream("fos.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
int d = -1;
//緩衝讀入,實際上並不是是一個字節一個字節從文件讀取
while((d=bis.read())!=-1){
System.out.println(d);
}
bis.close();
}
}
3.對象流
1)對象序列化
對象是存在於內存中的。有時候咱們須要將對象保存到硬盤上或者將對象傳輸到另外一臺計算機上等,這時須要將對象轉換爲一個字節序列,而這個過程就成爲對象序列化。相反,這樣一個字節序列須要將其轉換爲對應的對象,這個過程成爲對象的反序列化。
2)OOS實現對象序列化
ObjectOutputStream是用來對對象進行序列化的輸出流,方法以下:
3)OIS實現對象反序列化
ObjectInputStream是用來對對象進行反序列化的輸入流,方法以下:
4)Serializable接口
ObjectOutputStream在對對象進行序列化時有一個要求,就是須要序列化的對象所屬的類必須實現Serializable接口。實現該接口不須要重寫任何方法,其只是做爲可序列化的標誌。一般實現該接口的類須要提供一個常量serialVersionUID,代表該類的版本。若不顯示的聲明,在對象序列化時也會根據當前類的各個方面計算該類的默認serialVersionUID,但不一樣平臺編譯器實現有所不一樣,因此若想跨平臺,都應顯示的聲明版本號。
若是聲明的類的對象序列化存到硬盤上面,以後隨着需求的變化更改了類的屬性(增長或減小或更名),那麼當反序列化時,就會出現InvalidClassException,這樣會形成不兼容的問題。但當serialVersionUID相同時,它就會將不同的field以type的預設值反序列化,可避開不兼容性問題。
案例7:OOS序列化演示
//建立類Person import java.io.Serializable; import java.util.List; public class Person implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; private char gender; private double salary; private List<String> otherInfo; @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", salary=" + salary + ", otherInfo=" + otherInfo + "]"; } 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 char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public List<String> getOtherInfo() { return otherInfo; } public void setOtherInfo(List<String> otherInfo) { this.otherInfo = otherInfo; } }
進行序列化
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /* * 對象流是一組高級流,做用是方便讀寫java中任何對象. * 對象輸出流,能夠寫出java對象 * 工做原理:將給定java對象按照其結構轉化爲一組字節而後寫出. */ public class OOSDemo { public static void main(String[] args) throws IOException { Person p = new Person(); //引用對象並設置相關信息 p.setName("暮"); p.setAge(20); p.setGender('男'); p.setSalary(5000); List<String> otherInfo = new ArrayList<String>(); otherInfo.add("是一位詩人"); otherInfo.add("也是一位程序猿"); p.setOtherInfo(otherInfo); System.out.println(p.toString()); //開始寫出對象 FileOutputStream fos = new FileOutputStream("mu.obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); //當調用oos.writeObject時,實際上作了兩件事:將p對象按照結果轉換爲了一組字節(對象序列化) //而後再將這組字節經過FOS寫入到文件中,將數據寫入硬盤的過程成爲:持久化 oos.writeObject(p); //對象序列化 //可能會報錯: java.io.NotSerializableException,這是由於對象所屬的類沒有繼承Serializable接口,須要繼承接口並生成serialVersionUID System.out.println("序列化完成"); oos.close(); } } /* * 運行結果: * 反序列化完成 * Person [name=暮, age=20, gender=男, salary=5000.0, otherInfo=[是一位詩人, 也是一位程序猿]] */
案例8:反序列化演示
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class OISDemo { public static void main(String[] args) throws ClassNotFoundException, IOException { FileInputStream fis = new FileInputStream("mu.obj"); ObjectInputStream ois = new ObjectInputStream(fis); Person p = (Person)ois.readObject(); System.out.println(p); System.out.println("反序列化完成"); ois.close(); } } /* * 運行結果: * Person [name=暮, age=20, gender=男, salary=5000.0, otherInfo=[是一位詩人, 也是一位程序猿]] * 反序列化完成 */
5)transient關鍵字
對象在序列化後獲得的字節序列每每比較大,有時咱們在對一個對象進行序列化時能夠忽略某些沒必要要的屬性,從而對序列化後獲得的字節序列「瘦身」。
案例9:transient演示
//修改類Person import java.io.Serializable; import java.util.List; public class Person implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; private char gender; transient private double salary; //修改部分 transient private List<String> otherInfo; //修改部分 @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", salary=" + salary + ", otherInfo=" + otherInfo + "]"; } 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 char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public List<String> getOtherInfo() { return otherInfo; } public void setOtherInfo(List<String> otherInfo) { this.otherInfo = otherInfo; } }
序列化操做
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /* * 對象流是一組高級流,做用是方便讀寫java中任何對象. * 對象輸出流,能夠寫出java對象 * 工做原理:將給定java對象按照其結構轉化爲一組字節而後寫出. */ public class OOSDemo { public static void main(String[] args) throws IOException { Person p = new Person(); //引用對象並設置相關信息 p.setName("暮"); p.setAge(20); p.setGender('男'); p.setSalary(5000); List<String> otherInfo = new ArrayList<String>(); otherInfo.add("是一位詩人"); otherInfo.add("也是一位程序猿"); p.setOtherInfo(otherInfo); System.out.println(p.toString()); //開始寫出對象 FileOutputStream fos = new FileOutputStream("mu1.obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); //當調用oos.writeObject時,實際上作了兩件事:將p對象按照結果轉換爲了一組字節(對象序列化) //而後再將這組字節經過FOS寫入到文件中,將數據寫入硬盤的過程成爲:持久化 oos.writeObject(p); //對象序列化 //可能會報錯: java.io.NotSerializableException,這是由於對象所屬的類沒有繼承Serializable接口,須要繼承接口並生成serialVersionUID System.out.println("序列化完成"); oos.close(); } } /* * 運行結果: * 反序列化完成 * Person [name=暮, age=20, gender=男, salary=5000.0, otherInfo=[是一位詩人, 也是一位程序猿]] */
反序列化,會發現加上transient關鍵字的部分輸出變成了默認值輸出。
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class OISDemo { public static void main(String[] args) throws ClassNotFoundException, IOException { FileInputStream fis = new FileInputStream("mu1.obj"); ObjectInputStream ois = new ObjectInputStream(fis); Person p = (Person)ois.readObject(); System.out.println(p); System.out.println("反序列化完成"); ois.close(); } } /* * 運行結果: * Person [name=暮, age=20, gender=男, salary=0.0, otherInfo=null] * 反序列化完成 */
4.字符轉換流
1)Reader和Writer
字符流原理:
Reader經常使用方法:
Writer的經常使用方法:
2)字符轉換流原理
3)指定字符編碼
IntputStreamReader的構造方法容許咱們設置字符集:
OutputStreamWriter的構造方法:
4)OSW
案例10:OSW演示
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("demo.txt");
OutputStreamWriter writer = new OutputStreamWriter(fos,"UTF-8");
String str = "Java,你好!";
writer.write(str);
writer.close();
}
}
5)ISR
案例11:ISR演示
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("demo.txt");
InputStreamReader reader = new InputStreamReader(fis,"utf-8");
int c = -1;
while((c=reader.read())!=-1){
System.out.print((char)c);
}
reader.close();
}
}
/*
運行結果:
Java,你好!
*/
5.緩衝字符流
1)PrintWriter
PrintWriter是具備自動行刷新的緩衝字符輸出流,提供了豐富的構造方法:
PrintWriter(File file) PrintWriter(String fileName) PrintWriter(OutputStream out) PrintWriter(OutputStream out,boolean autoFlush) PrintWriter(Writer writer) PrintWriter(Writer writer,boolean autoFlush)
其中OutputStream與Writer的構造方法提供了一個可傳入boolean值參數,該參數用於表示PrintWriter是否具備自動行刷新。
2)PrintWriter的重載print和println方法
使用PrintWriter寫出字符串時咱們一般不使用Writer提供的writer()相關方法,而是使用print和println等方法,PrintWriter提供了若干重載的print和println方法,其中println方法是在寫出數據後自動追加一個系統支持的換行符。
重載方法:
void print(int i) //打印整數 void print(char c) //打印字符 void print(boolean b) //打印boolean值 void print(char[] c) //打印字符數組 void print(double d) //打印double值 void print(float t) //打印float值 void print(long l) //打印long值 void print(String str) //打印字符串
println的方法參數與上面相同。
3)使用PW輸出字符數據
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; public class PW { public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException { FileOutputStream fos = new FileOutputStream("pw.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); //建立帶有自動行刷新的PW PrintWriter pw = new PrintWriter(osw,true); pw.println("或許青春根本就沒有明天"); pw.println("青春只有如今"); System.out.println("寫出完畢"); pw.close(); } }
4)BufferedReader
BufferedReader是緩衝字符輸入流,其內部提供了緩衝區,能夠提升讀取效率。
經常使用構造方法:
BufferedReader(Reader reader)
建立一個BufferedRader緩衝字符輸入流:
FileInputStream fis = new FileInputStream("pw.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr);
由於BufferedReader在構造實例時須要傳入一個字符流,因此當咱們想基於一個字節流進行讀取時,要先將字節流轉換爲字符流後猜能夠建立緩衝字符輸入流BufferedReader。
5)BR讀取字符串
BufferedReader讀取一行字符串:
String readLine()
該方法連續讀取一行字符串,直到讀取到換行符爲止,返回的字符串中不包含該換行符,若EOF則返回null。
6)使用BR讀取一行字符串
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class BR { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("pw.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String str = null; while((str=br.readLine())!=null){ System.out.println(str); } br.close(); } }
6.案例演示
案例1:FileOutputStream寫操做演示
import java.io.FileOutputStream; import java.io.IOException; public class FOS { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("fos.txt"); String str = "若是這注定是座荒蕪的墳墓,那麼我將硬生生的變成一座美麗的花園!"; byte[] date = str.getBytes("GBK"); fos.write(date); System.out.println("寫出完畢"); fos.close(); } }
案例2:FileInputStream讀操做演示
import java.io.FileInputStream; import java.io.IOException; public class FIS { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("fos.txt"); byte[] date = new byte[100]; int len = fis.read(date); String str = new String(date,0,len,"GBK"); System.out.println(str); fis.close(); } } //運行結果:若是這注定是座荒蕪的墳墓,那麼我將硬生生的變成一座美麗的花園!
案例3:緩衝輸出流寫操做演示
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class BOSDemo { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("bos.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); String str = "東風吹落花滿路,一片相思卻似無."; byte[] date = str.getBytes("GBK"); bos.write(date); bos.flush(); System.out.println("寫出完畢"); bos.close(); } }
案例4:緩衝輸入流讀操做演示
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class BOSDemo { public static void main(String[] args) throws IOException{ FileInputStream fis = new FileInputStream("bos.txt"); BufferedInputStream bis = new BufferedInputStream(fis); byte[] date = new byte[100]; int len = bis.read(date); String str = new String(date,0,len,"GBK"); System.out.println(str); bis.close(); } } /* 運行結果: 東風吹落花滿路,一片相思卻似無. */
案例5:使用文件流複製文件
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("src.mp3"); FileOutputStream fos = new FileOutputStream("desc.mp3"); byte[] date = new byte[1024*10]; int len = -1; while((len = fis.read(date))!=-1){ fos.write(date,0,len); } System.out.println("複製完畢"); fis.close(); fos.close(); } }
案例6:緩衝流複製文件
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 緩衝流 緩衝流是一對高級流,做用是提升讀寫效率 */ public class CopyDemo02 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("music.mp3"); BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("musiccopy.mp3"); BufferedOutputStream bos = new BufferedOutputStream(fos); int d = -1; while((d=bis.read())!=-1){ bos.write(d); } System.out.println("複製完畢"); bis.close(); bos.close(); } }
案例7:OSW轉換流寫出演示
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class OSW { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("osw.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); osw.write("我從遠方來,帶着筆墨紙硯"); osw.write("我打江南走過,留下一紙舊約"); System.out.println("寫出完畢"); osw.close(); } }
案例8:ISR轉換流讀取演示
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class ISR { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("osw.txt"); InputStreamReader isr = new InputStreamReader(fis,"GBK"); int d = -1; while((d=isr.read())!=-1){ System.out.print((char)d); } isr.close(); } } /* 運行結果: 我從遠方來,帶着筆墨紙硯我打江南走過,留下一紙舊約 */
案例9:PW緩衝字符輸入流直接對文件寫操做
import java.io.FileNotFoundException; import java.io.PrintWriter; /* * PW提供了直接針對文件寫操做的構造方法: * PrintWriter(String path) * PrintWriter(File file) * 按照指定字符集對文件寫操做: * PrintWriter(String path,String csn) * PrintWriter(File file,String csn) */ public class PWDemo { public static void main(String[] args) throws FileNotFoundException { PrintWriter pw = new PrintWriter("PW.txt"); pw.println("青春是一座墳墓"); pw.println("流年走過"); pw.println("留下不一樣的墓誌銘"); System.out.println("寫出完畢"); pw.close(); } }
案例10:簡易記事本
要求:程序啓動後要求用戶輸入文件名,而後針對該文件寫入數據,每輸入一行字符串就按行寫入文件中,輸入"exit"時退出程序,最後將用戶寫出的數據讀取到控制檯上。
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.Scanner; public class Note { public static void main(String[] args) throws IOException { Scanner scan = new Scanner(System.in); System.out.println("請輸入文件名:"); String fileName = scan.nextLine(); PrintWriter pw = new PrintWriter(fileName,"GBK"); System.out.println("請輸入內容:"); while(true){ String line = scan.nextLine(); if(line.equals("exit")){ break; } pw.println(line); } System.out.println("寫出完畢,程序退出"); pw.close(); System.out.println("=====輸入內容展現====="); FileInputStream fis = new FileInputStream(fileName); InputStreamReader isr = new InputStreamReader(fis,"GBK"); BufferedReader br = new BufferedReader(isr); String line = null; while((line=br.readLine())!=null){ System.out.println(line); } br.close(); } } /* 運行結果: 請輸入文件名: note.txt 請輸入內容: 青春是一場盛宴 不繁華不罷休 exit 寫出完畢,程序退出 =====輸入內容展現===== 青春是一場盛宴 不繁華不罷休 */