Java IO流

cwstd 發表於 2021-05-13
Java

Java IO流

1.File Class

File類代表一個檔案或者檔案目錄
構造器:

  • File(String pathname)
  • File(String pathname,String child)
  • File(String parent,String child)
    parent目錄路徑 child表示從parent的下一層目錄
        File file = new File("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\123.txt");
        File file1=new File("123.txt");
        File file2=new File("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream","123.txt");
        File file3=new File("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd","iostream");

1.1 File類的獲取方法

  • getAbsolutePath()獲取絕對路徑
  • getAbsoluteFile()獲取絕對路徑表示的檔案
  • getPath()獲取路徑
  • getParent()獲取上一層檔案目錄路徑,若無返回null
  • length()獲取檔案長度(位元組數)
  • lastModified() 獲取最後一次修改時間
  • String [] list()獲取目錄下所有檔案和資料夾的名稱陣列,返回String陣列
  • File[] listFiles()獲取指定目錄下的所有資料夾和檔案目錄File陣列
        //獲取絕對路徑
        System.out.println(file.getAbsolutePath());
        //獲取絕對路徑表示的檔案
        System.out.println(file.getAbsoluteFile());
        //獲取路徑
        System.out.println(file.getPath());
        //獲取上一層檔案目錄路徑,若無返回null
        System.out.println(file.getParent());
        //獲取檔案長度(位元組數),不能獲取目錄的大小
        System.out.println(file.length());
        //獲取最後一次修改時間
        System.out.println(file.lastModified());
        //獲取目錄下所有檔案和資料夾的名稱陣列,返回String陣列
        String []filenames=file3.list();
        for (String o:filenames)
        {
            System.out.println(o);
        }
        //獲取指定目錄下的所有資料夾和檔案目錄File陣列
        File [] filenames2=file3.listFiles();
        for (File files : filenames2)
        {
            System.out.println(files.getName());
        }

1.2 File類的重新命名與建立檔案功能

renameTo()把檔案重新命名為指定的檔案路徑

file2.renameTo(new File("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\suanfa\\binarytree\\123.txt"));

createNewFile() 建立檔案,若檔案存在,則不建立,返回false
mkdir() 建立檔案目錄,如果此檔案存在,就不建立,如果上級目錄不存在也不建立
mkdirs() 建立檔案目錄,上級目錄不存在也會建立

        //建立檔案,若檔案存在,則不建立,返回false
        file1.createNewFile();
        //建立檔案目錄,如果此檔案存在,就不建立,如果上級目錄不存在也不建立
        file4.mkdir();
        //建立檔案目錄,上級目錄不存在也會建立
        file4.mkdirs();

2.Java IO流

2.1 Java IO流的概念

Java程式中輸入與輸出都是以流的方式的進行,I/O技術是用於處理裝置之間的資料傳輸。在java中把不同的輸入/輸出源(鍵盤,檔案,網路連線等)抽象表述為“流”(stream)。通過流的形式允許java程式使用相同的方式來訪問不同的輸入/輸出源。stram是從起源(source)到接收的(sink)的有序資料。
主要的IO流

資料單位 位元組流 字元流
抽象基類 InputStream OutputStream Reader Writer
節點流 FileInputStream FileOutputStream FileReader FileWriter
處理流 BufferedInputStream BufferedOutputStream(資料流、物件流、列印流等) BufferedReader BufferedWriter

2.2 節點流

Java重要的節點流有FileInputStream FileOutputStream(位元組流)和FileReader FileWriter(字元流)
注意:字元流是對位元組流進行封裝,字元流的底層也是位元組流,進行封裝轉化,更方便簡單處理字元文件(可以用記事本開啟的)
例子:使用FileInputStream FileOutputStream(位元組流)進行檔案複製

  • 第一步:建立流 輸入流輸出流分別指向
  • 第二步:操作流 建立一箇中轉站(位元組陣列),在使用輸入流read方法將位元組流讀入陣列,直到檔案複製完成。
  • 第三步:關閉流
    需要使用try--catch--finally捕獲異常
/***
 * 使用FileInputStream和FileOutputStream實現檔案複製
 */
public class TestFileStream {
    public static void main(String[] args) {
        //1.建立流
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try{
            fis = new FileInputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\123.txt");
            fos = new FileOutputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\12345.txt");
            //2.使用流
            //2.1使用一箇中轉站
            byte [] buf=new byte[1024];
            int len;//記錄每次讀取位元組長度
            while((len=fis.read(buf))>=0)
            {
                fos.write(buf,0,len);//將讀取的位元組,寫入新的檔案中

            }
        }catch(Exception e)
        {
            e.printStackTrace();
        }finally {
            //3.關閉流
            if(fis!=null)
            {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos!=null)
            {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

例子:使用FileReader FileWriter(字元流)進行txt文件的複製
注意:字元流只能複製字元文件,如果要複製視訊、音訊、圖片等需要使用位元組流,字元流複製跟位元組流流程一樣,就是中轉站採用的是字元陣列。

  • 第一步:建立流 輸入流輸出流分別指向
  • 第二步:操作流 建立一箇中轉站(字元陣列),在使用輸入流read方法將字元流讀入陣列,直到檔案複製完成。
  • 第三步:關閉流
    需要使用try--catch--finally捕獲異常
/***
 * 使用FileReader和FileWriter實現檔案複製
 */
public class TestFileReader {
    public static void main(String[] args) {
        FileReader fr=null;
        FileWriter fw=null;

        try {
            //建立流
            fr = new FileReader("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\123.txt");
            fw = new FileWriter("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\12345.txt");
            fw = new FileWriter("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\12345.txt",true);//每次在後面追加,不覆蓋
            //使用流
            char []buf=new char[1024];
            int n;
            while((n=fr.read(buf))>=0)
            {
                fw.write(buf,0,n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //關閉流
            try {
                if(fr!=null)
                {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fw!=null)
                {
                    fw.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

2.2 緩衝流

作用:緩衝流分為快取位元組流和快取字元流,目的是提高訪問速度,提高便捷。
原理:分別開闢一個輸入流緩衝區,和輸出流緩衝區,不用每次讀取寫入都直接操作硬碟,中轉站會先從緩衝區讀取或寫入資料,如果緩衝區沒有或者快取寫滿,這時緩衝區才會操作硬碟,大大減少操作硬碟次數,節約時間。
Java IO流

注意

  • 緩衝流BufferedInputStream BufferedOutputStream 和 BufferedReader BufferedWriter是高層流,資源回收時,只需要關閉高層流,低層流會自動的關閉。
  • 何時緩衝區寫入硬碟,三種情況:緩衝區滿、關閉緩衝流、手動使用flush函式。

例子1:使用FileInputStream FileOutputStream(位元組流)進行檔案複製,並使用BufferedInputStream BufferedOutputStream緩衝流提高速度。

/**
 * 使用緩衝流Buffered來加快檔案複製的過程
 */
public class TestBufferedStream {
    public static void main(String[] args) {
        BufferedInputStream bis=null;
        BufferedOutputStream bos=null;
        try {
            bis=new BufferedInputStream(new FileInputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\2007.07481.pdf"));
            bos=new BufferedOutputStream(new FileOutputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\2007.pdf"));
            byte [] buf=new byte[1024];
            int n;
            while((n=bis.read(buf))!=-1)
            {
                bos.write(buf,0,n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {//關閉流
            if(bis!=null)
            {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bos!=null)
            {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

例子2:使用 BufferedReader BufferedWriter(字元流)進行字元文件複製,要求一行一行的複製

/**
 * 使用緩衝流字元流逐行讀取文件,並複製到另一個文件上
 */
public class TestBufferedReader {
    public static void main(String[] args) {
        BufferedReader bor=null;
        BufferedWriter bow=null;
        try {
            //建立流
            bor=new BufferedReader(new FileReader("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\123.txt"));
            bow=new BufferedWriter(new FileWriter("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\12345.txt"));
            //使用流
            String s;
            while((s=bor.readLine())!=null)//如果讀不到資料,返回null
            {
                bow.write(s);//寫入資料
                bow.newLine();//換行
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //關閉流
            try {
                if(bor!=null)
                {
                    bor.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bow!=null)
                {
                    bow.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    }

2.3 其他流

資料流 DataInputStream和DataOutputStream

方便操作各種資料型別,可以將各種資料型別,寫入檔案,讀取出來也能還原出各種資料型別

public class TestDataInputStream {
    public static void main(String[] args) {
        DataInputStream dain=null;
        DataOutputStream daou=null;
        try{
            //建立資料流
            dain=new DataInputStream(new FileInputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\Data.txt"));
            daou=new DataOutputStream(new FileOutputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\Data.txt"));
            daou.writeBoolean(true);
            daou.writeChar('偉');
            daou.writeInt(12);
            daou.writeUTF("hhhhhhh");
            //讀取資料
            System.out.println(dain.readBoolean());
            System.out.println(dain.readChar());
            System.out.println(dain.readInt());
            System.out.println(dain.readUTF());

        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            if(dain!=null)
            {
                try {
                    dain.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(daou!=null)
            {
                try {
                    daou.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

物件流 ObjectInputStream和ObjectOutputStream

注意
使用物件流寫入和讀取物件時,需要將類繼承Serialization(序列化)或者DeSerialization(反序列化)
物件(記憶體)---->位元組陣列(外存,網路)---->(物件)記憶體

  • static 修飾不參加序列化,可以使用transient使類的變數屬性不參加序列化
  • 序列化後不能修改類的內容(除非在建立類的時候,生成類的序列號)
  • 如果物件寫入檔案,不僅要保證物件序列化,也要保證物件成員變數序列化

public class TestObjectInputStream {
    public static void main(String[] args) {
        ObjectInputStream dain=null;
        ObjectOutputStream daou=null;
        try{
            //建立資料流
            daou=new ObjectOutputStream(new FileOutputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\Data.txt"));
            dain=new ObjectInputStream(new FileInputStream("C:\\Users\\cw\\Desktop\\Project\\Java\\study\\src\\com\\cwstd\\iostream\\Data.txt"));
            daou.writeBoolean(true);
            daou.writeChar('偉');
            daou.writeInt(12);
            daou.writeUTF("hhhhhhh");
            daou.writeObject(new Person(0,"cwstd",22));

            //讀取資料
            System.out.println(dain.readBoolean());
            System.out.println(dain.readChar());
            System.out.println(dain.readInt());
            System.out.println(dain.readUTF());
            System.out.println(dain.readObject().toString());

        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            if(dain!=null)
            {
                try {
                    dain.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(daou!=null)
            {
                try {
                    daou.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}