淺談基礎IO

目錄

IO 簡介

瞭解File類

1. File類基本介紹

2. File類常見操作

1. 流的基本概念

2. 輸入輸出流

3. 字節流

4. 字符流

序列化與反序列化


IO 簡介

在馮諾依曼體系結構我見到了各種各樣的輸入設備(鼠標、鍵盤、硬盤、網卡等等)和輸出設備(音響、屏幕、硬盤、、網卡等等)。其實,IO(Input/Output)其實解決的就是一個輸入輸出的問題。

          Input:數據從各種輸入設備以二進制流輸入到內存中
          Output:數據從內存以二進制流輸出到各種輸出設備

因爲有各種不同的輸入輸出設備,纔會出現不同的輸入輸出流。而且,數據天生的格式都是字節流(二進制流)。通過上面的分析,我們會發現硬盤既是一種輸入設備 又是一種輸出設備。那麼如何通過java提供的API把內存中的數據保存到硬盤中,又如何把硬盤中的數據讀入到內存中呢?我們必須要瞭解到下面的File類。

瞭解File類

1. File類基本介紹

File類其實就是描述文件源信息(屬性)的一組類。那麼文件是什麼呢?

書上是這麼描述的:文件是相關記錄或者放在一起的數據的集合。其實文件就是OS對硬盤空間一塊一塊的抽象。在windows操作中,經常在硬盤上創建的各種.txt, .doc, .exe, .java, .lib, .mp3等等,都可以稱之爲文件。文件簡單的可以理解成,在外設硬盤上面保存數據的一種方式。

文件一共可以由兩部分構成:屬性(文件大小,文件名,文件類型等)+內容(就是文件裏面放的是什麼) 。 File文件操作類在 java.io 包之中,用 File 類來對文件進行操作(創建、刪除、取得信息等)

2. File類常見操作

1. 獲取文件基本信息

    public static void main(String[] args) throws IOException {
        {
            // File 對象的實際文件不存在
            String path = "D:\\文檔\\File類練習\\test.txt";
            File file = new File(path);
            System.out.println(file);
        }

        // 傳入一個父路徑
        {
            String parent = "D:\\文檔\\File類練習";
            String path = "test.txt";
            File file = new File(parent, path);
            System.out.println(file);

            // 獲取常見的屬性
            System.out.println(file.exists()); //文件是否存在
            System.out.println(file.getAbsolutePath()); //返回絕對路徑
            System.out.println(file.getName());  //返回文件名
            System.out.println(file.getParent()); //返回父路徑
            System.out.println(file.isAbsolute()); //是否爲絕對路徑
            System.out.println(file.isDirectory()); //是否是目錄
            System.out.println(file.isFile()); //是否是文件
            System.out.println(file.isHidden()); //是否是隱藏的
            System.out.println(file.canRead()); //是否可讀
            System.out.println(file.canWrite()); //是否可寫
            System.out.println(file.canExecute()); //是否可執行
        }
}

2. 文件的創建

           //普通文件的創建
            String parent = "D:\\文檔\\File類練習"; //路徑
            String fileName = "文件1.txt"; //文件名

            File file = new File(parent, fileName);

3. 文件夾的創建

            // 文件夾的創建過程
            String parent = "D:\\文檔\\File類練習"; //父路徑
            String filename = "文件夾的創建"; //文件夾名稱
            File file = new File(parent, filename);

4. 文件的刪除

         file.deleteOnExit(); //請求在虛擬機終止時刪除由此抽象路徑名錶示的文件或目錄。 
         boolean delete = file.delete();// 只能刪除一個空的文件夾

5. 文件夾文件的操作

獲取文件夾下面的文件

            String path = "D:\\文檔";
            File dir = new File(path);

            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    System.out.println(file.getName());
                }
            }

1. 流的基本概念

Java中所有數據都是使用流讀寫的。流是一組有順序的,有起點和終點的字節集合,是對數據傳輸的總稱或抽象。即數據在兩設備間的傳輸稱爲流,流的本質是數據傳輸,根據數據傳輸特性將流抽象爲各種類,方便更直觀的進行數據操作。

2. 輸入輸出流

輸入就是將數據從各種輸入設備(包括文件、鍵盤等)中讀取到內存中。
輸出就是將數據從內存中寫入到各種輸出設備(比如文件、顯示器、磁盤等)。 
例如:鍵盤就是一個標準的輸入設備,而顯示器就是一個標準的輸出設備,但是文件既可以作爲輸入設備,又可以作爲輸出設備。

3. 字節流

字節流:數據流中最小的數據單元是字節。InputStreamOutputStream
 
文件輸入字節流(讀):
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("輸入文件.txt")) {
            byte[] buf = new byte[8192];
            int len;

            while ((len = is.read(buf)) != -1) {
                // 有效數據是 buf[0, len)
                for (int i = 0; i < len; i++) {
                    // 如果直接按照數字打印出來,就是打印 ASCII
                    // System.out.println(buf[i]);
                    char c = (char)buf[i];
                    System.out.print(c);
                }
            }
        }
    }

文件輸出字節流(寫):

    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("輸出內容.txt")) {
           
            // Second 一次寫一個字節的方式
            //寫法1
            os.write('S');
            os.write('e');
            os.write('c');
            os.write('o');
            os.write('n');
            os.write('d');
            os.write('\r');
            os.write('\n');

            
           // 寫法2
            byte[] buf = new byte[1024];
            buf[0] = (byte)'T';
            buf[1] = (byte)'h';
            buf[2] = (byte)'i';
            buf[3] = (byte)'r';
            buf[4] = (byte)'d';
            buf[5] = (byte)'\r';
            buf[6] = (byte)'\n';
            os.write(buf, 0, 7);

            //寫法3
            String s = "Hello World\r\n";
            byte[] bytes = s.getBytes(); //string內部可以把它轉爲byte類型數組
            os.write(bytes);

        
            os.flush(); // 保證把所有緩衝的數據全部寫入硬盤中
        }
    }
}

4. 字符流

字符流:數據流中最小的數據單元是字節, Java中的字符是Unicode編碼,一個字符佔用兩個字節:Reader、Writer

文件輸入字節流(讀):

    private static void read() throws IOException {
        try (InputStream is = new FileInputStream("某篇文章.txt")) {
            try (InputStreamReader isReader = new InputStreamReader(is, "UTF-8")) {
                try (Scanner scanner = new Scanner(isReader)) {
                    // 按行讀
                    while (scanner.hasNextLine()) {
                        String line = scanner.nextLine();
                    }
                }
            }
        }
    }

文件輸出字節流(寫):

    private static void write() throws IOException {
        try (OutputStream os = new FileOutputStream("某篇文章.txt")) {
            try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
                try (PrintWriter printWriter = new PrintWriter(osWriter)) {
                    printWriter.println("");
                    printWriter.printf("");
                    printWriter.print("");
                    printWriter.format("");

                    printWriter.flush();
                }
            }
        }
    }

那麼字符流和字節流有什麼區別呢?

1. 字節流操作的基本單元是字節;字符流操作的基本單元爲Unicode碼元。
2. 字節流在操作的時候本身不會用到緩衝區的,是與文件本身直接操作的;而字符流在操作的時候使
用到緩衝區的。
3. 所有文件的存儲都是字節(byte)的存儲,在磁盤上保留的是字節。
4. 在使用字節流操作中,即使沒有關閉資源(close方法),也能輸出;而字符流不使用close方法的
話,不會輸出任何內容。

序列化與反序列化

1. 什麼是序列化

序列化:把對象轉換爲字節序列的過程稱爲對象的序列化。

反序列化:把字節序列恢復爲對象的過程稱爲對象的反序列化。
 
其實就是達到信息持久化保存起來的效果,那麼序列化的意思就是把內存裏面的這些對象給變成一連串的字節描述的過程。常見的就是變成文件。

2. 序列化使用場景

3. 如何序列化

實現序列化其實有很多方式:Java對象序列化、JSON序列化、XML等等。如果Java對象進行序列化需要實現Serializable接口即可。

用一組例子來說明序列化和反序列化:

package uesFile.com;

import java.io.*;

public class SerializeDemo {
    // 聲明實現 Serializable 接口
    // 聲明之後,就擁有了可以序列號和反序列化的功能了
    static class Person implements Serializable {
        String name;
        int age;
    }

    //讀
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        try (InputStream is = new FileInputStream("名單.binary")) {
            try (ObjectInputStream ois = new ObjectInputStream(is)) {
                Person p = (Person) ois.readObject();
                System.out.println(p.name);
                System.out.println(p.age);
                Person q = (Person) ois.readObject();
                System.out.println(q.name);
                System.out.println(q.age);
            }
        }
    }

    
    //寫
    public static void main(String[] args) throws IOException {
        Person p = new Person();
        p.name = "人員1"; p.age = 34;
        Person q = new Person();
        q.name = "人員2"; q.age = 18;

        try (OutputStream os = new FileOutputStream("名單.binary")) {
            try (ObjectOutputStream oos = new ObjectOutputStream(os)) {
                oos.writeObject(p);
                oos.writeObject(q);

                oos.flush();
            }
        }
    }
    
}

就算程序關閉,文件中的內容也不會消失。實現了先寫,再進行讀的序列化。這就實現了Java對象的實例化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章