尚硅谷JavaSE入門筆記 - P581 ~ P617

IO流

前言

本文爲B站Java教學視頻BV1Kb411W75N的相關筆記,主要用於我的記錄與分享,若有錯誤歡迎留言指出。
本章筆記涵蓋視頻內容P581~P617java

1.File類

  • 定義:File類是文件和文件目錄路徑的抽象表示形式;File能新建,刪除,重命名文件和目錄,但File不能訪問文件內容。若是須要訪問文件內容,則須要使用輸入/輸出流。

1.1 File類的實例化

public void test1(){
    
    //構造器1
    File file1 = new File("hello.txt");	//相對路徑
    File file2 = new File("D:\\workspace_idea\\day08\\he.txt");	//絕對路徑
    
    //構造器2
    File file3 = new File("D:\\workspace_idea","day08");//父路徑下的子路徑
    
    //構造器3
    File file4 = new File(file3,"hi.txt");	//應用其它File類的路徑
    
}
  • 注意事項
    • 相對路徑:相較於某個路徑下,指明的路徑
      絕對路徑:包含盤符在內的文件或文件目錄的路徑
    • 路徑中的每級目錄之間都用一個路徑分割符隔開
      windows和DOS系統默認使用""來表示
      UNIX和URL使用"/"來表示
      爲保證平臺兼容,java提供了File類的常量public static final String separator,表示動態分隔符
    • 想要在Java程序中表示一個真實存在的文件或目錄,那麼必須有一個File對象,可是Java程序中的一個File對象,具備的不必定是真實存在的文件或目錄

1.2 File類的經常使用方法

  • File類的獲取功能windows

  • public String getAbsolutePath():獲取絕對路徑數組

  • public String getPath():獲取路徑app

  • public String getName():獲取名稱dom

  • public String getParent():獲取上層文件目錄路徑。若無,返回nullide

  • public long length():獲取文件長度(字節數),不能獲取目錄的長度優化

  • public long lastModified():獲取最後一次的修改時間(時間戳)ui

  • public String[] list:獲取指定目錄下的全部文件,或者文件目錄的名稱數組編碼

  • public String[] listFiles:獲取指定目錄下的全部文件,或者文件目錄的File數組idea

  • File類的重命名功能

  • public boolean renameTo(File dest):把文件重命名爲指定的文件路徑

    • 要想保證返回true,須要讓調用File類在硬盤中實際存在,且dest不能在硬盤中存在(被佔用)
  • File類的判斷功能

  • public boolean isDirectory():判斷是不是文件目錄

  • public boolean isFile():判斷是不是文件

  • public boolean exists():判斷是否存在

  • public boolean canRead():判斷是不是可讀

  • public boolean canWrite():判斷是否可寫

  • public boolean isHidden():判斷是不是隱藏

  • File類的建立與刪除功能

  • public boolean createNewFile():建立文件。若文件存在,則不建立,返回false

  • public boolean mkdir():建立文件目錄。若是此文件目錄已存在,則不建立。若是此文件目錄上層目錄不存在,也不建立

  • public boolean mkdirs():建立文件目錄。若是此文件目錄已存在,則不建立。若是此文件目錄上層目錄不存在,則一併建立

  • public boolean delete():刪除文件或者文件夾

2.IO流

2.1 流的分類

  • 按操做數據單位不一樣分爲:字節流(8 bit),字符流(16 bit)

  • 按數據流的流向不一樣分爲:輸入流,輸出流

  • 按流的角色的不一樣分爲:節點流,處理流

    抽象基類 字節流 字符流
    輸入流 InputStream Reader
    輸出流 OutputStream Writer
  • 流的體系結構

    抽象基類 節點流(文件流) 緩衝流(處理流的一種)
    InputStream FileInputStream BufferedInputStream
    OutputStream FileOutputStream BufferedOutputStream
    Reader FileReader BufferedReader
    Writer FileWriter BufferedWriter

2.2 節點流

2.2.1 FileReader/FileWriter

  • FileReader基本操做
public class Test{
    public static void main(String[] args) {
    }

    public void testFileReader(){
        //1.實例化File類的對象,指明要操做的文件
        File file = new File("hello.txt");	//相對路徑
        
        try {
            
            //2.提供具體的流
            FileReader fr = new FileReader(file);
            
            //3.數據的讀入
            //read():返回讀入的一個字符,若是達到文件末尾,返回-1
            int data = 0;
            while((data = fr.read()) != -1){
                System.out.print((char)data);
            }

            //4.流的關閉操做
            fr.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/*
異常的處理:爲了保證流資源必定能夠執行關閉操做,不推薦使用throw,而是須要用try-catch-finally處理
讀入的文件必定要存在,不然就會報FileNotFoundException
*/
  • 使用read的重載方法優化操做FileReader
public class Test{
    public static void main(String[] args) {
    }

    public void testFileReader1(){
        //1.File類的實例化
        File file = new File("hello.txt");
        
        try {
            
            //2.FileReader流的實例化
            FileReader fr = new FileReader(file);

            //3.讀入的操做
            //read(char[] cbuf):返回每次讀入cbuf數組中的字符的個數,若是達到文件末尾,返回-1
            char[] cbuf = new char[5];	//每次都read長度爲5的字符
            int len;
            while((len = fr.read(cbuf)) != -1){
                //方式一:
                //錯誤的寫法
//        	    for(int i = 0;i < cbuf.length;i++){
//              	System.out.print(cbuf[i]);
//		  	    }
                //正確的寫法
                for(int i = 0;i < len;i++){
                    System.out.print(cbuf[i]);
                }

                //方式二:
                //錯誤的寫法
//        	    String str = new String(cbuf);
//        	    System.out.print(str);
                //正確的寫法
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }

            //4.資源的關閉
            fr.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
/*
重載後的read能夠一次性讀入多個字符,效率獲得提高
須要注意數組的覆蓋問題
*/
  • FileWriter基本操做
public class Test{
    public static void main(String[] args) {
    }

    public void testFileWriter(){
        //1.提供File類的對象,指明寫出到的文件
        File file = new File("hello1.txt");
        
        try {
            
            //2.提供FileWriter的對象,用於數據的寫出
            FileWriter fw = new FileWriter(file,false);

            //3.寫出的操做
            fw.write("AAA");
            fw.write("BBBBBBB");

            //4.流資源的關閉
            fw.close();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/*
寫入操做,對應的File能夠不存在,不會報異常
File對應的硬盤中的文件若是不存在,在輸出的過程當中,會自動建立此文件
File對應的硬盤中的文件若是存在:
	若是流使用的構造器是:FileWriter(file,false)/FileWriter(file):對原有文件的覆蓋
	若是流使用的構造器是:FileWriter(file,true):不會對原有文件覆蓋,而是在原有文件基礎上追加內容
*/

2.2.2 FileInputStream/FileOutputStream

public void testFileInputOutputStream(){
        File srcFile = new File("1.jpg");
        File destFile = new File("2.jpg");

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            byte[] buffer = new byte[5];
            int len;
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer,0,len);
            }

            fos.close();
            fis.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
/*
對於文本文件(txt/java/c/cpp),使用字符流處理
對於非文本文件(jpg/mp3/mp4/doc),使用字節流處理
*/

2.3 處理流

2.3.1 緩衝流

  • 定義:緩衝流經過內部提供一個緩衝區的方式,提高了流的讀取,寫入速度
BufferedInputStream/BufferedOutputStream
public class Test{
    public static void main(String[] args) {

        //1.造文件
        File scrFile = new File("1.jpg");
        File destFile = new File("3.jpg");
        
        try {
            
            //2.造流
            //2.1 造節點流
            FileInputStream fis = new FileInputStream(scrFile);
            FileOutputStream fos = new FileOutputStream(destFile);

            //2.2 造緩衝流
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedOutputStream bos = new BufferedOutputStream(fos);

            //3.複製的細節:讀取,寫入
            byte[] buffer = new byte[10];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }

            //4.資源關閉
            //關閉外層流的同時,內層流也會自動的進行關閉。
            bos.close();
            bis.close();
            
        } catch (FileNotFoundException e) { 
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
BufferedReader/BufferedWriter
public class Test{
    public static void main(String[] args) {
        
        try {

            //匿名建立處理流
            BufferedReader br = new BufferedReader(new FileReader(new File("1.txt")));
            BufferedWriter bw = new BufferedWriter(new FileWriter(new File("2.txt")));

            //讀寫操做
            //方式一:使用char[]數組
//          char[] cbuf = new char[1024];
//          int len;
//          while((len = br.read(cbuf)) != -1){
//              bw.write(cbuf,0,len);
//          }

            //方式二:使用String
            String data;
            while((data = br.readLine()) != null){
                //方法一:
                bw.write(data + "\n");	//data中不包含換行符(須要額外添加換行符)
                //方法二:
                bw.write(data);
                bw.newLine();	//至關於每寫入一次就新建立一行("\n")
            }

            //關閉資源
            bw.close();
            br.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/*
flush()是在寫入時用於刷新緩衝區的,程序默認緩衝區滿了後纔會寫入內容,flush會強制讓緩衝區輸出內容
*/

2.3.2 轉換流

  • 定義:轉換流是字符流的一種,其提供字節流與字符流之間的轉換

    • InputStreamReader:將一個字節的輸入流轉換爲字符的輸入流
    • OutputStreamWriter:將一個字符的輸出流轉換爲字節的輸出流
  • 解碼:字節,字節數組 → 字符數組,字符串

    編碼:字符數組,字符串 → 字節,字節數組

public class Test{
    public static void main(String[] args) {
        
        try {
            
            FileInputStream fis = new FileInputStream("1.txt");

            //使用系統默認的字符集讀取輸入流
//          InputStreamReader isr = new InputStreamReader(fis);
            //使用指定的字符集讀取輸入流
            InputStreamReader isr = new InputStreamReader(fis,"UTF-8");

            char[] cbuf = new char[20];
            int len;
            while((len = isr.read(cbuf)) != -1){
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }
            isr.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3.3 標準輸入輸出流

  • System.in:標準的輸入流,默認從鍵盤輸入,類型是InputStream

    System.out:標準的輸入流,默認從控制檯輸出,類型是PrintStream(OutputStream的子類)

  • System類的setIn(InputStream is) / setOut(PrintStream ps)方式從新指定輸入和輸出的流

//經過轉化流與標準輸出輸入實現Scanner
public class Test{
    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        while(true){
            String data = null;
            try {
                data = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if("test".equalsIgnoreCase(data)){
                System.out.println("結束!");
                break;
            }
        }
    }
}

2.3.4 打印流

  • 定義:PrintStream和PrintWriter實現將基本數據類型的數據格式轉化爲字符串輸出
    • PrintStream和PrintWriter有自動flush功能
    • 提供了一系列重載的print()和println()方法,用於多種數據類型的輸出
public class Test{
    public static void main(String[] args) {
        
        PrintStream ps = null;
        
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        
        //建立打印輸出流,設置爲自動刷新模式(寫入換行符的時候會刷新輸出緩衝區)
        ps = new PrintStream(fos,true);
        if(ps != null){
            System.setOut(ps);
        }
        for(int i = 0;i <= 255; i++){
            System.out.print((char)i);
        }
    }
}
/*
這樣子print的內容都會輸出到指定的文件下,至關於重寫了print
*/

2.3.5 數據流

  • 定義:DataInputStream 和 DataOutputStream,用於讀取或寫出基本數據類型的變量或字符串
public class Test{
    public static void main(String[] args) {
        
        try {
            
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));

            dos.writeUTF("HARRY");
            dos.flush();
            dos.writeInt(23);
            dos.flush();
            dos.writeBoolean(true);
            dos.flush();

            dos.close();

            //讀取不一樣類型的數據的順序要與當初寫入文件時,保存的數據的順序一致
            DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));

            String name = dis.readUTF();
            int age = dis.readInt();
            boolean isMale = dis.readBoolean();

            System.out.println(name);
            System.out.println(age);
            System.out.println(isMale);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.對象流

  • 定義:ObjectInputStream和ObjectOutputStream用於存儲和讀取基本數據類型數據或對象的處理流,它能夠把Java的對象寫入到數據源中,也能把對象從數據源中還原回來

  • 序列化:用ObjectOutputStream類保存基本數據類型或對象的機制

    反序列化:用ObjectInputStream類讀取基本數據類型或對象的機制

  • ObjectInputStream和ObjectOutputStream不能序列化static和transient修飾的成員變量

public class Test{
    public static void main(String[] args) {
        //序列化:將內存中的java對象保存到磁盤中
        //使用ObjectOutputStream實現
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.dat"));
            oos.writeObject(new String("TestTest"));
            oos.flush();

            oos.close();

            //反序列化:將磁盤文件中的對象還原爲內存中的一個java對象
            //使用ObjectInputStream實現
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"));

            Object obj = ois.readObject();
            String str = (String)obj;
            System.out.println(str);

            ois.close();

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
  • 自定義類序列/反序列化
/*
自定義類須要知足如下要求,方可序列化
1.須要實現Serializable接口
2.當前類提供一個全局常量:serialVersionUID
3.除了當前類須要實現Serializable接口以外,還必須保證其內部全部屬性均可以序列化
4.ObjectInputStream和ObjectOutputStream不能序列化static和transient修飾的成員變量
*/
class Person implements Serializable{
    
    public static final long serialVersionUID = 64846545648L;
    
    private String name;
    private int age;
}
/*
serialVersionUID用來代表類的不一樣版本,其目的是對序列化對象進行版本控制。
若是類沒有顯式定義這個靜態常量,它的值是自動生成的。若類的實例變量作了修改,serialVersionUID可能發生變化(沒法反序列化)
*/

4. 隨機存取文件流RandomAccessFile

  • 定義:RandomAccessFile這個類實現了DataInput和DataOutput兩個接口,意味着它既能夠做爲一個輸入流也能夠做爲一個輸出流。它支持"隨機訪問"的方式,程序能夠直接跳到文件的任意地方來讀,寫文件

  • 若是RandomAccess做爲輸出流時,寫出到的文件若是不存在,則在執行過程當中自動建立。若是寫出到的文件存在,則會對原有文件內容進行覆蓋(默認狀況下,從頭覆蓋)

  • 有些相似C風格的讀寫方式

public class Test{
    public static void main(String[] args) {
        
        try {

            RandomAccessFile raf1 = new RandomAccessFile(new File("1.jpg"),"r");
            RandomAccessFile raf2 = new RandomAccessFile(new File("2.jpg"),"rw");

            byte[] buffer = new byte[1024];
            int len;
            while((len = raf1.read(buffer)) != -1){
                raf2.write(buffer,0,len);
            }

            raf1.close();
            raf2.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 使用RandomAccessFile實現數據的插入效果
public class Test{
    public static void main(String[] args) {
        
        try {
            
            RandomAccessFile raf1 = new RandomAccessFile("hello.txt","rw");
            
            raf1.seek(3);//將指針調到角標爲3的位置
            //保存指針3後面的全部數據到StringBuilder中
            StringBuilder builder = new StringBuilder((int)new File("hello.txt").length());
            byte[] buffer = new byte[20];
            int len;
            while((len = raf1.read(buffer)) != -1){
                builder.append(new String(buffer,0,len));
            }
            //調回指針,寫入xyz
            raf1.seek(3);
            raf1.write("xyz".getBytes());

            //將StringBuilder中的數據寫入到文件中
            raf1.write(builder.toString().getBytes());
            raf1.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索