Java復(fù)習(xí)之IO流(上)


IO流(Input Output ),即輸入輸出。

IO流:IO流用于處理設(shè)備間的數(shù)據(jù)傳輸(內(nèi)存和硬盤之間)。IO流讀取硬盤上的文件,對(duì)文件的操作,文件有可能不存在,操作不存在的文件,就會(huì)出現(xiàn)錯(cuò)誤,Java程序在運(yùn)行過(guò)程中出現(xiàn)的錯(cuò)誤,而這個(gè)錯(cuò)誤就叫做異常(Exception)。

下一篇文章傳送門:
Java復(fù)習(xí)之IO流(下)

什么叫異常:

異常的概述

  • 異常就是Java程序在運(yùn)行過(guò)程中出現(xiàn)的錯(cuò)誤,我們來(lái)看看異常體系圖。
異常繼承體系.png

JVM(Java Virtual Machine)默認(rèn)是如何處理異常的

  • main函數(shù)收到這個(gè)問(wèn)題時(shí),有兩種處理方式:
    • 自己處理該問(wèn)題,然后繼續(xù)運(yùn)行
    • 自己沒(méi)有針對(duì)的處理方式,只有交給調(diào)用main的jvm來(lái)處理
    • jvm有一個(gè)默認(rèn)的異常處理機(jī)制,對(duì)異常進(jìn)行處理, 并將該異常的名稱,異常的信息.異常出現(xiàn)的位置打印在了控制臺(tái)上,同時(shí)將程序停止運(yùn)行

函數(shù)自己處理異常

  • try…catch…finally
    • try后面如果跟多個(gè)catch,那么小的異常放前面,大的異常放后面,根據(jù)多態(tài)的原理,如果大的放前面,就會(huì)將所有的子類對(duì)象接收, 后面的catch就沒(méi)有意義
  • throws
    • throws的方式處理異常

      • 定義功能方法時(shí),需要把出現(xiàn)的問(wèn)題暴露出來(lái)讓調(diào)用者去處理。那么就通過(guò)throws在方法上標(biāo)識(shí)。
    • throw的概述

      • 在功能方法內(nèi)部出現(xiàn)某種情況,程序不能繼續(xù)運(yùn)行,需要進(jìn)行跳轉(zhuǎn)時(shí),就用throw把異常對(duì)象拋出。
  • throws和throw的區(qū)別
    • throws
      • 用在方法聲明后面,跟的是異常類名
      • 可以跟多個(gè)異常類名,用逗號(hào)隔開(kāi)
      • 表示拋出的異常,由該方法的調(diào)用者來(lái)處理
    • throw
      • 用在方法體內(nèi),跟的是異常對(duì)象名
      • 只能拋出一個(gè)異常對(duì)象名
      • 表示拋出異常,由方法體內(nèi)的語(yǔ)句處理
  • 下面來(lái)看個(gè)例子,如果是拋出Exception異常,則相當(dāng)于是編譯時(shí)異常,需要在throw拋出異常的方法中使用throws聲明異常,并且在調(diào)用該方法的函數(shù)中也要做此聲明,而如果是拋出運(yùn)行時(shí)異常(RuntimeException),則不用throws做聲明,因?yàn)樗沁\(yùn)行時(shí)異常,運(yùn)行中出現(xiàn)錯(cuò)誤才會(huì)捕獲。
/**
 * 
 * @author 毛麒添
 * throw 拋出異常
 * 運(yùn)行時(shí)異常拋出和編譯時(shí)異常拋出
 */
public class Demo_throws {
   
    public static void main(String[] args) throws Exception {
        Person p=new Person();
        p.setAge(-17);
    }
}

class Person{
     private int age;
     private String name;
     
    public int getAge() {
        return age;
    }
    public void setAge(int age) throws Exception {
        if(age>0&&age<=100){
            this.age = age;
        }else{
            throw new Exception("年齡不合法");
        }
    }
       /**
         * RuntimeException 不需要throws聲明
    
    public void setAge(int age)  {
        if(age>0&&age<=100){
            this.age = age;
        }else{
            throw new RuntimeException("年齡不合法");
        }
        
    }
     */
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     
}
運(yùn)行截圖.png
  • Java中的異常被分為兩大類:編譯時(shí)異常和運(yùn)行時(shí)異常。編譯期異常和運(yùn)行期異常的區(qū)別:
    • 所有的RuntimeException類及其子類的實(shí)例被稱為運(yùn)行時(shí)異常,其他的異常就是編譯時(shí)異常(運(yùn)行時(shí)異常一般為我們程序猿自己犯的錯(cuò)誤,程序運(yùn)行報(bào)錯(cuò),修改代碼)

    • 編譯時(shí)異常,Java程序必須顯示處理(直接加異常處理),否則程序就會(huì)發(fā)生錯(cuò)誤,無(wú)法通過(guò)編譯(如下IO流對(duì)文件操作)

    • 運(yùn)行時(shí)異常,無(wú)需顯示處理,也可以和編譯時(shí)異常一樣處理

try {
            FileInputStream fis=new FileInputStream("aaa.txt");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  • finally關(guān)鍵字

    • finally的特點(diǎn)
      • 被finally控制的語(yǔ)句體一定會(huì)執(zhí)行
      • 特殊情況:在執(zhí)行到finally之前jvm退出了(比如System.exit(0))
    • finally的作用
      • 用于釋放資源,在IO流操作和數(shù)據(jù)庫(kù)操作中會(huì)見(jiàn)到
    • 順便提一下面試中經(jīng)常見(jiàn)到關(guān)于finally的一個(gè)面試題
      • final,finally和finalize的區(qū)別

      • final: final可以修飾類,該類不能被繼承;也可以修飾方法,該方法不能被重寫;還可以修飾變量,表示該變量只能賦值一次
      • finally:finally是try語(yǔ)句中的一個(gè)語(yǔ)句體,不能單獨(dú)使用,用來(lái)釋放資源
      • finalize:finalize是一個(gè)方法,當(dāng)垃圾回收器確定不存在對(duì)該對(duì)象的更多引用時(shí),由對(duì)象的垃圾回收器調(diào)用此方法。
  • 自定義異常

    • 為什么要自定義異常

      • 異常名稱的不同主要就是為了讓我們知道到底我們程序中是有什么錯(cuò)誤,如果都是拋出Exception,我們就很那定位程序中到底是出現(xiàn)了什么錯(cuò)誤,所以如果Java中沒(méi)有給我們提供針對(duì)自身程序的異常,我們就可以自定義一個(gè)(比如上面例子中的設(shè)置年齡不合法我們就可以自定義一個(gè)異常 AgeOutoflegalException)
    • 繼承Exception 或者 RuntimeException等

class AgeOutoflegalException extends Exception{

    public AgeOutoflegalException() {
        super();
        // TODO Auto-generated constructor stub
    }

    public AgeOutoflegalException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }
    
}
自定義異常運(yùn)行結(jié)果.png
  • 最后來(lái)一個(gè)例子對(duì)異常做一個(gè)小結(jié)吧(異常嵌套)。
/**
 * @author 毛麒添
 *  鍵盤錄入一個(gè)int類型的整數(shù),對(duì)其求二進(jìn)制表現(xiàn)形式
 *  如果錄入的整數(shù)過(guò)大,給予提示,錄入的整數(shù)過(guò)大請(qǐng)重新錄入一個(gè)整數(shù)BigInteger
 *  如果錄入的是小數(shù),給予提示,錄入的是小數(shù),請(qǐng)重新錄入一個(gè)整數(shù)
 *  如果錄入的是其他字符,給予提示,錄入的是非法字符,請(qǐng)重新錄入一個(gè)整數(shù)
 */
public class Demo_Test {

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        
        System.out.println("請(qǐng)輸入一個(gè)整數(shù):");
        
            while(true){
                String string = sc.nextLine();
            
                try {
                    //將字符串轉(zhuǎn)換成整數(shù)
                    int num=Integer.parseInt(string);
                    System.out.println(string+"的二進(jìn)制表達(dá)形式為:"+Integer.toBinaryString(num));
                    break;
                } catch (Exception e) {
                    try {
                        new BigInteger(string);//到這步說(shuō)明這是一個(gè)很大的整數(shù)
                        System.out.println("錄入錯(cuò)誤,輸入的是一個(gè)很大的整數(shù),請(qǐng)重新輸入");
                    } catch (Exception e2) {
                        try {
                            new BigDecimal(string);//到這步說(shuō)明這是一個(gè)小數(shù)
                            System.out.println("錄入錯(cuò)誤,輸入的是一個(gè)小數(shù),請(qǐng)重新輸入");
                        } catch (Exception e3) {
                            //到這一步說(shuō)明輸入的是非法字符
                            System.out.println("錄入錯(cuò)誤,輸入的是非法字符,請(qǐng)重新輸入");
                        }
                    }
                }
            }
    }
}

運(yùn)行截圖:

異常小結(jié)例子截圖.png
  • File 類

前面提到,IO流操作文件,我們首先要知道文件在哪,沒(méi)有這個(gè)文件則需要?jiǎng)?chuàng)建,修改文件名等操作,則我們需要用到File類。

  • File類的概述
    • File更應(yīng)該叫做一個(gè)路徑
      • 文件路徑或者文件夾路徑
      • 路徑分為絕對(duì)路徑和相對(duì)路徑固,絕對(duì)路徑是一個(gè)固定的路徑,從盤符開(kāi)始(例如 E:\ ,表示E盤的絕對(duì)路徑); 相對(duì)路徑相對(duì)于某個(gè)位置,在IDE工具下是指當(dāng)前項(xiàng)目下,在dos操作界面下(cmd 打開(kāi)控制臺(tái),C:\Users\XXXX 則表示相對(duì)路徑),創(chuàng)建文件不寫盤符則表示相對(duì)路徑,寫入盤符則表示指定文件位置,表示為絕對(duì)路徑。
  • 構(gòu)造方法

    • File(String pathname):根據(jù)一個(gè)路徑得到File對(duì)象
    • File(String parent, String child):根據(jù)一個(gè)目錄和一個(gè)子文件/目錄得到File對(duì)象
    • File(File parent, String child):根據(jù)一個(gè)父File對(duì)象和一個(gè)子文件/目錄得到File對(duì)象
    • File(URI uri):將給定的file,URI轉(zhuǎn)換成一個(gè)抽象的路徑名來(lái)創(chuàng)建一個(gè)新的 File實(shí)例
  • 創(chuàng)建功能

    • public boolean createNewFile():創(chuàng)建文件, 如果要?jiǎng)?chuàng)建的文件已經(jīng)存在,就不創(chuàng)建了
    • public boolean mkdir():創(chuàng)建文件夾,如果要?jiǎng)?chuàng)建的文件夾已經(jīng)存在,就不創(chuàng)建了
    • public boolean mkdirs():創(chuàng)建文件夾,如果父文件夾不存在,則自動(dòng)幫你創(chuàng)建出來(lái)
  • 重命名和刪除功能

    • public boolean renameTo(File dest):把文件重命名為指定的文件路徑(如果路徑名相同,就是改名,如果路徑名不同,就是改名并剪切)
    • public boolean delete():刪除文件或者文件夾(Java中的刪除不經(jīng)過(guò)回收站,要?jiǎng)h除一個(gè)文件夾,請(qǐng)注意該文件夾內(nèi)不能包含文件或者文件夾)
  • 判斷功能

    • public boolean isDirectory():判斷是否是目錄
    • public boolean isFile():判斷是否是文件
    • public boolean exists():判斷是否存在
    • public boolean canRead():判斷是否可讀(Windows系統(tǒng)默認(rèn)所有文件都是可讀的,所以設(shè)置 File.setReadable(false) 無(wú)效)
    • public boolean canWrite():判斷是否可寫(Windows系統(tǒng)可以設(shè)置文件不可寫,設(shè)置 File.setWritable(false) 有效)
    • public boolean isHidden():判斷是否隱藏
  • 獲取功能

    • public String getAbsolutePath():獲取絕對(duì)路徑
    • public String getPath():獲取路徑(獲取的路徑為構(gòu)造方法中傳入的路徑,傳入的是絕對(duì)路徑,獲取就是絕對(duì)路徑;構(gòu)造方法中傳入相對(duì)路徑就是獲取相對(duì)路徑)
    • public String getName():獲取名稱(文件或者文件夾名稱)
    • public long length():獲取長(zhǎng)度。字節(jié)數(shù)
    • public long lastModified():獲取最后一次的修改時(shí)間,毫秒值
    • public String[] list():獲取指定目錄下的所有文件或者文件夾的名稱數(shù)組
    • public File[] listFiles():獲取指定目錄下的所有文件或者文件夾的File對(duì)象數(shù)組
  • 文件名稱過(guò)濾器方法

    • public String[] list(FilenameFilter filter) 過(guò)濾文件名稱
    • public File[] listFiles(FileFilter filter) 過(guò)濾文件對(duì)象
  • File 遞歸

    • 遞歸的好處:不用知道循環(huán)次數(shù),想遞歸多少次由讀取的數(shù)據(jù)決定

    • 遞歸的弊端:不能調(diào)用次數(shù)過(guò)多,對(duì)此調(diào)用容易導(dǎo)致棧內(nèi)存溢出

    • 構(gòu)造方法是否可以遞歸調(diào)用?

      • 構(gòu)造方法不能使用遞歸調(diào)用
    • 遞歸調(diào)用是否必須有返回值?

      • 不一定(可以有,也可以沒(méi)有)
/**
 * 
 * @author 毛麒添
 * 需求:判斷D盤目錄下是否有后綴名為.jpg的文件,如果有,就輸出該文件名稱 //遞歸
 * 需求:判斷D盤目錄下是否有后綴名為.jpg的文件,如果有,就輸出該文件名稱//文件過(guò)濾器
 */
public class Test {

    public static void main(String[] args) {
        
        demo1(new File("D:\\圖片"));
         //需求:判斷D盤目錄下是否有后綴名為.jpg的文件,如果有,就輸出該文件名稱//文件過(guò)濾器
        File file=new File("D:\\圖片");
        String[] list = file.list(new FilenameFilter() {
            
            @Override
            public boolean accept(File dir, String name) {
                // 將遍歷的文件封裝成對(duì)象
                File file2=new File(dir, name);
                return file2.isFile()&&file2.getName().endsWith(".jpg");
            }
        });
        
        for (String string : list) {
            System.out.println(string);
        }
    }

    private static void demo1(File dir) {
        //需求:判斷D盤目錄下是否有后綴名為.jpg的文件,如果有,就輸出該文件名稱 //遞歸 
         File[] files = dir.listFiles();
         for (File file2 : files) {
            if(file2.isFile()&& file2.getName().endsWith(".jpg")){
                System.out.println(file2);
            }else if(file2.isDirectory()){//如果是文件夾,則遞歸繼續(xù)尋找
                demo1(file2);
            }
        }
    }

}

一不小心,扯了這么多,好吧,下面進(jìn)入到本文主題 IO流

  • IO流基本概念

    • IO流用來(lái)處理設(shè)備之間的數(shù)據(jù)傳輸(內(nèi)存和硬盤之間,相當(dāng)于輸入輸出流在他們之間建立了一個(gè)管道,管道建立肯定要占用資源,所以我們使用輸入輸出流之后需要關(guān)閉流)

    • Java對(duì)數(shù)據(jù)的操作是通過(guò)流的方式,流的分類按操作類型可以分為兩種:

      • 字節(jié)流:字節(jié)流可以操作任何數(shù)據(jù)類型(文本,圖片,音頻,視頻等),在計(jì)算機(jī)中任何數(shù)據(jù)都是以字節(jié)的形式存儲(chǔ)(一般類以 Stream結(jié)尾)
      • 字符流:字符流只能操作純字符數(shù)據(jù)(一般類以 Reader和Writer結(jié)尾)
    • IO流常用父類:

      • 字節(jié)流抽象父類:

        • InputStream 和 OutputStream
      • 字符流抽象父類:

        • Reader 和 Writer
  • FileInputStream 和 FileOuputStream

 * 
 * @author 毛麒添
 * 讀取項(xiàng)目中 a.txt文件中的內(nèi)容,一次讀取一個(gè)字節(jié)
 */

public class Demo_FileInputStream {

    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("a.txt");//確保項(xiàng)目中有該文件
        int a;
        while((a=fis.read())!= -1){
            System.out.println(a);
        }
        System.out.println(a);
        fis.close();

    }

a.txt中的內(nèi)容.png

運(yùn)行結(jié)果:

FileInputStream例子運(yùn)行截圖.png
  • 從運(yùn)行結(jié)果我們可以看出,1數(shù)字在機(jī)器中編碼為49,2數(shù)字為50,3數(shù)字為51,而文件結(jié)束的標(biāo)記為-1,看a.txt文件的屬性是6字節(jié),但是我們接收定義的值a 為什么用 int類型而不是byte?因?yàn)樽止?jié)輸入流可以操作任意類型的文件,比如圖片音頻等,這些文件底層都是以二進(jìn)制形式的存儲(chǔ)的,如果每次讀取都返回byte,有可能在讀到中間的時(shí)候遇到111111111,那么這11111111是byte類型的-1,我們的程序是遇到-1就會(huì)停止不讀了(文件結(jié)束標(biāo)志),這樣文件后面的數(shù)據(jù)就讀不到了,所以在讀取的時(shí)候用int類型接收,如果11111111會(huì)在其前面補(bǔ)上24個(gè)0湊足4個(gè)字節(jié),那么byte類型的-1就變成int類型的255了,這樣可以保證整個(gè)數(shù)據(jù)讀完,而結(jié)束標(biāo)記的-1就是int類型,而在輸出流操作文件的時(shí)候,保證文件的一致性,則會(huì)寫入的時(shí)候自動(dòng)將前 3個(gè)字節(jié)24位給去除。
/**
 * 
 * @author 毛麒添
 * 寫入內(nèi)容,一個(gè)一個(gè)字節(jié)寫
 */

public class Demo_FileOutputStream {

    public static void main(String[] args) throws IOException {
        /* 如果沒(méi)有改文件,則會(huì)自動(dòng)創(chuàng)建,構(gòu)造方法中,寫入文件如果不加入boolean類型判斷,則寫入會(huì)
         * 清空之前的內(nèi)容再寫入,如果想繼續(xù)在前面寫入的基礎(chǔ)追加,則需要boolean類型參數(shù),true表示繼續(xù)追加
         */
        FileOutputStream fos=new FileOutputStream("b.txt",true);
        //前面我們讀取到123,現(xiàn)在則寫入 機(jī)器碼分別為 49 50 51
        fos.write(49); //雖然寫出的是一個(gè)int數(shù),但是在寫出的時(shí)候會(huì)將前面的24個(gè)0去掉,所以寫出的一個(gè)字節(jié)
        fos.write(50);
        fos.write(51);
        fos.close();
    }
}

程序每運(yùn)行一次都會(huì)添加一次123

b.txt文件內(nèi)容.png
  • 接下來(lái)復(fù)習(xí)一下文件的拷貝,也就是InputStream 和 OutputStream的組合使用
/**
 * 
 * @author 毛麒添
 * 文件拷貝三種方式
 * 方式一 :一個(gè)字節(jié)一個(gè)字節(jié)讀取拷貝
 * 方式二:整個(gè)文件一起讀取在拷貝
 * 方式三:定義小數(shù)組讀取文件,在將小數(shù)組中的數(shù)據(jù)寫入文件
 */

public class FileCopy {

    public static void main(String[] args) throws IOException {
        //demo1();
        //demo2();
        
        //方式三:定義小數(shù)組讀取文件,在將小數(shù)組中的數(shù)據(jù)寫入文件(開(kāi)發(fā)中標(biāo)準(zhǔn)的文件拷貝寫法)
        FileInputStream fis=new FileInputStream("a.txt");
        FileOutputStream fos=new FileOutputStream("c.txt");
        
        byte[] bytes=new byte[1024*2];
        int len;
        //這里如果不讀取字節(jié)數(shù)組,則len每一次得到的是對(duì)應(yīng)數(shù)據(jù)的機(jī)器碼,則拷貝寫入的文件大小則為機(jī)器碼的字節(jié)數(shù)總和
        while((len=fis.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }
        
        fis.close();
        fos.close();
        
    }

    private static void demo2() throws FileNotFoundException, IOException {
        //方式二:整個(gè)文件一起讀取在拷貝(available())
        //該方式如果讀取的是大文件,當(dāng)將整個(gè)大文件讀取,則會(huì)導(dǎo)致內(nèi)存溢出
                FileInputStream fis=new FileInputStream("a.txt");
                FileOutputStream fos=new FileOutputStream("c.txt");
                
                int available = fis.available();//獲取文件大小
                //創(chuàng)建一個(gè)與該文件一樣大小的字節(jié)數(shù)組
                byte[] b= new byte[available];
                //將字節(jié)數(shù)組讀取到內(nèi)存中
                fis.read(b);
                //將字節(jié)數(shù)組的數(shù)組寫到需要拷貝到的文件中
                fos.write(b);
                
                fis.close();
                fos.close();
    }

    private static void demo1() throws FileNotFoundException, IOException {
        //方式一 :一個(gè)字節(jié)一個(gè)字節(jié)讀取拷貝(該方法也是IO流的拷貝核心代碼)
        FileInputStream fis=new FileInputStream("a.txt");
        FileOutputStream fos=new FileOutputStream("c.txt");
        
        int a;
        while((a=fis.read())!=-1){
            fos.write(a);
        }
        
        fis.close();
        fos.close();
    }

}

  • IO流標(biāo)準(zhǔn)異常處理寫法
/**
 * 
 * @author 毛麒添
 * JDK 1.6 1.7 版本IO流標(biāo)準(zhǔn)異常處理寫法
 *
 */
public class Demo_CopyFile {

    public static void main(String[] args) throws IOException {
        demo1();
        //jdk 1.7 版本
        // FileInputStream和FileOutputStream 最上層都繼承了 AutoCloseable接口,自動(dòng)調(diào)用close方法,所以該寫法不用手動(dòng)關(guān)流
        try(
                FileInputStream fis=new FileInputStream("a.txt");
                FileOutputStream fos=new FileOutputStream("b.txt");
                ){
             int a;
            
             while((a=fis.read())!=-1){
                fos.write(a);
        }
        }
    }

    private static void demo1() throws FileNotFoundException, IOException {
        // JDK1.6版本
        FileInputStream fis=null;//局部變量使用前需要賦值
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream("a.txt");
            fos=new FileOutputStream("b.txt");
            
            int a;
            
            while((a=fis.read())!=-1){
                fos.write(a);
            }
        } finally{
            try{                    //try finally 嵌套保證能關(guān)一個(gè)流就盡量關(guān)閉一個(gè)
                if(fis!=null)
                    fis.close();
            }finally{

                if(fos!=null)
                fos.close();
            }
            
        }
    }

}

  • BufferedInputStream 和 BufferedOuputStream
    • BufferedInputStream 和 BufferedOuputStream相當(dāng)于對(duì)FileInputStream 和 FileOuputStream進(jìn)行了一次包裝;舉個(gè)例子:一個(gè)美女素顏出鏡和畫了妝出鏡一般情況下應(yīng)該是畫了妝的美女更美,而使用BufferedInputStream 和 BufferedOuputStream則拷貝的效率則更高。
    • 緩沖思想
      • 字節(jié)流一次讀寫一個(gè)數(shù)組的速度明顯比一次讀寫一個(gè)字節(jié)的速度快很多,
      • 這是加入了數(shù)組這樣的緩沖區(qū)效果,java本身在設(shè)計(jì)的時(shí)候,提供了字節(jié)緩沖區(qū)流(裝飾設(shè)計(jì)模式)
    • BufferedInputStream
      • BufferedInputStream內(nèi)置了一個(gè)緩沖區(qū)(數(shù)組)
      • 從BufferedInputStream中讀取一個(gè)字節(jié)時(shí)
      • BufferedInputStream會(huì)一次性從文件中讀取8192個(gè), 存在緩沖區(qū)中, 返回給程序一個(gè)
      • 程序再次讀取時(shí), 就不用找文件了, 直接從緩沖區(qū)中獲取
      • 直到緩沖區(qū)中所有的都被使用過(guò), 才重新從文件中讀取8192個(gè)
    • BufferedOutputStream
      • BufferedOutputStream也內(nèi)置了一個(gè)緩沖區(qū)(數(shù)組)
      • 程序向流中寫出字節(jié)時(shí), 不會(huì)直接寫到文件, 先寫到緩沖區(qū)中
      • 直到緩沖區(qū)寫滿, BufferedOutputStream才會(huì)把緩沖區(qū)中的數(shù)據(jù)一次性寫到文件里
BufferedInputStream 和 BufferedOuputStream操作示意圖.png

下面給出BufferedInputStream 和 BufferedOuputStream拷貝問(wèn)價(jià)的例子

/**
 * 
 * @author 毛麒添
 * BufferedInputStream和BufferOutputStream拷貝
 */

public class Demo_BufferCopy {

    public static void main(String[] args) throws IOException {
        
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("a.txt"));
        
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("c.txt"));
        
        int a;
        
        while((a=bis.read())!=-1){
            bos.write(a);
        }

        
        bis.close();
        bos.close();

    }

}
  • flush和close方法的區(qū)別
    • flush()方法
      • 用來(lái)刷新緩沖區(qū)的,刷新后可以再次寫出
    • close()方法
      • 用來(lái)關(guān)閉流釋放資源的的,如果是帶緩沖區(qū)的流對(duì)象的close()方法,不但會(huì)關(guān)閉流,還會(huì)再關(guān)閉流之前刷新緩沖區(qū),關(guān)閉后不能再寫出
  • IO流小例子(練習(xí))
/**
 * 
 * @author 毛麒添
 * 文件加密
 * 將寫出的字節(jié)異或上一個(gè)數(shù),這個(gè)數(shù)也就是我們的秘鑰,這時(shí)候文件已經(jīng)加密
 * 如果需要將文件解密,則讀取加密文件再次異或我們的秘鑰變可以解密
 */


public class FileEncrypt {

    public static void main(String[] args) throws IOException {
        
        String file1="a.jpg";
        
        String file2="c.jpg";
        int key=456;
        //加密
        fileEncrypt(file1, file2, key);
        
        String file3="d.jpg";
        //解密
        fileEncrypt(file2, file3, key);
    }

    public static void fileEncrypt(String file1, String file2, int key) throws FileNotFoundException, IOException {
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file1));
        
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file2));
        
        int b;
        while((b= bis.read())!=-1){
            bos.write(b^key);//456就是我們加密的秘鑰
        }
    }
}

運(yùn)行結(jié)果:

圖片a.png
圖片C.png
圖片d.png
  • 將鍵盤輸入的字符串寫入到文件當(dāng)中
/**
 * 
 * @author 毛麒添
 * 將鍵盤輸入的字符串寫入到文件當(dāng)中
 */
public class WriteToFile {

    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);

        FileOutputStream fos=new FileOutputStream("write.txt");
        
        System.out.println("請(qǐng)?jiān)阪I盤中輸入數(shù)據(jù):");
        while(true){
            String nextLine = sc.nextLine();
            if("quit".equals(nextLine)){
                System.out.println("寫入完成!!");
                break;
            }
            fos.write(nextLine.getBytes());//字符串寫入文件必須為字符數(shù)組
            fos.write("\r\n".getBytes());//換行
        }
        
        fos.close();
    }

}

運(yùn)行結(jié)果:

文件寫入運(yùn)行結(jié)果1.png
文件寫入運(yùn)行結(jié)果2.png
  • 鍵盤輸入文件路徑,將該文件拷貝到當(dāng)前項(xiàng)目下
/**
 * 
 * @author 毛麒添
 * 鍵盤輸入文件路徑,將該文件拷貝到當(dāng)前項(xiàng)目下
 * 
 */
public class CopyFileProgress {

    public static void main(String[] args) throws IOException {
        //鍵盤錄入文件路徑,獲取該文件對(duì)象
        File file=getFile();

        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
        //拷貝的文件名稱一樣
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file.getName()));
        
        int a;
        
        while((a=bis.read())!= -1){
            bos.write(a);
        }
        System.out.println("拷貝完成");
        bis.close();
        bos.close();
        
    }

    private static File getFile() {
        Scanner sc=new Scanner(System.in);
    
        System.out.println("請(qǐng)輸入文件的路徑:");
        
        while(true){
            String nextLine = sc.nextLine();
            File file=new File(nextLine);
            if(!file.exists()){
                System.out.println("該文件不存在,請(qǐng)重新輸入!");
            }else if(file.isDirectory()){//如果是一個(gè)路徑
                System.out.println("輸入的是文件路徑,請(qǐng)重新輸入!");
            }else{
                return file;
            }
        }
        
    }

}

鍵盤輸入路徑拷貝文件截圖.png

本文對(duì)異常處理,F(xiàn)ile類和字節(jié)流做了復(fù)習(xí),在下一篇文章則繼續(xù)對(duì)IO流中的字符流等知識(shí)進(jìn)行復(fù)習(xí)。如果大家有發(fā)現(xiàn)不對(duì)的地方,歡迎給我指出,大家一起學(xué)習(xí)進(jìn)步。如果覺(jué)得文章對(duì)你有幫助,也請(qǐng)給我一個(gè)喜歡。

本系列文章:
Java復(fù)習(xí)之集合框架
Java復(fù)習(xí)之IO流(上)
Java復(fù)習(xí)之IO流(下)
Java 復(fù)習(xí)之多線程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,559評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 178,442評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,835評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,581評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,922評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 43,096評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,639評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,374評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,591評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,789評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,196評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,524評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,322評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,554評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,828評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,737評(píng)論 18 399
  • 1 IONo18 1.1IO框架 【 IO:Input Output 在程序運(yùn)行的過(guò)程中,可能需要對(duì)一些設(shè)備進(jìn)...
    征程_Journey閱讀 974評(píng)論 0 1
  • 在經(jīng)過(guò)一次沒(méi)有準(zhǔn)備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼,基礎(chǔ)知識(shí)卻忘的差不多了。這是程序員的大忌,沒(méi)...
    猿來(lái)如癡閱讀 2,866評(píng)論 3 10
  • 這是一個(gè)糾結(jié)患者的第一篇簡(jiǎn)書,對(duì)我來(lái)說(shuō)是一個(gè)開(kāi)端。Say 加油 to me! 一、認(rèn)識(shí)自我 我是一...
    露蘇維閱讀 256評(píng)論 0 0