文件寫入的方法有哪些

這篇文章主要講解了“文件寫入的方法有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“文件寫入的方法有哪些”吧!

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),清徐企業(yè)網(wǎng)站建設(shè),清徐品牌網(wǎng)站建設(shè),網(wǎng)站定制,清徐網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,清徐網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

0.什么是流?

Java 中的“流”是一種抽象的概念,也是一種比喻,就好比水流一樣,水流是從一端流向另一端的,而在 Java  中的“水流”就是數(shù)據(jù),數(shù)據(jù)會從一端“流向”另一端。

根據(jù)流的方向性,我們可以將流分為輸入流和輸出流,當(dāng)程序需要從數(shù)據(jù)源中讀入數(shù)據(jù)的時候就會開啟一個輸入流,相反,寫出數(shù)據(jù)到某個數(shù)據(jù)源目的地的時候也會開啟一個輸出流,數(shù)據(jù)源可以是文件、內(nèi)存或者網(wǎng)絡(luò)等。

1.什么是字節(jié)流?

字節(jié)流的基本單位為字節(jié)(Byte),一個字節(jié)通常為 8 位,它是用來處理二進(jìn)制(數(shù)據(jù))的。字節(jié)流有兩個基類:InputStream(輸入字節(jié)流)和  OutputStream(輸出字節(jié)流)。

常用字節(jié)流的繼承關(guān)系圖如下圖所示:

文件寫入的方法有哪些

其中 InputStream 用于讀操作,而  OutputStream 用于寫操作。

2.什么是字符流?

字符流的基本單位為 Unicode,大小為兩個字節(jié)(Byte),它通常用來處理文本數(shù)據(jù)。字符流的兩個基類:Reader(輸入字符流)和  Writer(輸出字符流)。

常用字符流的繼承關(guān)系圖如下圖所示:

文件寫入的方法有哪些

3.流的分類

流可以根據(jù)不同的維度進(jìn)行分類,比如可以根據(jù)流的方向進(jìn)行分類,也可以根據(jù)傳輸?shù)膯挝贿M(jìn)行分類,還可以根據(jù)流的功能進(jìn)行分類,比如以下幾個。

① 按流向分類

  • 輸出流:OutputStream 和 Writer 為基類。

  • 輸入流:InputStream 和 Reader 為基類。

② 根據(jù)傳輸數(shù)據(jù)單位分類

  • 字節(jié)流:OutputStream 和 InputStream 為基類。

  • 字符流:Writer 和 Reader 為基類。

③ 根據(jù)功能分類

  • 字節(jié)流:可以從或向一個特定的地方(節(jié)點)讀寫數(shù)據(jù)。

  • 處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調(diào)用實現(xiàn)數(shù)據(jù)讀寫。

PS:我們通常是以傳輸數(shù)據(jù)的單位來為流進(jìn)行分類。

4.寫文件的6種方法

寫入文件的方法主要源于字符流 Writer 和輸出字節(jié)流 OutputStream 的子類,如下圖所示:

文件寫入的方法有哪些

以上標(biāo)注?號的類就是用來實現(xiàn)文件寫入的類,除此之外,在 JDK 1.7 中還提供了 Files  類用來實現(xiàn)對文件的各種操作,接下來我們分別來看。

方法 1:FileWriter

FileWriter 屬于「字符流」體系中的一員,也是文件寫入的基礎(chǔ)類,它包含 5  個構(gòu)造函數(shù),可以傳遞一個具體的文件位置,或者 File 對象,第二參數(shù)表示是否要追加文件,默認(rèn)值為 false  表示重寫文件內(nèi)容,而非追加文件內(nèi)容(關(guān)于如何追加文件,我們后面會講)。

文件寫入的方法有哪些

FileWriter 類的實現(xiàn)如下:

/**   * 方法 1:使用 FileWriter 寫文件   * @param filepath 文件目錄   * @param content  待寫入內(nèi)容   * @throws IOException   */ public static void fileWriterMethod(String filepath, String content) throws IOException {     try (FileWriter fileWriter = new FileWriter(filepath)) {         fileWriter.append(content);     } }

只需要傳入具體的文件路徑和待寫入的內(nèi)容即可,調(diào)用代碼如下:

public static void main(String[] args) {     fileWriterMethod("/Users/mac/Downloads/io_test/write1.txt", "哈嘍,Java中文社群."); }

然后我們打開寫入的文件,實現(xiàn)結(jié)果如下:

文件寫入的方法有哪些
  • 關(guān)于資源釋放的問題:在 JDK 7 以上的版本,我們只需要使用 try-with-resource 的方式就可以實現(xiàn)資源的釋放,就比如使用 try  (FileWriter fileWriter = new FileWriter(filepath)) {...} 就可以實現(xiàn) FileWriter  資源的自動釋放。

方法 2:BufferedWriter

BufferedWriter 也屬于字符流體系的一員,與 FileWriter 不同的是  BufferedWriter自帶緩沖區(qū),因此它寫入文件的性能更高(下文會對二者進(jìn)行測試)。

小知識點:緩沖區(qū)

緩沖區(qū)又稱為緩存,它是內(nèi)存空間的一部分。也就是說,在內(nèi)存空間中預(yù)留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數(shù)據(jù),這部分預(yù)留的空間就叫做緩沖區(qū)。

緩沖區(qū)的優(yōu)勢

以文件流的寫入為例,如果我們不使用緩沖區(qū),那么每次寫操作 CPU  都會和低速存儲設(shè)備也就是磁盤進(jìn)行交互,那么整個寫入文件的速度就會受制于低速的存儲設(shè)備(磁盤)。但如果使用緩沖區(qū)的話,每次寫操作會先將數(shù)據(jù)保存在高速緩沖區(qū)內(nèi)存上,當(dāng)緩沖區(qū)的數(shù)據(jù)到達(dá)某個閾值之后,再將文件一次性寫入到磁盤上。因為內(nèi)存的寫入速度遠(yuǎn)遠(yuǎn)大于磁盤的寫入速度,所以當(dāng)有了緩沖區(qū)之后,文件的寫入速度就被大大提升了。

了解了緩存區(qū)的優(yōu)點之后,咱們回到本文的主題,接下來我們用 BufferedWriter 來文件的寫入,實現(xiàn)代碼如下:

/**  * 方法 2:使用 BufferedWriter 寫文件  * @param filepath 文件目錄  * @param content  待寫入內(nèi)容  * @throws IOException  */ public static void bufferedWriterMethod(String filepath, String content) throws IOException {     try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath))) {         bufferedWriter.write(content);     } }

調(diào)用代碼和方法 1 類似,這里就不再贅述了。

方法 3:PrintWriter

PrintWriter  也屬于字符流體系中的一員,它雖然叫“字符打印流”,但使用它也可以實現(xiàn)文件的寫入,實現(xiàn)代碼如下:

/**  * 方法 3:使用 PrintWriter 寫文件  * @param filepath 文件目錄  * @param content  待寫入內(nèi)容  * @throws IOException  */ public static void printWriterMethod(String filepath, String content) throws IOException {     try (PrintWriter printWriter = new PrintWriter(new FileWriter(filepath))) {         printWriter.print(content);     } }

從上述代碼可以看出,無論是 PrintWriter 還是 BufferedWriter 都必須基于 FileWriter 類來完成調(diào)用。

方法 4:FileOutputStream

上面 3 個示例是關(guān)于字符流寫入文件的一些操作,而接下來我們將使用字節(jié)流來完成文件寫入。我們將使用 String  自帶的 getBytes() 方法先將字符串轉(zhuǎn)換成二進(jìn)制文件,然后再進(jìn)行文件寫入,它的實現(xiàn)代碼如下:

/**  * 方法 4:使用 FileOutputStream 寫文件  * @param filepath 文件目錄  * @param content  待寫入內(nèi)容  * @throws IOException  */ public static void fileOutputStreamMethod(String filepath, String content) throws IOException {     try (FileOutputStream fileOutputStream = new FileOutputStream(filepath)) {         byte[] bytes = content.getBytes();         fileOutputStream.write(bytes);     } }

方法 5:BufferedOutputStream

BufferedOutputStream 屬于字節(jié)流體系中的一員,與 FileOutputStream  不同的是,它自帶了緩沖區(qū)的功能,因此性能更好,它的實現(xiàn)代碼如下:

/**  * 方法 5:使用 BufferedOutputStream 寫文件  * @param filepath 文件目錄  * @param content  待寫入內(nèi)容  * @throws IOException  */ public static void bufferedOutputStreamMethod(String filepath, String content) throws IOException {     try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(             new FileOutputStream(filepath))) {         bufferedOutputStream.write(content.getBytes());     } }

方法 6:Files

接下來的操作方法和之前的代碼都不同,接下來咱們就使用 JDK 7 中提供的一個新的文件操作類 Files 來實現(xiàn)文件的寫入。

Files 類是 JDK 7  添加的新的操作文件的類,它提供了提供了大量處理文件的方法,例如文件復(fù)制、讀取、寫入,獲取文件屬性、快捷遍歷文件目錄等,這些方法極大的方便了文件的操作,它的實現(xiàn)代碼如下:

/**  * 方法 6:使用 Files 寫文件  * @param filepath 文件目錄  * @param content  待寫入內(nèi)容  * @throws IOException  */ public static void filesTest(String filepath, String content) throws IOException {     Files.write(Paths.get(filepath), content.getBytes()); }

以上這些方法都可以實現(xiàn)文件的寫入,那哪一種方法性能更高呢?接下來我們來測試一下。

5.性能測試

我們先來構(gòu)建一個比較大的字符串,然后分別用以上 6 種方法來測試文件寫入的速度,最后再把結(jié)果打印出來,測試代碼如下:

import java.io.*; import java.nio.file.Files; import java.nio.file.Paths;  public class WriteExample {     public static void main(String[] args) throws IOException {         // 構(gòu)建寫入內(nèi)容         StringBuilder stringBuilder = new StringBuilder();         for (int i = 0; i < 1000000; i++) {             stringBuilder.append("ABCDEFGHIGKLMNOPQRSEUVWXYZ");         }         // 寫入內(nèi)容         final String content = stringBuilder.toString();         // 存放文件的目錄         final String filepath2 = "/Users/mac/Downloads/io_test/write1.txt";         final String filepath3 = "/Users/mac/Downloads/io_test/write2.txt";         final String filepath4 = "/Users/mac/Downloads/io_test/write3.txt";         final String filepath5 = "/Users/mac/Downloads/io_test/write4.txt";         final String filepath6 = "/Users/mac/Downloads/io_test/write5.txt";         final String filepath7 = "/Users/mac/Downloads/io_test/write6.txt";          // 方法一:使用 FileWriter 寫文件         long stime1 = System.currentTimeMillis();         fileWriterTest(filepath2, content);         long etime1 = System.currentTimeMillis();         System.out.println("FileWriter 寫入用時:" + (etime1 - stime1));          // 方法二:使用 BufferedWriter 寫文件         long stime2 = System.currentTimeMillis();         bufferedWriterTest(filepath3, content);         long etime2 = System.currentTimeMillis();         System.out.println("BufferedWriter 寫入用時:" + (etime2 - stime2));          // 方法三:使用 PrintWriter 寫文件         long stime3 = System.currentTimeMillis();         printWriterTest(filepath4, content);         long etime3 = System.currentTimeMillis();         System.out.println("PrintWriterTest 寫入用時:" + (etime3 - stime3));          // 方法四:使用 FileOutputStream  寫文件         long stime4 = System.currentTimeMillis();         fileOutputStreamTest(filepath5, content);         long etime4 = System.currentTimeMillis();         System.out.println("FileOutputStream 寫入用時:" + (etime4 - stime4));          // 方法五:使用 BufferedOutputStream 寫文件         long stime5 = System.currentTimeMillis();         bufferedOutputStreamTest(filepath6, content);         long etime5 = System.currentTimeMillis();         System.out.println("BufferedOutputStream 寫入用時:" + (etime5 - stime5));          // 方法六:使用 Files 寫文件         long stime6 = System.currentTimeMillis();         filesTest(filepath7, content);         long etime6 = System.currentTimeMillis();         System.out.println("Files 寫入用時:" + (etime6 - stime6));      }      /**      * 方法六:使用 Files 寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void filesTest(String filepath, String content) throws IOException {         Files.write(Paths.get(filepath), content.getBytes());     }      /**      * 方法五:使用 BufferedOutputStream 寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void bufferedOutputStreamTest(String filepath, String content) throws IOException {         try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(                 new FileOutputStream(filepath))) {             bufferedOutputStream.write(content.getBytes());         }     }      /**      * 方法四:使用 FileOutputStream  寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void fileOutputStreamTest(String filepath, String content) throws IOException {         try (FileOutputStream fileOutputStream = new FileOutputStream(filepath)) {             byte[] bytes = content.getBytes();             fileOutputStream.write(bytes);         }     }      /**      * 方法三:使用 PrintWriter 寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void printWriterTest(String filepath, String content) throws IOException {         try (PrintWriter printWriter = new PrintWriter(new FileWriter(filepath))) {             printWriter.print(content);         }     }      /**      * 方法二:使用 BufferedWriter 寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void bufferedWriterTest(String filepath, String content) throws IOException {         try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath))) {             bufferedWriter.write(content);         }     }      /**      * 方法一:使用 FileWriter 寫文件      * @param filepath 文件目錄      * @param content  待寫入內(nèi)容      * @throws IOException      */     private static void fileWriterTest(String filepath, String content) throws IOException {         try (FileWriter fileWriter = new FileWriter(filepath)) {             fileWriter.append(content);         }     } }

在查看結(jié)果之前,我們先去對應(yīng)的文件夾看看寫入的文件是否正常,如下圖所示:

文件寫入的方法有哪些

從上述結(jié)果可以看出,每種方法都正常寫入了 26  MB 的數(shù)據(jù),它們最終執(zhí)行的結(jié)果如下圖所示:

文件寫入的方法有哪些

從以上結(jié)果可以看出,字符流的操作速度最快,這是因為我們本次測試的代碼操作的是字符串,所以在使用字節(jié)流時,需要先將字符串轉(zhuǎn)換為字節(jié)流,因此在執(zhí)行效率上不占優(yōu)勢。

從上述結(jié)果可以看出,性能最好的是帶有緩沖區(qū)的字符串寫入流 BufferedWriter,性能最慢的是 Files。

PS:以上的測試結(jié)果只是針對字符串的操作場景有效,如果操作的是二進(jìn)制的文件,那么就應(yīng)該使用帶緩沖區(qū)的字節(jié)流  BufferedOutputStream。

6.擴展知識:內(nèi)容追加

以上代碼會對文件進(jìn)行重寫,如果只想在原有的基礎(chǔ)上追加內(nèi)容,就需要在創(chuàng)建寫入流的時候多設(shè)置一個 append 的參數(shù)為 true,比如如果我們使用  FileWriter 來實現(xiàn)文件的追加的話,實現(xiàn)代碼是這樣的:

public static void fileWriterMethod(String filepath, String content) throws IOException {     // 第二個 append 的參數(shù)傳遞一個 true = 追加文件的意思     try (FileWriter fileWriter = new FileWriter(filepath, true)) {         fileWriter.append(content);     } }

如果使用的是 BufferedWriter 或 PrintWriter,也是需要在構(gòu)建 new FileWriter 類時多設(shè)置一個 append  的參數(shù)為 true,實現(xiàn)代碼如下:

try (BufferedWriter bufferedWriter = new BufferedWriter(     new FileWriter(filepath, true))) {     bufferedWriter.write(content); }

相比來說 Files 類要想實現(xiàn)文件的追加寫法更加特殊一些,它需要在調(diào)用 write 方法時多傳一個 StandardOpenOption.APPEND  的參數(shù),它的實現(xiàn)代碼如下:

Files.write(Paths.get(filepath), content.getBytes(), StandardOpenOption.APPEND);

感謝各位的閱讀,以上就是“文件寫入的方法有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對文件寫入的方法有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

網(wǎng)站題目:文件寫入的方法有哪些
標(biāo)題網(wǎng)址:http://muchs.cn/article4/jcppie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計、網(wǎng)站策劃、定制網(wǎng)站微信公眾號、電子商務(wù)品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)