1. 程式人生 > 其它 >Java基礎之IO

Java基礎之IO

File類

File類構造方法

  • public File(String pathname)
  • public File(String parent, String child)
  • public File(File parent, String child)

File類常用方法之get

  • public String getAbsolutePath():獲取絕對路徑
  • public String getPath() :獲取路徑
  • public String getName() :獲取名稱
  • public String getParent():獲取上層檔案目錄路徑。若無,返回null
  • public long length() :獲取檔案長度(即:位元組數)。不能獲取目錄的長度。
  • public long lastModified() :獲取最後一次的修改時間,毫秒值
  • public String[] list() :獲取指定目錄下的所有檔案或者檔案目錄的名稱陣列
  • public File[] listFiles() :獲取指定目錄下的所有檔案或者檔案目錄的File陣列

File常用方法之重新命名

  • public boolean renameTo(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() :建立檔案目錄。如果上層檔案目錄不存在,一併建立

File常用方法之刪除

  • public boolean delete():刪除檔案或者資料夾(要刪除一個檔案目錄,請注意該檔案目錄內不能包含檔案或者檔案目錄)

IO概述

流的分類

  • 按照資料單位,分為:位元組流(8bit)、字元流(16bit)
  • 按照流向,分為:輸入流、輸出流
  • 按照角色,分為:節點流、處理流

IO流的體系

檔案流(節點流)

  • FileReader, FileWriter 字元流用來讀取和吸入文字文件,如.txt, .java, .html
  • FileInputStream, FileOutputStream 位元組流用來處理非文字文件,如.doc, .jpg, .mp3, .mp4

FileReader 文字字元輸入流

  • public int read():讀取一個字元並返回,到了檔案末尾時返回-1
  • public int read(char cbuf[]):讀取一定數量的字元至cbuf中,返回讀取的長度,到了檔案末尾時返回-1
    @Test
    public void testFileReader() {
        // 1.建立檔案
        File file = new File("test.txt");
        FileReader fileReader = null;
        try {
            // 2.建立輸入流
            fileReader = new FileReader(file);
            // 3.讀取輸入
            int c;
            while ((c = fileReader.read()) != -1) {
                System.out.print((char) c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4.關閉資源
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void testFileReader1() {
        // 1.建立檔案
        File file = new File("test.txt");
        FileReader fileReader = null;
        try {
            // 2.建立輸入流
            fileReader = new FileReader(file);
            // 3.讀取輸入
            char[] buffer = new char[5];
            int len;
            while ((len = fileReader.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4.關閉資源
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

FileWriter 文字字元輸出流

構造方法:

  • public FileWriter(String fileName | File file, boolean append) : append為true時續寫檔案,append為false時重寫檔案
  • public FileWriter(String fileName | File file), 相當於FileWriter(String fileName | File file, false)

注意事項:

  • Writer和OutputStream操作的檔案如果不存在,不會報錯,並將自動建立該檔案
    @Test
    public void testFileWriter() {
        FileWriter fileWriter = null;
        try {
            // 1.建立檔案
            File file = new File("test1.txt");
            // 2.建立輸出流
            fileWriter = new FileWriter(file, false);
            // 3.寫入
            fileWriter.write("Hello World!\n");
            fileWriter.write("我愛北京天安門\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4.關閉資源
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

FileInputStream、FileOutputStream 文字位元組輸入輸出流

    /**
     * 使用FileInputStream和FileOutputStream實現通用的檔案拷貝
     */
    public void fileCopy(String src, String dest) {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            File srcFile = new File(src);
            File destFile = new File(dest);

            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile, false);

            byte[] buffer = new byte[1024];
            int len;
            while((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

緩衝流

原理

為了提高資料讀寫的速度,Java API提供了帶緩衝功能的流類,在使用這些流類時,會建立一個內部緩衝區陣列,預設使用8192個位元組或字元的緩衝區

BufferedInputStream、BufferedOutputStream

    public void fileCopy(String src, String dest) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));

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

        out.close();
        in.close();
    }

BufferReader、BufferedWriter

注意點:

  • BufferedReader除了可以使用read()方法之外,還封裝了一個readLine()方法用於讀取一行,到檔案末尾時返回null
  • readLine()方法返回的字串不好含換行符,如需輸出換行符,可手動拼接換行符或使用BufferedWriter.newLine()換行
    public void testBufferedReaderWriter() throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("test(1).txt"));

        // 方式1:
//        char[] cbuf = new char[10];
//        int len;
//        while ((len = reader.read(cbuf)) != -1) {
//            writer.write(cbuf, 0, len);
//        }

        // 方式2:
        String line;
        while ((line = reader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
        }

        writer.close();
        reader.close();
    }

轉換流

轉換流提供了位元組流和字元流之間的轉換,常用來時間檔案編碼的轉換:

  • InputStreamReader:將InputStream轉換為Reader
  • OutputStreamWriter:將Writer轉換為OutputStream
    public void utf8ToGbk() throws IOException {
        InputStreamReader reader = new InputStreamReader(new FileInputStream("test.txt"), "UTF-8");
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("test_gbk.txt"), "GBK");

        char[] cbuf = new char[10];
        int len;
        while ((len = reader.read(cbuf)) != -1) {
            writer.write(cbuf, 0, len);
        }

        reader.close();
        writer.close();
    }

標準輸入輸出流(瞭解)

  • System.in 標準輸入流,型別是InputStream,預設輸入裝置是鍵盤,可通過System.setIn(InputStream in)設定輸入裝置
  • System.out 標準輸出流,型別是PrintStream,預設輸出裝置是控制檯,可通過System.setOut(PrintStream out)設定輸出裝置
    /**
     * 從鍵盤輸入字串,要求將讀取到的整行字串轉成大寫輸出。
     * 然後繼續進行輸入操作,直至當輸入“e”或者“exit”時,退出程式。
     */
    public static void main(String[] args) throws IOException {
        // 為了藉助BufferedReader的readLine()方法,這裡先把System.in(InputStream)轉為轉換流,又轉為了緩衝流
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String line;
        while ((line = reader.readLine()) != null) {
            if (!line.equals("e") && !line.equals("exit")) {
                System.out.println(line);
            } else {
                break;
            }
        }

        reader.close();
    }

列印流(瞭解)

列印流:PrintStream和PrintWriter

  • 提供了一系列過載的print()和println()方法,用於多種資料型別的輸出
  • PrintStream和PrintWriter的輸出不會丟擲IOException異常
  • PrintStream和PrintWriter有自動flush功能
  • PrintStream 列印的所有字元都使用平臺的預設字元編碼轉換為位元組。
    在需要寫入字元而不是寫入位元組的情況下,應該使用 PrintWriter 類。
  • System.out返回的是PrintStream的例項
    public void testPrintStream() throws FileNotFoundException {
        PrintStream out = new PrintStream(new FileOutputStream("test11.txt"));
        System.setOut(out);

        for (int i = 0; i <= 255; i++) {
            System.out.print((char) i);
            if (i % 50 == 0) {
                System.out.println();
            }
        }

        out.close();
    }

資料流(瞭解)

資料流有兩個類:(用於讀取和寫出基本資料型別、String類的資料)DataInputStream 和 DataOutputStream

    /**
     * 資料流:寫入
     */
    @Test
    public void testDataOutputStream() throws IOException {
        DataOutputStream out = new DataOutputStream(new FileOutputStream("test.dat"));

        out.writeUTF("張三");
        out.writeInt(30);
        out.writeBoolean(true);

        out.close();
    }


    /**
     * 資料流:讀取
     */
    @Test
    public void testDataInputStream() throws IOException {
        DataInputStream in = new DataInputStream(new FileInputStream("test.dat"));

        String name = in.readUTF();
        int age = in.readInt();
        boolean isAlive = in.readBoolean();

        System.out.println("name:" + name);
        System.out.println("age:" + age);
        System.out.println("isAlive:" + isAlive);

        in.close();
    }

物件流

可序列化物件的要求:

  • 需要實現介面:Serializable
  • 當前類提供一個全域性常量:serialVersionUID
  • 類內部所有屬性也必須是可序列化的(預設情況下,基本資料型別可序列化)
/**
 * 物件序列化與反序列化
 */
public class IOTest7 {
    /**
     * 物件序列化
     */
    @Test
    public void testObjectOutputStream() throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.obj"));

        out.writeObject("我愛你中國");

        Person person = new Person("張三", 30, true);
        out.writeObject(person);

        out.close();
    }

    /**
     * 物件反序列化
     */
    @Test
    public void testObjectInputStream() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("test.obj"));

        String str = (String) in.readObject();
        System.out.println(str);

        Person person = (Person) in.readObject();
        System.out.println(person);

        in.close();
    }
}

class Person implements Serializable {
    public static final long serialVersionUID = 20211021L;

    private String name;
    private int age;
    private boolean isAlive;

    public Person(String name, int age, boolean isAlive) {
        this.name = name;
        this.age = age;
        this.isAlive = isAlive;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isAlive=" + isAlive +
                '}';
    }
}