流就是當(dāng)不同的介質(zhì)之間有數(shù)據(jù)交互的時候,JAVA就使用流來實現(xiàn)认罩。數(shù)據(jù)源可以是文件,還可以是數(shù)據(jù)庫续捂,網(wǎng)絡(luò)甚至是其他的程序垦垂,比如讀取文件的數(shù)據(jù)到程序中,站在程序的角度來看牙瓢,就叫做輸入流
字節(jié)流:
字節(jié)輸入流: InputStream
字節(jié)輸出流:OutputStream
以字節(jié)流的方式讀取文件:
public?class?TestStream {
????public?static?void?main(String[] args) {
????????try?{
?????//準(zhǔn)備文件lol.txt其中的內(nèi)容是AB劫拗,對應(yīng)的ASCII分別是65 66
????????????File f =new?File("d:/lol.txt");
????????????//創(chuàng)建基于文件的輸入流
????????????FileInputStream fis =new?FileInputStream(f);
????????????//創(chuàng)建字節(jié)數(shù)組,其長度就是文件的長度
????????????byte[] all =new?byte[(int) f.length()];
????????????//以字節(jié)流的形式讀取文件所有內(nèi)容
????????????fis.read(all);
????????????for?(byte?b : all) {
????????????????//打印出來是65 66
????????????????System.out.println(b);
????????????}?
????????????//每次使用完流矾克,都應(yīng)該進行關(guān)閉
????????????fis.close();?
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}??
????}
}
以字節(jié)流的方式向文件寫數(shù)據(jù):
public?class?TestStream {
????public?static?void?main(String[] args) {
????????try?{
????????????// 準(zhǔn)備文件lol2.txt其中的內(nèi)容是空的
????????????File f =?new?File("d:/lol2.txt");
??// 準(zhǔn)備長度是2的字節(jié)數(shù)組页慷,用88,89初始化,其對應(yīng)的字符分別是X,Y
????????????byte?data[] = {?88,?89?};
????????????// 創(chuàng)建基于文件的輸出流
????????????FileOutputStream fos =?new?FileOutputStream(f);
????????????// 把數(shù)據(jù)寫入到輸出流
????????????fos.write(data);
????????????// 關(guān)閉輸出流
????????????fos.close();?????????
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
流的關(guān)閉方式有3種:1胁附、try中關(guān)閉 2酒繁、finally中關(guān)閉 3、使用try()方式關(guān)閉
1控妻、在try的作用域里關(guān)閉文件輸入流州袒,一般在開發(fā)中經(jīng)常使用,這樣做有一個弊端饼暑;
如果文件不存在稳析,或者讀取的時候出現(xiàn)問題而拋出異常,那么就不會執(zhí)行這一行關(guān)閉流的代碼弓叛,存在巨大的資源占用隱患彰居。?不推薦使用
public?class?TestStream {
????public?static?void?main(String[] args) {
????????try?{
????????????File f =?new?File("d:/lol.txt");
????????????FileInputStream fis =?new?FileInputStream(f);
????????????byte[] all =?new?byte[(int) f.length()];
????????????fis.read(all);
????????????for?(byte?b : all) {
????????????????System.out.println(b);
????????????}
????????????// 在try 里關(guān)閉流
????????????fis.close();
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}
????}
}
2、這是標(biāo)準(zhǔn)的關(guān)閉流的方式
(1)首先把流的引用聲明在try的外面撰筷,如果聲明在try里面陈惰,其作用域無法抵達finally.
(2)在finally關(guān)閉之前,要先判斷該引用是否為空
(3)關(guān)閉的時候毕籽,需要再一次進行try catch處理
這是標(biāo)準(zhǔn)的嚴謹?shù)年P(guān)閉流的方式抬闯,但是看上去很繁瑣井辆,所以寫不重要的或者測試代碼的時候,都會采用上面的有隱患try的方式溶握,因為不麻煩
public?class?TestStream {
????public?static?void?main(String[] args) {
????????File f =?new?File("d:/lol.txt");
????????FileInputStream fis =?null;
????????try?{
????????????fis =?new?FileInputStream(f);
????????????byte[] all =?new?byte[(int) f.length()];
????????????fis.read(all);
????????????for?(byte?b : all) {
????????????????System.out.println(b);
????????????}
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}?finally?{
????????????// 在finally 里關(guān)閉流
????????????if?(null?!= fis)
????????????????try?{
????????????????????fis.close();
????????????????}?catch?(IOException e) {
????????????????????// TODO Auto-generated catch block
????????????????????e.printStackTrace();
????????????????}
????????}
????}
}
3杯缺、把流定義在try()里,try,catch或者finally結(jié)束的時候,會自動關(guān)閉睡榆,這種編寫代碼的方式叫做?try-with-resources萍肆, 這是從JDK7開始支持的技術(shù),所有的流胀屿,都實現(xiàn)了一個接口叫做?AutoCloseable塘揣,任何類實現(xiàn)了這個接口,都可以在try()中進行實例化宿崭。并且在try, catch, finally結(jié)束的時候自動關(guān)閉亲铡,回收相關(guān)資源。
public?class?TestStream {
????public?static?void?main(String[] args) {
????????File f =?new?File("d:/lol.txt");
????????//把流定義在try()里,try,catch或者finally結(jié)束的時候葡兑,會自動關(guān)閉
????????try?(FileInputStream fis =?new?FileInputStream(f)) {
????????????byte[] all =?new?byte[(int) f.length()];
????????????fis.read(all);
????????????for?(byte?b : all) {
????????????????System.out.println(b);
????????????}
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}
????}
}
字符流:
字符輸入流:Reader
字符輸出流:Writer
使用字符流讀取文件:
public?class?TestStream {
????public?static?void?main(String[] args) {
????????// 準(zhǔn)備文件lol.txt其中的內(nèi)容是AB
????????File f =?new?File("d:/lol.txt");
????????// 創(chuàng)建基于文件的Reader
????????try?(FileReader fr =?new?FileReader(f)) {
????????????// 創(chuàng)建字符數(shù)組奖蔓,其長度就是文件的長度
????????????char[] all =?new?char[(int) f.length()];
????????????// 以字符流的形式讀取文件所有內(nèi)容
????????????fr.read(all);
????????????for?(char?b : all) {
????????????????// 打印出來是A B
????????????????System.out.println(b);
????????????}
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
使用字符流把字符串寫入到文件:
public?class?TestStream {
????public?static?void?main(String[] args) {
????????// 準(zhǔn)備文件lol2.txt
????????File f =?new?File("d:/lol2.txt");
????????// 創(chuàng)建基于文件的Writer
????????try?(FileWriter fr =?new?FileWriter(f)) {
????????????// 以字符流的形式把數(shù)據(jù)寫入到文件中
????????????String data="abcdefg1234567890";
????????????char[] cs = data.toCharArray();
????????????fr.write(cs);
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
緩存流:
緩存字符輸入流BufferedReader, 可以一次讀取一行數(shù)據(jù)
緩存字符輸出流PrintWriter?铁孵, 可以一次寫出一行數(shù)據(jù)
使用緩存字符輸入流讀取文件:
public?class?TestStream {
????public?static?void?main(String[] args) {
????????// 準(zhǔn)備文件lol.txt其中的內(nèi)容是
????????// garen kill teemo
????????// teemo revive after 1 minutes
????????// teemo try to garen, but killed again
????????File f =?new?File("d:/lol.txt");
????????// 創(chuàng)建文件字符流
????????// 緩存流必須建立在一個存在的流的基礎(chǔ)上
????????try?(
????????????????FileReader fr =?new?FileReader(f);
????????????????BufferedReader br =?new?BufferedReader(fr);
????????????)
????????{
????????????while?(true) {
????????????????// 一次讀一行
????????????????String line = br.readLine();
????????????????if?(null?== line)
????????????????????break;
????????????????System.out.println(line);
????????????}
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
使用緩存流寫出數(shù)據(jù):
public?class?TestStream {
????public?static?void?main(String[] args) {
????????// 向文件lol2.txt中寫入三行語句
????????File f =?new?File("d:/lol2.txt");
????????try?(
????????????????// 創(chuàng)建文件字符流
????????????????FileWriter fw =?new?FileWriter(f);
????????????????// 緩存流必須建立在一個存在的流的基礎(chǔ)上??????????????
????????????????PrintWriter pw =?new?PrintWriter(fw);??????????????
????????) {
????????????pw.println("garen kill teemo");
????????????pw.println("teemo revive after 1 minutes");
????????????pw.println("teemo try to garen, but killed again");
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
有的時候锭硼,需要立即把數(shù)據(jù)寫入到硬盤,而不是等緩存滿了才寫出去蜕劝。 這時候就需要用到flush
public?class?TestStream {
????public?static?void?main(String[] args) {
????????//向文件lol2.txt中寫入三行語句
????????File f =new?File("d:/lol2.txt");
????????//創(chuàng)建文件字符流
????????//緩存流必須建立在一個存在的流的基礎(chǔ)上
????????try(FileWriter fr =?new?FileWriter(f);PrintWriter pw =?new?PrintWriter(fr);) {
????????????pw.println("garen kill teemo");
????????????//強制把緩存中的數(shù)據(jù)寫入硬盤檀头,無論緩存是否已滿
????????????????pw.flush();???????????
????????????pw.println("teemo revive after 1 minutes");
????????????????pw.flush();
????????????pw.println("teemo try to garen, but killed again");
????????????????pw.flush();
????????}?catch?(IOException e) {
????????????// TODO Auto-generated catch block
????????????e.printStackTrace();
????????}
????}
}
數(shù)據(jù)流:
DataInputStream 數(shù)據(jù)輸入流?
DataOutputStream 數(shù)據(jù)輸出流
使用數(shù)據(jù)流進行讀寫:
public?class?TestStream {
????public?static?void?main(String[] args) {
????????write();
????????read();
????}
????private?static?void?read() {
????????File f =new?File("d:/lol.txt");
????????try?(
????????????????FileInputStream fis? =?new?FileInputStream(f);
????????????????DataInputStream dis =new?DataInputStream(fis);
????????){
????????????boolean?b= dis.readBoolean();
????????????int?i = dis.readInt();
????????????String str = dis.readUTF();
????????????System.out.println("讀取到布爾值:"+b);
????????????System.out.println("讀取到整數(shù):"+i);
????????????System.out.println("讀取到字符串:"+str);
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}
????}
????private?static?void?write() {
????????File f =new?File("d:/lol.txt");
????????try?(
????????????????FileOutputStream fos? =?new?FileOutputStream(f);
????????????????DataOutputStream dos =new?DataOutputStream(fos);
????????){
????????????dos.writeBoolean(true);
????????????dos.writeInt(300);
????????????dos.writeUTF("123 this is gareen");
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}
????}
}
對象流:是可以直接把一個對象以流的形式傳輸給其他的介質(zhì),比如硬盤岖沛,一個對象以流的形式進行傳輸暑始,叫做序列化。 該對象所對應(yīng)的類婴削,必須是實現(xiàn)Serializable接口
學(xué)生類實現(xiàn)Serializable
public class Student implements Serializable{
????????public String name;
????????public int age;
}
public class TextFileObject {
????public static void main(String[] args) {
????//創(chuàng)建一個學(xué)生對象
????//要把Student對象直接保存在文件上廊镜,務(wù)必讓Student類實現(xiàn)Serializable接口
????Student stu = new Student();
????stu.name="小王";
????stu.age=18;
????//準(zhǔn)備一個文件用于保存該對象
????File f = new File("d:/hero.txt");
????//創(chuàng)建對象輸出流
????try(FileOutputStream fos = new FileOutputStream(f);
????ObjectOutputStream oos = new ObjectOutputStream(fos);
????//創(chuàng)建對象輸入流
????FileInputStream fis = new FileInputStream(f);
????ObjectInputStream ois = new ObjectInputStream(fis);){
????oos.writeObject(stu);
????Student s = (Student) ois.readObject();
????System.out.println(s.name);
????System.out.println(s.age);
????} catch (Exception e) {
????// TODO: handle exception
}
}
}
System.in
public?class?TestStream {
????public?static?void?main(String[] args) {
????????// 控制臺輸入
????????try?(InputStream is = System.in;) {
????????????while?(true) {
????????????????// 敲入a,然后敲回車可以看到
????????????????// 97 13 10
????????????????// 97是a的ASCII碼
????????????????// 13 10分別對應(yīng)回車換行
????????????????int?i = is.read();
????????????????System.out.println(i);
????????????}
????????}?catch?(IOException e) {
????????????e.printStackTrace();
????????}
????}
}
使用Scanner讀取
public?class?TestStream {
????public?static?void?main(String[] args) {
????????????Scanner s =?new?Scanner(System.in);
????????????while(true){
????????????????String line = s.nextLine();
????????????????System.out.println(line);
????????????}
????}
}
使用Scanner從控制臺讀取整數(shù)
public?class?TestStream {
????public?static?void?main(String[] args) {
????????Scanner s =?new?Scanner(System.in);
????????int?a = s.nextInt();
????????System.out.println("第一個整數(shù):"+a);
????????int?b = s.nextInt();
????????System.out.println("第二個整數(shù):"+b);
????}
}