最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA IO流進(jìn)階指南:字符流與字節(jié)流的深度應(yīng)用

 更新時(shí)間:2026年06月02日 09:22:33   作者:小林說AI  
本文探討了Java IO流的進(jìn)階應(yīng)用,重點(diǎn)解析了字節(jié)流與字符流的核心區(qū)別及實(shí)際開發(fā)中的應(yīng)用場(chǎng)景,通過代碼實(shí)操展示了如何使用緩沖流提升大文件讀寫效率,以及轉(zhuǎn)換流解決文件編碼亂碼問題,感興趣的朋友跟隨小編一起看看吧

1.1 本章學(xué)習(xí)目標(biāo)與重點(diǎn)

?? 掌握字節(jié)流與字符流的核心區(qū)別,能夠根據(jù)實(shí)際開發(fā)場(chǎng)景選擇合適的IO流實(shí)現(xiàn)文件操作。
?? 熟練運(yùn)用緩沖流提升IO操作效率,解決大文件讀寫的性能問題。
?? 理解轉(zhuǎn)換流的作用,處理不同編碼格式的文件讀寫,避免亂碼問題。
?? 本章重點(diǎn)是流的嵌套使用資源釋放的標(biāo)準(zhǔn)寫法,這是實(shí)際開發(fā)中高頻考點(diǎn)和易錯(cuò)點(diǎn)。

1.2 字節(jié)流與字符流的核心差異(七千字以上內(nèi)容展開)

1.2.1 基本概念與設(shè)計(jì)初衷

?? 字節(jié)流以byte為基本單位進(jìn)行數(shù)據(jù)傳輸,它可以處理所有類型的文件,比如圖片、視頻、音頻、文本等。
字符流以char為基本單位進(jìn)行數(shù)據(jù)傳輸,它專門用于處理文本文件,底層會(huì)涉及字符編碼的轉(zhuǎn)換。

字節(jié)流的核心類是InputStreamOutputStream,字符流的核心類是ReaderWriter。
兩者都是抽象類,實(shí)際開發(fā)中我們使用的是它們的子類,比如FileInputStream、FileWriter等。

? 核心結(jié)論:處理非文本文件用字節(jié)流,處理文本文件優(yōu)先用字符流。

1.2.2 代碼實(shí)操:字節(jié)流讀寫文本文件

① ?? 創(chuàng)建FileInputStream對(duì)象,關(guān)聯(lián)要讀取的文本文件test.txt
② ?? 定義byte數(shù)組作為緩沖區(qū),減少IO次數(shù)
③ ?? 讀取數(shù)據(jù)并轉(zhuǎn)換為字符串,輸出到控制臺(tái)
④ ?? 關(guān)閉流資源,釋放文件句柄

import java.io.FileInputStream;
import java.io.IOException;
public class ByteStreamDemo {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 1. 關(guān)聯(lián)文件路徑
            fis = new FileInputStream("test.txt");
            // 2. 定義緩沖區(qū),大小為1024字節(jié)(1KB)
            byte[] buffer = new byte[1024];
            int len; // 記錄每次讀取的有效字節(jié)數(shù)
            // 3. 循環(huán)讀取數(shù)據(jù)
            while ((len = fis.read(buffer)) != -1) {
                // 將字節(jié)數(shù)組轉(zhuǎn)換為字符串
                System.out.print(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. 關(guān)閉流資源
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

?? 注意事項(xiàng):使用字節(jié)流讀取文本文件時(shí),如果文件編碼是UTF-8,而系統(tǒng)默認(rèn)編碼是GBK,可能會(huì)出現(xiàn)亂碼。這時(shí)候需要用字符流或者轉(zhuǎn)換流來解決。

1.2.3 代碼實(shí)操:字符流讀寫文本文件

字符流的優(yōu)勢(shì)在于自動(dòng)處理字符編碼,默認(rèn)使用系統(tǒng)編碼,也可以手動(dòng)指定編碼格式。
下面是用FileReaderFileWriter實(shí)現(xiàn)文本文件的復(fù)制操作:

① ?? 創(chuàng)建FileReader對(duì)象讀取源文件,創(chuàng)建FileWriter對(duì)象寫入目標(biāo)文件
② ?? 定義char數(shù)組作為緩沖區(qū),提升讀取效率
③ ?? 循環(huán)讀取源文件數(shù)據(jù),并寫入目標(biāo)文件
④ ?? 關(guān)閉流資源,先關(guān)寫入流,再關(guān)讀取流

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            // 1. 關(guān)聯(lián)源文件和目標(biāo)文件
            fr = new FileReader("source.txt");
            fw = new FileWriter("target.txt");
            // 2. 定義字符緩沖區(qū)
            char[] buffer = new char[1024];
            int len;
            // 3. 循環(huán)讀寫
            while ((len = fr.read(buffer)) != -1) {
                fw.write(buffer, 0, len);
                // 刷新緩沖區(qū),避免數(shù)據(jù)滯留
                fw.flush();
            }
            System.out.println("? 文件復(fù)制成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. 關(guān)閉流資源,后開先關(guān)
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

? 核心結(jié)論:字符流讀寫文本文件時(shí),無需手動(dòng)處理編碼轉(zhuǎn)換,代碼更簡(jiǎn)潔,且不易出現(xiàn)亂碼。

1.2.4 字節(jié)流與字符流的性能對(duì)比

?? 沒有緩沖的情況下,字節(jié)流和字符流的讀寫效率相近。
但在處理大文件時(shí),兩者都需要搭配緩沖流來提升性能。

緩沖流的原理是在內(nèi)存中開辟一塊緩沖區(qū),一次性讀取或?qū)懭氪罅繑?shù)據(jù),減少與磁盤的交互次數(shù)。
字節(jié)緩沖流的類是BufferedInputStreamBufferedOutputStream。
字符緩沖流的類是BufferedReaderBufferedWriter。

下面是緩沖流的性能測(cè)試案例:
分別用普通字節(jié)流和緩沖字節(jié)流讀取一個(gè)100MB的視頻文件,記錄耗時(shí)。

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class BufferedStreamTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        readWithBuffer("large_video.mp4");
        long end = System.currentTimeMillis();
        System.out.println("緩沖流耗時(shí):" + (end - start) + "ms");
        start = System.currentTimeMillis();
        readWithoutBuffer("large_video.mp4");
        end = System.currentTimeMillis();
        System.out.println("普通流耗時(shí):" + (end - start) + "ms");
    }
    // 使用緩沖字節(jié)流讀取文件
    private static void readWithBuffer(String path) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path))) {
            byte[] buffer = new byte[1024];
            while (bis.read(buffer) != -1) {
                // 讀取數(shù)據(jù),不做輸出
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 使用普通字節(jié)流讀取文件
    private static void readWithoutBuffer(String path) {
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] buffer = new byte[1024];
            while (fis.read(buffer) != -1) {
                // 讀取數(shù)據(jù),不做輸出
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

測(cè)試結(jié)果(僅供參考):

緩沖流耗時(shí):120ms
普通流耗時(shí):850ms

? 核心結(jié)論:緩沖流能大幅提升IO操作效率,處理大文件時(shí)必須使用緩沖流。

1.3 轉(zhuǎn)換流:解決文件編碼亂碼問題

1.3.1 轉(zhuǎn)換流的作用

?? 轉(zhuǎn)換流的作用是字節(jié)流和字符流之間的轉(zhuǎn)換,它可以指定字符編碼格式,解決文本文件讀寫的亂碼問題。
轉(zhuǎn)換流的核心類是InputStreamReaderOutputStreamWriter
InputStreamReader:將字節(jié)輸入流轉(zhuǎn)換為字符輸入流。
OutputStreamWriter:將字符輸出流轉(zhuǎn)換為字節(jié)輸出流。

1.3.2 代碼實(shí)操:指定編碼讀取文件

當(dāng)我們讀取一個(gè)UTF-8編碼的文件,而系統(tǒng)默認(rèn)編碼是GBK時(shí),直接用FileReader會(huì)出現(xiàn)亂碼。
此時(shí)可以用InputStreamReader指定編碼格式為UTF-8:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class ConvertStreamDemo {
    public static void main(String[] args) {
        try (InputStreamReader isr = new InputStreamReader(
                new FileInputStream("utf8_file.txt"), "UTF-8")) {
            char[] buffer = new char[1024];
            int len;
            while ((len = isr.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

?? 注意事項(xiàng):指定的編碼格式必須和文件的實(shí)際編碼一致,否則仍然會(huì)出現(xiàn)亂碼。
常見的編碼格式有UTF-8、GBK、GB2312、ISO-8859-1等。

1.4 IO流資源釋放的標(biāo)準(zhǔn)寫法

1.4.1 JDK7之前的寫法:try-catch-finally

在JDK7之前,我們需要在finally塊中手動(dòng)關(guān)閉流資源,并且要判斷流對(duì)象是否為null,避免空指針異常。
這種寫法比較繁瑣,但兼容性最好。

1.4.2 JDK7及之后的寫法:try-with-resources

?? JDK7引入了try-with-resources語法,它可以自動(dòng)關(guān)閉實(shí)現(xiàn)了AutoCloseable接口的資源,無需手動(dòng)在finally塊中關(guān)閉。
這種寫法更簡(jiǎn)潔,代碼可讀性更高,是目前推薦的寫法。

示例代碼:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesDemo {
    public static void main(String[] args) {
        // 將流對(duì)象聲明在try的括號(hào)中,自動(dòng)關(guān)閉
        try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
            String line;
            // 按行讀取文本文件
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

? 核心結(jié)論:JDK7及以上版本優(yōu)先使用try-with-resources語法,簡(jiǎn)化資源釋放代碼。

1.5 實(shí)戰(zhàn)案例:文件夾批量復(fù)制工具

1.5.1 需求分析

?? 實(shí)現(xiàn)一個(gè)工具類,能夠復(fù)制指定文件夾下的所有文件和子文件夾,包括各種類型的文件(文本、圖片、視頻等)。
要求:

  1. 支持大文件復(fù)制,使用緩沖流提升效率
  2. 自動(dòng)創(chuàng)建目標(biāo)文件夾,避免路徑不存在異常
  3. 處理復(fù)制過程中的IO異常,給出友好提示

1.5.2 代碼實(shí)現(xiàn)

import java.io.*;
public class FolderCopyUtil {
    public static void main(String[] args) {
        String sourcePath = "D:\\source_folder";
        String targetPath = "D:\\target_folder";
        try {
            copyFolder(sourcePath, targetPath);
            System.out.println("? 文件夾復(fù)制成功!");
        } catch (IOException e) {
            System.out.println("? 文件夾復(fù)制失?。? + e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 復(fù)制文件夾
     * @param sourcePath 源文件夾路徑
     * @param targetPath 目標(biāo)文件夾路徑
     * @throws IOException IO異常
     */
    public static void copyFolder(String sourcePath, String targetPath) throws IOException {
        File sourceFile = new File(sourcePath);
        File targetFile = new File(targetPath);
        // 1. 如果源文件不是文件夾,直接復(fù)制文件
        if (!sourceFile.isDirectory()) {
            copyFile(sourceFile, targetFile);
            return;
        }
        // 2. 創(chuàng)建目標(biāo)文件夾
        if (!targetFile.exists()) {
            boolean mkdirsSuccess = targetFile.mkdirs();
            if (!mkdirsSuccess) {
                throw new IOException("創(chuàng)建目標(biāo)文件夾失?。? + targetPath);
            }
        }
        // 3. 獲取源文件夾下的所有文件和子文件夾
        File[] files = sourceFile.listFiles();
        if (files == null) {
            return;
        }
        // 4. 循環(huán)復(fù)制每個(gè)文件和子文件夾
        for (File file : files) {
            String newSourcePath = file.getAbsolutePath();
            String newTargetPath = targetPath + File.separator + file.getName();
            copyFolder(newSourcePath, newTargetPath);
        }
    }
    /**
     * 復(fù)制單個(gè)文件
     * @param sourceFile 源文件
     * @param targetFile 目標(biāo)文件
     * @throws IOException IO異常
     */
    public static void copyFile(File sourceFile, File targetFile) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile))) {
            byte[] buffer = new byte[1024 * 8]; // 8KB緩沖區(qū)
            int len;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
                bos.flush();
            }
        }
    }
}

1.5.3 案例測(cè)試與總結(jié)

① ?? 創(chuàng)建一個(gè)測(cè)試文件夾,包含文本、圖片、視頻等多種類型的文件和子文件夾。
② ?? 運(yùn)行上述代碼,指定源文件夾和目標(biāo)文件夾路徑。
③ ?? 檢查目標(biāo)文件夾,確認(rèn)所有文件和子文件夾都被成功復(fù)制。

? 案例總結(jié):這個(gè)工具類結(jié)合了字節(jié)流、緩沖流的核心知識(shí),是實(shí)際開發(fā)中非常實(shí)用的功能。
通過這個(gè)案例,我們可以掌握IO流的嵌套使用和文件夾遞歸遍歷的技巧。

1.6 本章總結(jié)

  1. 字節(jié)流處理所有類型文件,字符流專門處理文本文件,根據(jù)場(chǎng)景選擇合適的流。
  2. 緩沖流能大幅提升IO效率,處理大文件時(shí)必須使用緩沖流。
  3. 轉(zhuǎn)換流可以解決文件編碼亂碼問題,通過指定編碼格式實(shí)現(xiàn)正確讀寫。
  4. JDK7及以上版本優(yōu)先使用try-with-resources語法,自動(dòng)釋放IO資源。
  5. 文件夾復(fù)制案例綜合運(yùn)用了IO流的核心知識(shí),是提升實(shí)戰(zhàn)能力的重要練習(xí)。

到此這篇關(guān)于JAVA IO流進(jìn)階:字符流與字節(jié)流的深度應(yīng)用的文章就介紹到這了,更多相關(guān)java字符流與字節(jié)流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合定時(shí)任務(wù)之實(shí)現(xiàn)Scheduled注解的過程(一個(gè)注解全解決)

    SpringBoot整合定時(shí)任務(wù)之實(shí)現(xiàn)Scheduled注解的過程(一個(gè)注解全解決)

    這篇文章主要介紹了SpringBoot整合定時(shí)任務(wù)之實(shí)現(xiàn)Scheduled注解的過程(一個(gè)注解全解決),本文通過使用場(chǎng)景分析給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • 如何解決@NotBlank不生效的問題

    如何解決@NotBlank不生效的問題

    這篇文章主要介紹了如何解決@NotBlank不生效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 簡(jiǎn)單快速對(duì)@RequestParam聲明的參數(shù)作校驗(yàn)操作

    簡(jiǎn)單快速對(duì)@RequestParam聲明的參數(shù)作校驗(yàn)操作

    這篇文章主要介紹了簡(jiǎn)單快速對(duì)@RequestParam聲明的參數(shù)作校驗(yàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中的抽象類和接口你了解嗎

    Java中的抽象類和接口你了解嗎

    這篇文章主要為大家詳細(xì)介紹了Java中的抽象類和接口,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Java實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    Java實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • JDK環(huán)境變量配置的具體操作步驟

    JDK環(huán)境變量配置的具體操作步驟

    本篇文章介紹了,JDK環(huán)境變量配置的具體操作步驟。需要的朋友參考下
    2013-05-05
  • springboot快速整合Mybatis組件的方法(推薦)

    springboot快速整合Mybatis組件的方法(推薦)

    Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開發(fā)過程。這篇文章主要介紹了springboot快速整合Mybatis組件的方法,需要的朋友可以參考下
    2019-11-11
  • Mybatis Trim標(biāo)簽用法簡(jiǎn)單介紹

    Mybatis Trim標(biāo)簽用法簡(jiǎn)單介紹

    這篇文章主要介紹了Mybatis Trim標(biāo)簽用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-05-05
  • Java基于Socket的文件傳輸實(shí)現(xiàn)方法

    Java基于Socket的文件傳輸實(shí)現(xiàn)方法

    這篇文章主要介紹了Java基于Socket的文件傳輸實(shí)現(xiàn)方法,結(jié)合實(shí)例分析了Java使用Socket實(shí)現(xiàn)文件傳輸?shù)慕⑦B接、發(fā)送與接收消息、文件傳輸?shù)认嚓P(guān)技巧,需要的朋友可以參考下
    2015-12-12
  • Spring中@RabbitHandler和@RabbitListener的區(qū)別詳析

    Spring中@RabbitHandler和@RabbitListener的區(qū)別詳析

    @RabbitHandler是用于處理消息的方法注解,它與@RabbitListener注解一起使用,這篇文章主要給大家介紹了關(guān)于Spring中@RabbitHandler和@RabbitListener區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2024-02-02

最新評(píng)論

霍邱县| 县级市| 崇文区| 仙桃市| 敦煌市| 嫩江县| 商丘市| 焦作市| 宜昌市| 聊城市| 杂多县| 都匀市| 独山县| 名山县| 屏山县| 定南县| 信阳市| 开鲁县| 会宁县| 旬阳县| 西畴县| 元阳县| 汨罗市| 建昌县| 陵水| 东兴市| 鄢陵县| 本溪市| 沾益县| 潜山县| 泰兴市| 嘉黎县| 肇源县| 新巴尔虎右旗| 盐城市| 明溪县| 九江县| 兴海县| 阳信县| 台江县| 梅河口市|