理解JAVA的IO

1. 什麼是流
Java中的流是對字節序列的抽象,咱們能夠想象有一個水管,只不過如今流動在水管中的再也不是水,而是字節序列。和水流同樣,Java中的流也具備一個「流動的方向」,一般能夠從中讀入一個字節序列的對象被稱爲輸入流;可以向其寫入一個字節序列的對象被稱爲輸出流java

2. 字節流
Java中的字節流處理的最基本單位爲單個字節,它一般用來處理二進制數據。Java中最基本的兩個字節流類是InputStream和OutputStream,它們分別表明了一組基本的輸入字節流和輸出字節流。InputStream類與OutputStream類均爲抽象類,咱們在實際使用中一般使用Java類庫中提供的它們的一系列子類。app

3. 字符流
Java中的字符流處理的最基本的單元是Unicode碼元(大小2字節),它一般用來處理文本數據。所謂Unicode碼元,也就是一個Unicode代碼單元,範圍是0×0000~0xFFFF。在以上範圍內的每一個數字都與一個字符相對應,Java中的String類型默認就把字符以Unicode規則編碼然後存儲在內存中。然而與存儲在內存中不一樣,存儲在磁盤上的數據一般有着各類各樣的編碼方式。使用不一樣的編碼方式,相同的字符會有不一樣的二進制表示。ui

4. 字符流與字節流的區別
通過以上的描述,咱們能夠知道字節流與字符流之間主要的區別體如今如下幾個方面:
    字節流操做的基本單元爲字節;字符流操做的基本單元爲Unicode碼元。
    字節流默認不使用緩衝區;字符流使用緩衝區。
    字節流一般用於處理二進制數據,實際上它能夠處理任意類型的數據,但它不支持直接寫入或讀取Unicode碼元;字符流一般處理文本數據,它支持寫入及讀取Unicode碼元。

示例一:文件讀取和寫入(支持編碼選擇、文件內容追加)編碼

/**
* 讀取文件文本內容。
*
* @param filePath 文件路徑
* @param charset  字符編碼格式
* @throws Exception
*/

public static String readAllText(String filePath, String charset) throws Exception {
StringBuilder sb = new StringBuilder();
try (
        InputStreamReader reader = new InputStreamReader(new FileInputStream(filePath), charset);
        BufferedReader br = new BufferedReader(reader)
) {
    String line;
    while ((line = br.readLine()) != null) {
        sb.append(line);
        sb.append(SystemCharUtils.getNewLine());
    }
} catch (Exception e) {
    throw e;
}

return sb.toString();
}


/**
* 將字符串追加到文件。
*
* @param str      待寫入字符串
* @param filePath 文件路徑(文件不存在則自動建立)
* @param charset  字符編碼
* @throws Exception
*/
public static void appendFile(String str, String filePath, String charset) throws Exception {
// 建立新文件對象。
File file = new File(filePath);

//自動建立目錄。
if (!file.getParentFile().exists()) {
    if (!file.getParentFile().mkdirs()) {
        throw new RuntimeException("文件目錄建立失敗:" + file.getParentFile().getAbsolutePath());
    }
}

//若是文件不存在則自動建立。
if (!file.exists()) {
    file.createNewFile();
}

try (
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file, true), charset);
        BufferedWriter bw = new BufferedWriter(writer);
) {
    bw.write(str);
} catch (Exception e) {
    throw e;
}
}

 

示例二:對象序列化到文件流 及 從文件流反序列化爲對象
注意:實體對象要實現Serializable接口。spa

/**
     * 序列化文件路徑。
     */
    String localFilePath = SystemCharUtils.getUserDir() + SystemCharUtils.getFileSeparator() + "data" + SystemCharUtils.getFileSeparator() + "test" +SystemCharUtils.getFileSeparator() + "testData.data";

    /**
     * 從文件流反序列化爲對象。
     *
     * @param filePath 文件路徑
     * @throws Exception
     */
    public static <T> T getObject(String filePath) throws Exception {
        try (
                ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(filePath));
        ) {
            return (T) inputStream.readObject();
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 將對象序列化到文件流。
     *
     * @param obj      須要序列化的對象
     * @param filePath 文件路徑
     * @throws Exception
     */
    public static void saveObject(Object obj, String filePath) throws Exception {
        // 建立新文件對象。
        File file = new File(filePath);

        //自動建立目錄。
        if (!file.getParentFile().exists()) {
            if (!file.getParentFile().mkdirs()) {
                throw new RuntimeException("文件目錄建立失敗:" + file.getParentFile().getAbsolutePath());
            }
        }

        //若是文件不存在則自動建立。
        if (!file.exists()) {
            file.createNewFile();
        }

        try (
                ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
        ) {
            outputStream.writeObject(obj);
        } catch (Exception e) {
            throw e;
        }
    }

 

 

相關文章
相關標籤/搜索