欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

Java I/O 簡(jiǎn)介

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ū)來(lái)減少實(shí)際的 I/O 操作次數(shù),提高性能。

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

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

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

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

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

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

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

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

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

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

文件字節(jié)流:

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

文件輸入流:

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

創(chuàng)建方式

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

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

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

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

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

優(yōu)點(diǎn)

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

語(yǔ)法格式

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

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

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

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

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

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

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

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

1.直接讀取

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

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

2.循環(huán)讀取

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

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

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

3.區(qū)間讀取

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

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

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

        } catch (IOException e){ // 這里變成IOException是因?yàn)檎{(diào)用close()可能會(huì)出現(xiàn),而FileNotFoundException是繼承自IOException的
            e.printStackTrace();
        }// 無(wú)需再編寫finally語(yǔ)句塊,因?yàn)樵谧詈笞詣?dòng)幫我們調(diào)用了close()。

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

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

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

文件輸出流:

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

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

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

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

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

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

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

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

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

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

文件的拷貝:

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

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

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

// 文件拷貝+進(jìn)度條
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\\無(wú)限彈窗代碼.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ù)。使用一個(gè)緩沖區(qū)來(lái)提高拷貝效率,每次讀取一定數(shù)量的字節(jié)到緩沖區(qū),然后將緩沖區(qū)中的數(shù)據(jù)寫入目標(biāo)文件,直到讀取完源文件的所有內(nèi)容。

文件拷貝在很多場(chǎng)景中都很有用,比如:

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

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

總結(jié)

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    mybatisplus的邏輯刪除問題

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

    Java 泛型全解析

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

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

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

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

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

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

    本文主要介紹了SpringSecurity中獲取當(dāng)前登錄用戶信息的多種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(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解壓后運(yùn)行,本文分析Springboot打包成jar發(fā)布,感興趣的朋友一起看看吧
    2023-02-02

最新評(píng)論