Java編程基礎21——IO(字節流)

1_IO流概述及其分類

  • 1.概念java

    • IO流用來處理設備之間的數據傳輸
    • Java對數據的操做是經過流的方式
    • Java用於操做流的類都在IO包中
    • 流按流向分爲兩種:輸入流,輸出流。
    • 流按操做類型分爲兩種:設計模式

      • 字節流 : 字節流能夠操做任何數據,由於在計算機中任何數據都是以字節的形式存儲的
      • 字符流 : 字符流只能操做純字符數據,比較方便。
  • 2.IO流經常使用父類數組

    • 字節流的抽象父類:ui

      • InputStream
      • OutputStream
    • 字符流的抽象父類:加密

      • Reader
      • Writer
  • 3.IO程序書寫spa

    • 使用前,導入IO包中的類
    • 使用時,進行IO異常處理
    • 使用後,釋放資源

2_FileInputStream

  • read()一次讀取一個字節
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Demo1_FileInputStream {
    public static void main(String[] args) throws IOException {
//        demo1();
        FileInputStream fis = new FileInputStream("xxx.txt");    //建立一個文件輸入流對象,並關聯xxx.txt
        int b;                                                    //定義變量,記錄每次讀到的字節
        while((b = fis.read()) != -1) {                            //將每次讀到的字節賦值給b並判斷是不是-1
            System.out.println(b);                                //打印每個字節
        }
        
        fis.close();                                            //關閉流釋放資源
    }

    private static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");//建立流對象
        int x = fis.read();                                    //從硬盤上讀取一個字節
        System.out.println(x);
        int y = fis.read();
        System.out.println(y);
        int z = fis.read();
        System.out.println(z);
        int a = fis.read();
        System.out.println(a);
        int b = fis.read();
        System.out.println(b);    
        
        fis.close();                                //關流釋放資源
    }
}

3_read()方法返回值爲何是int

  • read()方法讀取的是一個字節,爲何返回是int,而不是byte
  • 字節輸入流能夠操做任意類型的文件,好比圖片音頻等,這些文件底層都是以二進制形式的存儲的,若是每次讀取都返回byte,會有可能在讀到111111111,而11111111是byte類型的-1,程序在遇到-1就會中止讀取,用int類型接收遇到11111111會在其前面補上24個0湊足4個字節,那麼byte類型的-1就變成int類型的255了,這樣能夠保證整個數據讀完,而結束標記的-1是int類型的。

4_FileOutputStream

  • write()一次寫出一個字節
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo2_FileOutputStream {

    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("yyy.txt");    //自動建立沒有的對象
        fos.write(97);                    //雖然寫出的是一個int數,可是到文件上的是一個字節,會自動去除前三個八位
        fos.write(98);
        fos.write(99);
        
        fos.close();
    }
}

5_FileOutputStream追加

  • A:案例演示
public static void main(String[] args) throws IOException {
//        demo1();
        FileOutputStream fos = new FileOutputStream("yyy.txt",true);//追加在第二個參數傳true
        fos.write(97);
        fos.write(98);
        
        fos.close();
}

6_拷貝圖片

  • FileInputStream讀取
  • FileOutputStream寫出
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo3_Copy {
    public static void main(String[] args) throws IOException {
//        demo1();
        FileInputStream fis = new FileInputStream("視頻.avi");        //建立輸入流對象,關聯視頻
        FileOutputStream fos = new FileOutputStream("copy.avi");    //建立輸出流對象,關聯copy.avi
        
        int b;
        while((b = fis.read()) != -1) {                    //在不斷讀取每一個字節
            fos.write(b);                                //將每個字節寫出
            
        }
        fis.close();                                    //關流釋放資源
        fos.close();
    }

    private static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("圖片1.png");        //建立輸入流對象,關聯圖片
        FileOutputStream fos = new FileOutputStream("copy.jpg");    //建立輸出流對象,關聯cop.jpg
        
        int b;
        while((b = fis.read()) != -1) {                    //在不斷讀取每一個字節
            fos.write(b);                                //將每個字節寫出
            
        }
        fis.close();                                    //關流釋放資源
        fos.close();
    }
}

7_拷貝音頻文件畫原理圖

  • A:案例演示設計

    • 字節流一次讀寫一個字節複製音頻
  • 弊端:效率過低

圖片描述

8_字節數組拷貝之available()方法

  • A:案例演示code

    • int read(byte[] b):一次讀取一個字節數組
    • write(byte[] b):一次寫出一個字節數組
    • available()獲取讀的文件全部的字節個數
  • 弊端:有可能會內存溢出
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo3_Copy {
    public static void main(String[] args) throws IOException {    
        //第二種拷貝,不推薦,有可能致使內存溢出
        FileInputStream fis = new FileInputStream("視頻.avi");        //建立輸入流對象,關聯視頻
        FileOutputStream fos = new FileOutputStream("copy.avi");    //建立輸出流對象,關聯copy.avi
//        int len = fis.available();
//        System.out.println(len);
        
        byte[] arr = new byte[fis.available()];                    //建立與文件同樣大小的字節數組
        fis.read(arr);                                            //將文件上的字節讀取到內存中
        fos.write(arr);                                            //將字節數組中的字節數據寫到文件上
        
        fis.close();
        fos.close();
    }
}

9_定義小數組

  • write(byte[] b)
  • write(byte[] b, int off, int len)寫出有效的字節個數
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo4_ArrayCopy {
    public static void main(String[] args) throws IOException {
//        demo1();
        FileInputStream fis = new FileInputStream("xxx.txt");
        FileOutputStream fos = new FileOutputStream("yyy.txt");
        
        byte[] arr = new byte[2];
        int len;
        while((len = fis.read(arr)) != -1) {
            fos.write(arr,0,len);
        }
        
        fis.close();
        fos.close();
    }

    private static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");
        byte[] arr = new byte[2];
        int a = fis.read(arr);                        //將文件上的字節讀取到字節數組中
        
        System.out.println(a);                        //讀到的有效字節個數
        for (byte b : arr) {                        //第一次獲取到文件上的a和b
            System.out.println(b);
        }
        System.out.println("----");
        int c = fis.read(arr);
        System.out.println(c);
        for (byte b : arr) {
            System.out.println(b);
        }
        
        fis.close();
    }
}

10_定義小數組的標準格式

  • A:案例演示視頻

    • 字節流一次讀寫一個字節數組複製圖片和視頻
public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("視頻.avi");
        FileOutputStream fos = new FileOutputStream("copy.avi");
        
        byte[] arr = new byte[1024 * 8];
        int len;
        while((len = fis.read(arr)) != -1) {        //忘記寫arr,返回的是碼錶值
            fos.write(arr,0,len);
        }
        
        fis.close();
        fos.close();
    }

11_BufferedInputStream和BufferOutputStream拷貝

  • A:緩衝思想對象

    • 字節流一次讀寫一個數組的速度明顯比一次讀寫一個字節的速度快不少,
    • 這是加入了數組這樣的緩衝區效果,java自己在設計的時候,
    • 也考慮到了這樣的設計思想(裝飾設計模式後面講解),因此提供了字節緩衝區流
  • B.BufferedInputStream

    • BufferedInputStream內置了一個緩衝區(數組)
    • 從BufferedInputStream中讀取一個字節時
    • BufferedInputStream會一次性從文件中讀取8192個, 存在緩衝區中, 返回給程序一個
    • 程序再次讀取時, 就不用找文件了, 直接從緩衝區中獲取
    • 直到緩衝區中全部的都被使用過, 才從新從文件中讀取8192個
  • C.BufferedOutputStream

    • BufferedOutputStream也內置了一個緩衝區(數組)
    • 程序向流中寫出字節時, 不會直接寫到文件, 先寫到緩衝區中
    • 直到緩衝區寫滿, BufferedOutputStream纔會把緩衝區中的數據一次性寫到文件裏
  • D.小數組的讀寫和帶Buffered的讀取哪一個更快?

    • 定義小數組若是是8192個字節大小和Buffered比較的話
    • 定義小數組會略勝一籌,由於讀和寫操做的是同一個數組
    • 而Buffered操做的是兩個數組
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo5_BufferCopy {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("視頻.avi");    //建立輸入流對象
        FileOutputStream fos = new FileOutputStream("copy.avi");//建立輸出流對象
        
        //byte[] arr = new byte[8192]; 
        BufferedInputStream bis = new BufferedInputStream(fis);//建立緩衝區對象,對輸入流進行包裝,讓其變得更強
        BufferedOutputStream bos = new BufferedOutputStream(fos);    
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b);
        }
        
        bis.close();
        bos.close();
    }
}

12_flush和close方法的區別

  • flush()方法

    • 用來刷新緩衝區的,刷新後能夠再次寫出
  • close()方法

    • 用來關閉流釋放資源的的,若是是帶緩衝區的流對象的close()方法,不但會關閉流,還會再關閉流以前刷新緩衝區,關閉後不能再寫出
public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("視頻.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp3"));    
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b);
            bos.flush();
        }
//        bos.close();
//        bis.close();
    }

13_字節流讀寫中文)

  • 字節流讀取中文的問題

    • 字節流在讀中文的時候有可能會讀到半個中文,形成亂碼
  • 字節流寫出中文的問題

    • 字節流直接操做的字節,因此寫出中文必須將字符串轉換成字節數組
    • 寫出回車換行 write("rn".getBytes());
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo6_Chinese {
    public static void main(String[] args) throws IOException {
//        demo1();
        FileOutputStream fos = new FileOutputStream("zzz.txt");
        fos.write("同九年,汝獨秀".getBytes());
        fos.write("\r\n".getBytes());
        
        fos.close();
    }
    
    private static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("yyy.txt");
        byte[] arr = new byte[4];
        int len;
        while((len = fis.read(arr)) != -1) {
            System.out.println(new String(arr,0,len));
        }
        fis.close();
    }
}

14_流的標準處理異常代碼1.6版本及其之前

  • try finally嵌套
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo7_TryFinally {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("xxx.txt");
            fos = new FileOutputStream("yyy.txt");
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }finally {
            try {
                if(fis != null)
                    fis.close();
            }finally {                //try fianlly的目的是儘可能關閉
                if(fos != null)
                    fos.close();
            }
        }
    }
}

15_流的標準處理異常代碼1.7版本

  • try close
  • 原理

    • 在try()中建立的流對象必須實現了AutoCloseable這個接口,若是實現了,在try後面的{}(讀寫代碼)執行後就會自動調用,流對象的close方法將流關掉
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo7_TryFinally {
    public static void main(String[] args) throws IOException {
        try(
            FileInputStream fis = new FileInputStream("xxx.txt");
            FileOutputStream fos = new FileOutputStream("yyy.txt");
            MyClose mc = new MyClose();
        ){
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }
    }
}

class MyClose implements AutoCloseable{    //實現AutoCloseable,自動調用close();
    public void close() {
        System.out.println("我關了");
    }
}

16_圖片加密

  • 給圖片加密
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo8_test {
    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("圖片1.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b ^ 123);//將寫出的字節異或上一個數,這個數就是祕鑰,解密再異或就行
        }
        
        bis.close();
        bos.close();
    }
}

17_拷貝文件

  • 在控制檯錄入文件的路徑,將文件拷貝到當前項目下
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Demo9_test {
    public static void main(String[] args) throws IOException {
        File file = getFile();                //獲取文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file.getName()));
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b);
        }
        bis.close();
        bos.close();
    }
    
    //定義一個方法獲取鍵盤錄入的文件路徑,並封裝成file對象返回
    //返回值類型:File    參數列表:無    
    public static File getFile() {
        Scanner sc = new Scanner(System.in);//建立鍵盤錄入對象
        System.out.println("請輸入一個文件的路徑:");
        while(true) {
            String line = sc.nextLine();        //接收鍵盤錄入的路徑
            File file = new File(line);            //封裝成File對象,並對其判斷
            if(!file.exists()) {
                System.out.println("您錄入的文件路勁不存在,請從新錄入:");
            }else if(file.isDirectory()) {
                System.out.println("您錄入的是文件夾路徑,請從新錄入:");
            }else {
                return file;                    //彈棧返回路徑
            }
        }
    }
}

18_錄入數據拷貝到文件

  • 將鍵盤錄入的數據拷貝到當前項目下的text.txt文件中,鍵盤錄入數據當遇到quit時就退出
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Demo10_test {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);        //建立鍵盤錄入對象
        FileOutputStream fos = new FileOutputStream("text.txt");//建立輸出流對象,關聯text.txt文件
        System.out.println("請輸入數據:");
        
        while(true) {
            String line = sc.nextLine();            //將鍵盤錄入的數據存儲在line中
            if("quit".equals(line)) {
                break;                                //遇到quit退出循環
            }
            fos.write(line.getBytes());                //字符串寫出必須轉換成字節數組
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}
相關文章
相關標籤/搜索