<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    死磕 IO 流?你都磕對地方了么

    共 22180字,需瀏覽 45分鐘

     ·

    2021-04-21 18:25

    微信搜一搜
    村雨遙

    前言

    我們?nèi)粘i_發(fā)過程中,有許多方面都涉及到 IO 流,比如上傳下載、傳輸、設(shè)計(jì)模式等等。而所有的一切都是基于 IO 流來進(jìn)行,所以今天就來看看 Java 中 IO 流的相關(guān)知識點(diǎn)。

    本文主要內(nèi)容安排如下:

    • 文件對象
    • 流簡介
    • 字節(jié)流
    • 字符流

    文件對象

    文件路徑

    Java 標(biāo)準(zhǔn)庫 java.io 提供了 File 對象用于操作文件和目錄,也就是說我們的文件和目錄都是可以通過 File 封裝成對象的。構(gòu)造 File 對象時(shí),需要傳入我們的文件或目錄的路徑名,常用的構(gòu)造方法如下:

    方法描述
    File(String pathName)通過將給定路徑名字符串轉(zhuǎn)換為抽象路徑名來創(chuàng)建新實(shí)例
    File(String parent, String child)從父路徑名字符串和子路徑名字符串創(chuàng)建新實(shí)例
    File(File parent, String child)從父抽象路徑名和子路徑名字符串創(chuàng)建新實(shí)例
    import java.io.File;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : FileObject
     * @date : 2021/4/20 9:20
     * @description : 創(chuàng)建 File 對象的三個(gè)構(gòu)造方法
     */


    public class FileObject {
        public static void main(String[] args) {

            File file1 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/1.txt");
            System.out.println(file1);

            File file2 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data""1.txt");
            System.out.println(file2);

            File file3 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data");
            File file4 = new File(file3, "1.txt");
            System.out.println(file4);
        }
    }

    對于我們傳入文件的路徑,既可以使用絕對路徑,也可以使用相對路徑。

    • 相對路徑:以當(dāng)前文件所在位置為參考,然后建立出另一個(gè)文件所在位置路徑。我們最常用的有 ...,前者表示當(dāng)前目錄,而后者則表示當(dāng)前目錄的上一級目錄。假設(shè)我們當(dāng)前目錄為 /home/cunyu1943/data,則 . 仍然表示該目錄,而 .. 則表示 /home/cunyu1943 目錄。
    • 絕對路徑:又可以分為 本地絕對路徑網(wǎng)絡(luò)絕對路徑。本地絕對路徑以根目錄為參考,指文件在硬盤中真實(shí)存在的路徑,比如在 Windows 系統(tǒng),我們的一個(gè)絕對路徑是 D:\\Softwares\\Typora\\Typora.exe,而在類 Unix 系統(tǒng)中則為 /home/cunyu1943/IO.md,此時(shí)需要注意平臺間的分隔符是不一樣的,但為了同一,推薦同一寫成 /,這樣程序在不同系統(tǒng)中遷移時(shí)也不會(huì)出現(xiàn)問題。而網(wǎng)絡(luò)絕對位置則指帶有網(wǎng)址的路徑,比如 https://cunyu1943.site/index.html
    import java.io.File;
    import java.io.IOException;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : FilePath
     * @date : 2021/4/20 9:55
     * @description : 文件路徑
     */


    public class FilePath {
        public static void main(String[] args) throws IOException {
            File file = new File("../data/1.txt");
            System.out.println(file.getPath());
            System.out.println(file.getAbsolutePath());
            System.out.println(file.getCanonicalPath());
        }
    }

    文件和目錄操作

    創(chuàng)建與刪除

    既然拿到了 File 對象,接下來就是通過操作該對象來進(jìn)行創(chuàng)建和刪除文件或目錄了,以下是一些 File 類常用的創(chuàng)建和刪除方法。

    返回值方法描述
    booleancreateNewFile()當(dāng)具有該名稱的文件不存在時(shí),創(chuàng)建一個(gè)由該抽象路徑名命名的新空文件;存在時(shí),則創(chuàng)建失敗
    booleanmkdir()創(chuàng)建由此抽象路徑名命名的目錄
    booleanmkdirs()創(chuàng)建由此抽象路徑名命名的多級目錄,包括任何必需但不存在的父目錄
    booleandelete()刪除由此抽象路徑名命名的文件或目錄,刪除目錄的前提是該目錄必須為空
    import java.io.File;
    import java.io.IOException;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : CreateAndDelete
     * @date : 2021/4/20 10:40
     * @description : 創(chuàng)建&刪除
     */


    public class CreateAndDelete {
        public static void main(String[] args) throws IOException {
            File file1 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/2.txt");
            if (file1.createNewFile()) {
                System.out.println("創(chuàng)建文件成功");
            } else {
                System.out.println("創(chuàng)建文件失敗");
            }

            if (file1.delete()) {
                System.out.println("刪除文件成功");
            } else {
                System.out.println("刪除文件失敗");
            }

            File file2 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/demo");
            if (file2.mkdir()) {
                System.out.println("創(chuàng)建文件夾成功");
            } else {
                System.out.println("創(chuàng)建文件夾失敗");
            }

            File file3 = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/JavaSE/demo");
            if (file3.mkdirs()) {
                System.out.println("創(chuàng)建多級目錄成功");
            } else {
                System.out.println("創(chuàng)建多級目錄失敗");
            }
        }
    }

    注意

    • 創(chuàng)建文件時(shí),調(diào)用的是 createNewFile() 方法,而創(chuàng)建目錄時(shí)調(diào)用的是 mkdir() 或者 mkdirs() 方法。我們在調(diào)用時(shí)要注意區(qū)分,否則就算你的路徑是文件,當(dāng)調(diào)用了創(chuàng)建目錄的方法后它也會(huì)創(chuàng)建成目錄而非文件。對應(yīng)的,就算你給定的路徑是目錄,當(dāng)調(diào)用創(chuàng)建文件的方法后它也會(huì)創(chuàng)建成文件而非目錄。

    • 刪除目錄時(shí),若目錄中有內(nèi)容(目錄、文件),則 不能直接刪除,而是應(yīng)該先刪除目錄中的內(nèi)容,然后才能刪除目錄;

    相關(guān)屬性

    獲取到 File 對象后,我們可以對其相關(guān)屬性進(jìn)行判斷,常用方法如下:

    返回值方法描述
    longlength()該抽象路徑名表示的文件的所占字節(jié)大小
    booleancanRead()該抽象路徑名表示的文件是否可讀
    booleancanWrite()該抽象路徑名表示的文件是否可寫
    booleancanExecute()該抽象路徑名表示的文件是否可執(zhí)行
    import java.io.File;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : Main
     * @date : 2021/4/20 11:04
     * @description : 相關(guān)屬性
     */


    public class Main {
        public static void main(String[] args) {
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/new.txt");

            if (file.canExecute()) {
                System.out.println("該對象可執(zhí)行");
            } else {
                System.out.println("該對象不可執(zhí)行");
            }
            if (file.canRead()) {
                System.out.println("該對象可讀");
            } else {
                System.out.println("該對象不可讀");
            }
            if (file.canWrite()) {
                System.out.println("該對象可寫");
            } else {
                System.out.println("該對象不可寫");
            }

            System.out.println("文件大?。? + file.length() + " Byte");
        }
    }

    判斷和獲取

    獲取到 File 對象后,我們既可以用它來表示文件,也可以用來表示目錄。而對于文件和目錄的判斷和獲取功能,可以使用如下常用的方法:

    返回值方法描述
    booleanisFile()測試此抽象路徑名表示的文件是否為普通文件
    booleanisDirectory()測試此抽象路徑名表示的文件是否為目錄
    booleanexists()測試此抽象路徑名表示的文件或目錄是否存在
    StringgetPath()將抽象路徑轉(zhuǎn)換為路徑字符串
    StringgetAbsolutePath()返回此抽象路徑名的絕對路徑名字符串
    StringgetName()返回由此抽象路徑名表示的文件或目錄的名稱
    String[]list()返回字符串?dāng)?shù)組,表示該抽象路徑名表示目錄下的文件和目錄
    File[]listFiles()返回抽象路徑名數(shù)組,表示該抽象路徑名表示目錄下的文件
    import java.io.File;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : Main
     * @date : 2021/4/20 11:15
     * @description : 判斷和獲取
     */


    public class Main {
        public static void main(String[] args) {
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data");
            System.out.println(file.isDirectory());
            System.out.println(file.isFile());
            System.out.println(file.exists());
            System.out.println("-------------------------");
            System.out.println(file.getPath());
            System.out.println(file.getAbsolutePath());
            System.out.println(file.getName());
            System.out.println("-------------------------");
            System.out.println("目錄下的文件和目錄列表:(文件或目錄名)");
            for (String path : file.list()) {
                System.out.println(path);
            }
            System.out.println("-------------------------");
            System.out.println("目錄下的文件和目錄列表:(完整絕對路徑)");
            for (File path : file.listFiles()) {
                System.out.println(path);
            }
        }
    }

    練習(xí)

    假設(shè)我們要遍歷 Windows 下 C 盤的 Windows 目錄,并且列出其中文件名和文件大小,而不用列出目錄名,我們可以利用如下代碼來實(shí)現(xiàn):

    import java.io.File;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : Test
     * @date : 2021/4/20 11:40
     * @description : 遍歷 C 盤 Windows 目錄下的文件,并打印文件名和大小
     */


    public class Test {
        public static void main(String[] args) {
            File file = new File("C:/windows");
            for (File item : file.listFiles()) {
                if (item.isFile()) {
                    System.out.println("文件名:" + item.getName() + "\t文件大小占:" + item.length() + " 字節(jié)");
                }
            }
        }
    }

    什么是流

    所謂流,就是一系列數(shù)據(jù)的組合。當(dāng)我們需要進(jìn)行數(shù)據(jù)交互的時(shí)候,比如在服務(wù)器和客戶端之間進(jìn)行數(shù)據(jù)交互時(shí),我們此時(shí)就可以使用 Java 中的流來實(shí)現(xiàn)。Java 中,數(shù)據(jù)的輸入和輸出都是以流的形式來進(jìn)行的。根據(jù)數(shù)據(jù)流方向的不同,我們可以將其分為:輸入流、輸出流。而根據(jù)處理的數(shù)據(jù)單位不同,可分為:字節(jié)流、字符流。兩者的關(guān)系可以描述為下表:


    字節(jié)流字符流
    輸入流InputStreamReader
    輸出流OutputStreamWriter

    而對于字節(jié)流和字符流的選用原則,我們建議遵循如下規(guī)則:如果數(shù)據(jù)能夠通過 Windows 自帶筆記本軟件打開并且能夠讀懂其中的內(nèi)容,則選用字符流,否則選擇字節(jié)流。而如果我們也不知道應(yīng)該使用何種類型的流,則默認(rèn)使用字節(jié)流。

    下圖描述了字節(jié)流和字符流的類層次圖,注意:無論是字節(jié)流還是字符流,其子類名都是以其父類名作為子類名的后綴的

    IO 流.png

    InputStream

    InputStream.png

    注意,InputStream 并非是并不是一個(gè)接口,而是所有字節(jié)輸入流所有類的父類。下面我們主要以 FileInputStream 來舉例,所謂 FileInputStream,就是從文件流中讀取數(shù)據(jù),然后將數(shù)據(jù)從文件中讀取到內(nèi)存,常用方法如下:

    返回值方法描述
    intavailable()返回該輸入流中可以讀取的字節(jié)數(shù)的估計(jì)值
    voidclose()關(guān)閉輸入流并釋放相關(guān)資源
    intread(bytep[] b)從輸入流讀取一些字節(jié)數(shù),并將其存儲(chǔ)到緩沖區(qū) b

    下面是一個(gè)從文件中讀取數(shù)據(jù)到內(nèi)存中的實(shí)例,文件內(nèi)容如下:

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : TestInputStream
     * @date : 2021/4/20 15:29
     * @description : InputStream 實(shí)例
     */


    public class TestInputStream {

        public static void main(String[] args) {

            String result = null;
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/1.txt");
            try (InputStream inputStream = new FileInputStream(file)) {

    //            讀取輸入流中可以被讀的 bytes 估計(jì)值
                int size = inputStream.available();
    //            根據(jù) bytes 數(shù)創(chuàng)建數(shù)組
                byte[] array = new byte[size];
    //            數(shù)據(jù)讀取到數(shù)組
                inputStream.read(array);
    //            數(shù)組轉(zhuǎn)化為字符串
                result = new String(array);

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

    //        打印字符串
            System.out.println(result);

        }
    }

    OutputStream

    OutputStream.png

    OutputStream 并非是并不是一個(gè)接口,而是所有輸出字節(jié)流的所有類的父類。下面我們主要以 FileOutputStream 來舉例,所謂 FileOutputStream,就是從內(nèi)存中讀取數(shù)據(jù),然后將數(shù)據(jù)從內(nèi)存存放到文件中,常用方法如下:

    返回值方法描述
    voidwrite(byte[] b)b.length 個(gè)字節(jié)從指定字節(jié)數(shù)組寫入此文件輸出流
    voidclose()關(guān)閉文件輸出流并釋放相關(guān)資源
    import java.io.*;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : TestOutputStream
     * @date : 2021/4/20 15:58
     * @description : OutputStream 實(shí)例
     */


    public class TestOutputStream {
        public static void main(String[] args) {
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/2.txt");
            String content = "這是一個(gè) OutputStream 實(shí)例!";
            try (OutputStream outputStream = new FileOutputStream(file)) {
    //            字符串轉(zhuǎn)換為 byte 數(shù)組
                byte[] array = content.getBytes();

    //            寫入數(shù)據(jù)
                outputStream.write(array);
            } catch (IOException e) {
                e.printStackTrace();
            }

            System.out.println("寫入成功");
        }
    }

    需要注意的點(diǎn):

    • 字節(jié)流寫入數(shù)據(jù)時(shí)如何實(shí)現(xiàn)換行?

    寫入換行的轉(zhuǎn)義字符的字節(jié)數(shù)組即可,但是需要注意,不同系統(tǒng)下?lián)Q行的轉(zhuǎn)義字符不同,Windows 下為 \r\n,macOS 下為 \r,而 Linux 下為 \m。

    • 字節(jié)流寫入數(shù)據(jù)時(shí)如何實(shí)現(xiàn)追加?

    調(diào)用 public FileOutputStream(String name, boolean append) 這個(gè)構(gòu)造方法即可,當(dāng) appendtrue 時(shí),表示追加,默認(rèn)情況下是 false,表示不追加。

    字符串中的編解碼問題

    編碼

    • byte[] getBytes():使用平臺默認(rèn)字符集將該字符串編碼成一系列字節(jié),然后將結(jié)果存儲(chǔ)到新的字節(jié)數(shù)組中;
    • byte[] getBytes(String charsetName):使用指定字符集將該字符串編碼為一系列字節(jié),然后將結(jié)果存儲(chǔ)到新的字節(jié)數(shù)組中;

    解碼

    • String(byte[] bytes):使用平臺默認(rèn)字符集解碼指定的字節(jié)數(shù)來構(gòu)造新的字符串;
    • String(byte[] bytes, String charsetName):通過指定的字符集解碼指定的字節(jié)數(shù)組來構(gòu)造新的字符串;
    import java.io.UnsupportedEncodingException;
    import java.util.Arrays;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : EncodeAndDecode
     * @date : 2021/4/21 9:37
     * @description : 編碼和解碼
     */


    public class EncodeAndDecode {
        public static void main(String[] args) throws UnsupportedEncodingException {
    //        編碼
            String str = "村雨遙";
            byte[] bytes1 = str.getBytes();
            byte[] bytes2 = str.getBytes("UTF-8");
            byte[] bytes3 = str.getBytes("GBK");

            System.out.println(Arrays.toString(bytes1));
            System.out.println(Arrays.toString(bytes2));
            System.out.println(Arrays.toString(bytes3));

    //        解碼
            String res1 = new String(bytes1);
            String res2 = new String(bytes1, "UTF-8");
            String res3 = new String(bytes1, "GBK");

            System.out.println(res1);
            System.out.println(res2);
            System.out.println(res3);
        }
    }

    Writer

    Writer.png

    當(dāng)我們要寫入基于字符的數(shù)據(jù)到數(shù)據(jù)源中時(shí),需要使用寫入器 Writer. 以其中的 FileWriter 具體展開,其常用方法如下:

    返回值方法描述
    voidclose()先刷新再關(guān)閉流,不能再寫數(shù)據(jù)
    voidflush()刷新流,可以繼續(xù)寫數(shù)據(jù)
    voidnewLine()寫入行分隔符
    voidwrite()寫入字符或字符串
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : TestWriter
     * @date : 2021/4/20 18:35
     * @description : Writer 實(shí)例
     */


    public class TestWriter {
        public static void main(String[] args) {
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/2.txt");
            try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
                bufferedWriter.write("公眾號:村雨遙");
                bufferedWriter.newLine();
                bufferedWriter.write("Blog:https://cunyu1943.site");
                bufferedWriter.newLine();
                bufferedWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("寫入成功");
        }
    }

    Reader

    Reader.png

    當(dāng)我們要從數(shù)據(jù)源讀取基于字符的數(shù)據(jù)時(shí),需要使用讀取器 Reader. 我們以 FileReader 實(shí)踐,其常用的方法有:

    返回值方法描述
    voidclose()關(guān)閉流并釋放相關(guān)資源
    intread()讀取一個(gè)字符
    StringreadLine()讀一行文字
    booleanready()獲取該流是否準(zhǔn)備好被讀取

    我們以從文件中讀取內(nèi)容為例:

    import java.io.*;

    /**
     * @author : cunyu
     * @version : 1.0
     * @className : TestReader
     * @date : 2021/4/20 18:40
     * @description : Reader 實(shí)例
     */


    public class TestReader {
        public static void main(String[] args) {
            String content = null;
            File file = new File("D:/PersonalFiles/github/githubCodes/IDEA/TheWay2Java/IOStream/data/2.txt");
            System.out.println("內(nèi)容如下:");
            try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
                while ((content = bufferedReader.readLine()) != null) {
                    System.out.println(content);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    總結(jié)

    好了,關(guān)于 IO 流的知識點(diǎn)到此就結(jié)束了,趕緊學(xué)起來!如果你覺得本文對你有所幫助,那就點(diǎn)贊關(guān)注一波吧!

    對于文中遺漏或者錯(cuò)誤的知識點(diǎn),歡迎大家評論留言,咱們評論區(qū)見!



    瀏覽 58
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評論
    圖片
    表情
    推薦
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    好吊视频一区二区三区 | 黄色日韩欧美 | 亚洲无码成人精品 | 欧美日韩电影一区二区三区 | 成人 在线观看免费爱爱 |