亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java?I/O?(Input/Output)文件字節(jié)流舉例詳解

 更新時間:2024年08月23日 10:11:38   作者:誓則盟約  
Java的輸入輸出流(IO)是用于與外部設(shè)備(如文件、網(wǎng)絡(luò)連接等)進行數(shù)據(jù)交互的機制,下面這篇文章主要給大家介紹了關(guān)于Java?I/O?(Input/Output)文件字節(jié)流的相關(guān)資料,需要的朋友可以參考下

Java I/O 簡介

Java I/O(輸入/輸出)是 Java 程序中用于處理數(shù)據(jù)輸入和輸出的重要部分。

輸入流(Input Streams):用于從數(shù)據(jù)源讀取數(shù)據(jù)。常見的輸入流包括FileInputStream(從文件讀?。?、BufferedInputStream(提高讀取效率)等。

輸出流(Output Streams):用于將數(shù)據(jù)寫入到目的地。例如FileOutputStream(向文件寫入)、BufferedOutputStream(提高寫入效率)。

字符流(Reader 和 Writer):處理字符數(shù)據(jù),更適合處理文本。如FileReaderFileWriter。

緩沖流(Buffered Streams):通過緩沖區(qū)來減少實際的 I/O 操作次數(shù),提高性能。

對象流(Object Streams):用于實現(xiàn)對象的序列化和反序列化,如ObjectInputStreamObjectOutputStream。

在實際編程中,根據(jù)具體的需求選擇合適的 I/O 流可以提高程序的效率和可讀性。

計算機總線結(jié)構(gòu):   

那么為什么會有I/O呢?其實I/O無時無刻不在我們身邊,比如讀取硬盤上的文件,網(wǎng)絡(luò)文件的傳輸,鼠標(biāo)鍵盤輸入,也可以是接受單片機發(fā)回的數(shù)據(jù),而能夠支持這些操作的設(shè)備就是I/O設(shè)備。

我們可以大致看一下整個計算機的總線結(jié)構(gòu)

最核心的是CPU,CPU像計算機的大腦一樣,是計算機的核心部件,幾乎所有的計算都是靠這個CPU來進行的,CPU懂的比較多,它可以對各種類型進行計算,但是隨著時代的發(fā)展對圖形的要求越來越高,CPU就略顯乏力;于是就出現(xiàn)了GPU(顯卡),顯卡就是專門對于圖形進行計算。

通過北橋芯片連接到內(nèi)存,這樣CPU就可以對內(nèi)存進行操作;南橋芯片是用于讀取U盤或者硬盤內(nèi)的數(shù)據(jù) 。

常見的I/O設(shè)備一般是鼠標(biāo)、鍵盤這類通過USB進行傳輸?shù)耐庠O(shè)或者是通過Sata接口或是M.2連接的硬盤。一般情況下,這些設(shè)備是由CPU發(fā)出指令通過南橋芯片間接進行控制,而不是由CPU直接操作。

而我們在程序中,想要讀取這些外部連接的!O設(shè)備中的內(nèi)容,就需要將數(shù)據(jù)傳輸?shù)絻?nèi)存中。而需要實現(xiàn)這樣的操作,單單憑借一個小的程序是無法做到的,而操作系統(tǒng)(如:Windows/inux/MacOS)就是專門用于控制和管理計算機硬件和軟件資源的軟件,我們需要讀取一個IO設(shè)備的內(nèi)容時,就可以向操作系統(tǒng)發(fā)出請求,由操作系統(tǒng)幫助我們來和底層的硬件交互以完成我們的讀取/寫入請求。

JDK提供了一套用于IO操作的框架,為了方便我們開發(fā)者使用,就定義了一個像水流一樣,根據(jù)流的傳輸方向和讀取單位,分為字節(jié)流InputStream和OutputStream以及字符流Reader和Writer的IO框架,當(dāng)然,這里的流指的是數(shù)據(jù)流,通過流,我們就可以一直從流中讀取數(shù)據(jù),直到讀取到盡頭,或是不斷向其中寫入數(shù)據(jù),直到我們寫入完成,而這類IO就是我們所說的BIO。

文件字節(jié)流:

字節(jié)流一次讀取一個字節(jié),也就是一個 byte 的大小,而字符流顧名思義,就是一次讀取一個字符,也就是一個 char 的大小(在讀取純文本文件的時候更加適合)。

文件輸入流:

在 Java 中,文件輸入流(FileInputStream)用于從文件中讀取數(shù)據(jù)。FileInputStream 允許程序以字節(jié)為單位讀取文件的內(nèi)容。

創(chuàng)建方式

通常通過指定要讀取的文件路徑來創(chuàng)建文件輸入流對象。例如:

try {
    FileInputStream fis = new FileInputStream("your_file_path");
    // 后續(xù)的讀取操作
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

但是這種方式需要處理各種可能的異常,比如 FileNotFoundException 異常和 IOException 異常,并且需要手動關(guān)閉文件,完整代碼如下:

public class Hello_World {
    public static void main(String[] args) { // 想讀取一個文件  創(chuàng)建一個文件輸入流   使用完把流關(guān)閉掉 釋放掉 close
        FileInputStream stream = null;
        try {
            stream = new FileInputStream("絕對路徑/相對路徑");
//            stream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

僅僅是取得文件就如此費勁,不合乎常理。所以有了try-with-resources 語句這種簡便方式,try-with-resources 語句是一種用于更方便、更安全地管理資源(如輸入流、輸出流、數(shù)據(jù)庫連接等)的機制。

優(yōu)點

  • 自動資源管理:無需顯式地調(diào)用 close 方法來關(guān)閉資源,避免了因忘記關(guān)閉資源而導(dǎo)致的資源泄漏問題。
  • 簡潔的代碼:減少了樣板代碼,使代碼更簡潔、更易讀。

語法格式

try (Resource res = new Resource()) {
    // 使用資源的操作
} catch (Exception e) {
    // 異常處理
}

對于以上示例的完整代碼轉(zhuǎn)成try-with-resources 語句如下:

public class Hello_World {
    public static void main(String[] args) {
        try(FileInputStream inputStream = new FileInputStream("路徑")){ // 直接在try()中定義要在完成之后釋放的資源
        } catch (IOException e){ // 這里變成IOException是因為調(diào)用close()可能會出現(xiàn),而FileNotFoundException是繼承自IOException的
            e.printStackTrace();
        }// 無需再編寫finally語句塊,因為在最后自動幫我們調(diào)用了close()。
    }
}

由此可見,try-with-resources 語句極大地提高了資源管理的便利性和可靠性,使代碼更加健壯和易于維護。

數(shù)據(jù)的傳遞:

如圖所示,在計算機數(shù)據(jù)由文件向內(nèi)存進行傳遞的形式是以二進制01串進行的,一次一個字節(jié),就像水流一樣源源不斷的傳輸,直至文件傳輸結(jié)束。

數(shù)據(jù)不斷傳輸過來,那我們?nèi)绾稳プx取數(shù)據(jù)呢?

調(diào)用read()方法是必要的,但是read()方法的調(diào)用方式也有很多種,這里主要列出來常見的三種。

1.直接讀取

       try(FileInputStream inputStream = new FileInputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt")){ // 直接在try()中定義要在完成之后釋放的資源
            int i = inputStream.read();
            System.out.println((char)i);
            int x = inputStream.read();  // 當(dāng)沒有內(nèi)容后,會返回-1
            System.out.println((char)x);
      } catch (IOException e){ // 這里變成IOException是因為調(diào)用close()可能會出現(xiàn),而FileNotFoundException是繼承自IOException的
            e.printStackTrace();
        }// 無需再編寫finally語句塊,因為在最后自動幫我們調(diào)用了close()。
    

由于讀取數(shù)據(jù)返回的是int類型的一個數(shù)據(jù),所以我們用int i 去接收它,然后利用強制類型轉(zhuǎn)換把i 轉(zhuǎn)為char類型進行輸出。調(diào)用一次讀取一個字符,當(dāng)讀取完之后會返回-1.這樣效率較為低下,所以有下面第二種讀取方法。

2.循環(huán)讀取

由于讀取完之后會返回數(shù)字-1,所以可以利用這一性質(zhì)進行while循環(huán)進行讀取,直到返回-1時結(jié)束循環(huán),代碼如下:

try(FileInputStream inputStream = new FileInputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt")){ // 直接在try()中定義要在完成之后釋放的資源
            int i;
            while ((i = inputStream.read()) != -1) {
                System.out.print((char)i);
            }
        } catch (IOException e){ // 這里變成IOException是因為調(diào)用close()可能會出現(xiàn),而FileNotFoundException是繼承自IOException的
            e.printStackTrace();
}// 無需再編寫finally語句塊,因為在最后自動幫我們調(diào)用了close()。
    

通過這種方式就可以一次性對文件內(nèi)的內(nèi)容全部讀取。但是由于不夠靈活,可變性較差,所以還可以用下面第三種方法進行讀取。

3.區(qū)間讀取

區(qū)間讀取,顧名思義就是定義一個固定長度的區(qū)間,將文件內(nèi)的內(nèi)容按照這個區(qū)間大小進行讀取,當(dāng)文件未讀內(nèi)容小于區(qū)間長度時會以小于區(qū)間長度的形式進行最后一次讀取,若沒有元素可讀取時,一樣會返回-1。具體代碼如下:

        try(FileInputStream inputStream = new FileInputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt")){ // 直接在try()中定義要在完成之后釋放的資源

            System.out.println(inputStream.available()); // 獲取有多少個數(shù)據(jù)可讀
            byte [] bytes = new byte[inputStream.available()]; // 一次讀x個數(shù)據(jù)
            while (inputStream.read(bytes) != -1)   // 當(dāng)最后不足x個或者已經(jīng)沒有時,會返回少于x個的數(shù)據(jù)或者-1
                System.out.println(new String(bytes));

        } catch (IOException e){ // 這里變成IOException是因為調(diào)用close()可能會出現(xiàn),而FileNotFoundException是繼承自IOException的
            e.printStackTrace();
        }// 無需再編寫finally語句塊,因為在最后自動幫我們調(diào)用了close()。

讀取過程中可使用available()方法查詢可讀數(shù)量,在上面的案例中,我將區(qū)間長度x設(shè)置為了可讀長度,這樣也可以一次性讀取完文件內(nèi)數(shù)據(jù)。也可以設(shè)置其他int類型的x作為長度參數(shù)。

這種方法在文件輸出流常用,一個字節(jié)一個字節(jié)的讀取出來并一個字節(jié)一個字節(jié)的寫入另一個文件,相當(dāng)于文件的拷貝操作。

跳過操作:skip()方法。給skip(x)傳人參數(shù)x,可以設(shè)置跳過前幾個字節(jié)進行讀取其下一個字節(jié)。

文件輸出流:

文件輸出流(FileOutputStream)用于將數(shù)據(jù)寫入到文件中。文件輸出流允許您以字節(jié)為單位向文件寫入數(shù)據(jù)。

在寫入之前您需要提供要寫入的文件的路徑和名稱。如果文件不存在,它將被創(chuàng)建;如果文件已存在,默認(rèn)情況下,新寫入的數(shù)據(jù)會覆蓋原有的內(nèi)容。

   try {
       FileOutputStream fos = new FileOutputStream("your_file.txt");
   } catch (IOException e) {
       e.printStackTrace();
   }

stream.flush()方法的主要作用是將輸出流緩沖區(qū)中的數(shù)據(jù)強制刷新并輸出。通常,當(dāng)我們使用輸出流(如 FileOutputStream 、BufferedOutputStream 等)寫入數(shù)據(jù)時,數(shù)據(jù)并不是立即被發(fā)送到目的地(如文件),而是先被存儲在緩沖區(qū)中。緩沖區(qū)的目的是減少實際的 I/O 操作次數(shù),從而提高性能。

然而,在某些情況下,我們希望確保數(shù)據(jù)能夠立即被發(fā)送出去,而不是等到緩沖區(qū)填滿或者輸出流被關(guān)閉。這時就可以使用 flush 方法。  

默認(rèn)情況下(append的參數(shù)默認(rèn)是false),寫入的內(nèi)容會直接取代原文件內(nèi)的內(nèi)容,即覆蓋掉。代碼如下:

public class Hello_World {
    public static void main(String[] args) {
        try(FileOutputStream stream = new FileOutputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt")){
            stream.write("Hello World".getBytes());  // 直接取代原內(nèi)容
            stream.flush();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

如果想接著文件的內(nèi)容往后繼續(xù)寫(追加模式),那么只需要把append的參數(shù)改為true即可,代碼如下:

public class Hello_World {
    public static void main(String[] args) {
        try(FileOutputStream stream = new FileOutputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt",true)){ // 加上true 變成追加模式
            stream.write("Hello World".getBytes());  // 直接取代原內(nèi)容
            stream.flush();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

至此,我們就完成了輸出流操作,那么,就可以結(jié)合輸入流和輸出流進行拷貝操作了。

文件的拷貝:

文件拷貝是將一個文件的內(nèi)容完整地復(fù)制到另一個文件的操作。相關(guān)的類有:

   import java.io.FileInputStream;
   import java.io.FileOutputStream;
   import java.io.IOException;

文件的拷貝操作一般使用讀取數(shù)據(jù)的第三種方法,區(qū)間讀取。因為這種方法可以設(shè)置足夠大的區(qū)間,讀取速度較快,不需要一個字節(jié)一個字節(jié)的去讀取。下面是兩個拷貝的示例代碼:

// 文件拷貝+進度條
public class Hello_World {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\Xxy63\\Desktop\\文章.md");
        try(FileInputStream in = new FileInputStream(file);
        FileOutputStream out = new FileOutputStream("XXX.txt")){
            byte [] bytes = new byte[400];
            int len;
            long total = file.length() , sum = 0;
            while ((len = in.read(bytes))!=-1){
                out.write(bytes, 0, len);
                sum += len;
                System.out.println("文件已拷貝" + (sum*100/total) + '%');
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
public class Hello_World {
    public static void main(String[] args) {
        try(FileInputStream in = new FileInputStream("C:\\Users\\Xxy63\\Desktop\\無限彈窗代碼.txt");
            FileOutputStream out = new FileOutputStream("C:\\Users\\Xxy63\\Desktop\\copy.txt")){
            byte[] bytes = new byte[1024];
            int len;
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            } // 拷貝速度大大提升
        }catch (IOException  e){
            e.printStackTrace();
        }
    }
}

在上述代碼中,通過創(chuàng)建輸入流 FileInputStream 從源文件讀取數(shù)據(jù),創(chuàng)建輸出流 FileOutputStream 向目標(biāo)文件寫入數(shù)據(jù)。使用一個緩沖區(qū)來提高拷貝效率,每次讀取一定數(shù)量的字節(jié)到緩沖區(qū),然后將緩沖區(qū)中的數(shù)據(jù)寫入目標(biāo)文件,直到讀取完源文件的所有內(nèi)容。

文件拷貝在很多場景中都很有用,比如:

  • 數(shù)據(jù)備份:將重要文件復(fù)制一份以防止數(shù)據(jù)丟失。
  • 共享文件:將文件拷貝到多個位置以便不同的程序或用戶使用。

例如,如果您有一個包含重要配置信息的文件,為了安全起見,可以定期進行備份拷貝。又或者在一個文件處理系統(tǒng)中,需要將原始文件拷貝到多個不同的目錄下以供不同的模塊處理。

總結(jié)

到此這篇關(guān)于Java I/O (Input/Output)文件字節(jié)流的文章就介紹到這了,更多相關(guān)Java I/O文件字節(jié)流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Security認(rèn)證的完整流程記錄

    Spring?Security認(rèn)證的完整流程記錄

    相信大伙對Spring Security這個框架又愛又恨,愛它的強大,恨它的繁瑣,下面這篇文章主要給大家介紹了關(guān)于Spring?Security認(rèn)證流程的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • springboot+dynamicDataSource動態(tài)添加切換數(shù)據(jù)源方式

    springboot+dynamicDataSource動態(tài)添加切換數(shù)據(jù)源方式

    這篇文章主要介紹了springboot+dynamicDataSource動態(tài)添加切換數(shù)據(jù)源方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 使用PageHelper插件實現(xiàn)Service層分頁

    使用PageHelper插件實現(xiàn)Service層分頁

    這篇文章主要為大家詳細(xì)介紹了使用PageHelper插件實現(xiàn)Service層分頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java?空和null的區(qū)別

    Java?空和null的區(qū)別

    本文主要介紹了Java?空和null的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • mybatisplus的邏輯刪除問題

    mybatisplus的邏輯刪除問題

    這篇文章主要介紹了mybatisplus的邏輯刪除問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java 泛型全解析

    Java 泛型全解析

    這篇文章主要介紹了Java 泛型的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-08-08
  • Java中靜態(tài)類型檢查是如何進行的實例思路詳解

    Java中靜態(tài)類型檢查是如何進行的實例思路詳解

    這篇文章主要介紹了Java中靜態(tài)類型檢查是如何進行的實例思路詳解的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • java管道piped輸入流與輸出流應(yīng)用場景案例分析

    java管道piped輸入流與輸出流應(yīng)用場景案例分析

    這篇文章主要介紹了java管道流PipedInputStream與PipedOutputStream(輸入流與輸出流)的應(yīng)用場景案例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • SpringSecurity獲取當(dāng)前登錄用戶的信息的幾種方法實現(xiàn)

    SpringSecurity獲取當(dāng)前登錄用戶的信息的幾種方法實現(xiàn)

    本文主要介紹了SpringSecurity中獲取當(dāng)前登錄用戶信息的多種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Springboot打包成jar發(fā)布的操作方法

    Springboot打包成jar發(fā)布的操作方法

    打包的方式有打包成jar包或者打包成war包發(fā)布,區(qū)別在于jar包內(nèi)置了tomcat、netty等服務(wù)器,更改只需要修改pom.xml的坐標(biāo)即可,war不內(nèi)置服務(wù)器,需要上傳到服務(wù)器tomcat解壓后運行,本文分析Springboot打包成jar發(fā)布,感興趣的朋友一起看看吧
    2023-02-02

最新評論