Java的文件IO編程

IO問題是任何編程語言都無法回避的幌墓,可以說但壮,IO問題是整個人機交互的核心問題。在Java中常侣,提供了包名為java.io的專門操作類庫蜡饵。
在這個包下提供了將近有80個類,這些類大致分為四組:

  • 基于字節(jié)操作的InputStreamOutputStream袭祟。
  • 基于字符操作的IO接口: WriterReader
  • 基于磁盤操作的IO接口: File
  • 基于網(wǎng)絡操作的IO接口:Socket

要學好Java的文件IO操作捞附,重點需要掌握:

  • 2個代碼模型
  • 5個類
    • File
    • OutputStream
    • InputStream
    • Reader
    • Writer
  • 1個接口(Serializable)

1. File類的基本使用

這個類的使用直接產(chǎn)生實例化對象即可巾乳。

1.1 File類實例化對象

如果要實例化對象,需要用到兩個構(gòu)造方法鸟召。

  1. public File(String pathName)
  2. public File(File parent,String child)胆绊,設置父路徑和子文件

1.2 File類操作文件

如果要進行文件的操作,可以使用下列方法:

  • createNewfile: 根據(jù)制訂的路徑創(chuàng)建新文件
  • exists(); 判斷文件是否存在
  • file.delete(); 刪除文件

實例: 判斷文件是否存在欧募,存在的話就刪除压状,不存在的話就創(chuàng)建

public class FileDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\hello.txt");   // 定義要操作的文件路徑
        if (file.exists()) {   // 判斷文件是否存在
            System.out.println("文件已經(jīng)存在,已經(jīng)將其刪除");
            file.delete();   //刪除文件
        } else {
            System.out.println("不存在文件,已經(jīng)創(chuàng)建了一個新的种冬!");
            file.createNewFile();   //創(chuàng)建一個空文件
        }
    }
}

說明镣丑,如果此處操作的都是根路徑,如果是含有子路徑的話娱两,如果路徑不存在莺匠,是不會自動創(chuàng)建路徑的,會報錯

File類基本操作

注意:路徑分隔符
由于不同的操作系統(tǒng)對路徑分隔符是不同的十兢,因此趣竣,使用路徑的時候,需要將上述指定操作文件的位置修改為如下:
File file = new File("D:"+File.separator+"hello.txt"); // 定義要操作的文件路徑

1.3 File類操作目錄

有以下常用的方法操作目錄

  • 獲得父目錄的方法1: getParentFile()旱物,該方法返回的是File類型的值(推薦使用)
  • 獲取父目錄的方法2: getParent()遥缕,該方法返回的是String類型的值
  • 創(chuàng)建父目錄,就對獲取的父目錄的返回對象執(zhí)行: file.getParentFile().mkdirs()宵呛,該方法如果有多層路徑单匣,都可以自動創(chuàng)建。
public class FileDemo {
    public static void main(String[] args) throws IOException {
     /**
         * 對路徑的操作
         * */
        File file = new File("D:"+File.separator+"hello"+File.separator+"hello.txt");   // 定義要操作的文件路徑
        if(!file.getParentFile().exists()){  // 判斷父目錄是否存在
            System.out.println(file.getParentFile().toString());
            file.getParentFile().mkdirs();   // 默認創(chuàng)建多級父目錄
        }
        file.createNewFile();
    }
}

1.4 File類取得文件信息

File類提供很多取得文件信息的方法烤蜕。方法有很多封孙,使用方式也都類似,直接通過一個例子記錄一下吧讽营。

范例

class MyMath {
    // 保留幾位小數(shù)
    public static double round(double num, int scale) {
        return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale);
    }
}

public class FileInfoDemo {
    public static void main(String[] args) {
        File file = new File("D:\\4. 暫存待整理\\截圖\\Screenshot_2016-07-17-11-21-27.png");   // 定義要操作的文件路徑
        if (file.exists() && file.isFile()) {  // 文件存在且是文件
            System.out.println("文件大谢⒓伞:" + MyMath.round((file.length()) / 1024, 2));   // 文件大小為字節(jié)數(shù),太大了橱鹏,僅保留2位小數(shù)
            System.out.println("上次修改時間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date(file.lastModified())));
        }
    }
}

2. 字節(jié)流與字符流

File類本質(zhì)上不操作文件的內(nèi)容膜蠢,要進行文件內(nèi)容的處理,就需要用到字節(jié)流和字符流的概念莉兰。
字節(jié)流和字符流的區(qū)別是什么挑围?

  1. 字節(jié)流是指文件作為數(shù)據(jù)的二進制傳輸形式,而字符流則是在內(nèi)存中進行操作的對象的感覺糖荒。這么理解不太嚴密杉辙,但是可以簡單認為,字符流更靠近文件捶朵。
  2. 字節(jié)流更多的是文件在磁盤上的保存蜘矢,網(wǎng)絡的數(shù)據(jù)傳輸形式等。
  3. 字符更適合處理中文

不管是字節(jié)流還是字符流综看,其處理文件內(nèi)容的基本步驟都是如下的思路:

  • 要根據(jù)文件的路徑創(chuàng)建File類的對象
  • 根據(jù)字節(jié)流或者字符流的子類實例化父類對象
  • 進行數(shù)據(jù)的讀取或者寫入操作
  • 關(guān)閉流:IO操作屬于資源操作品腹,所有的資源操作都必須執(zhí)行關(guān)閉操作。

2.1 字節(jié)輸出流OutputStream

如果要通過程序進行內(nèi)容的輸出红碑,則可以使用字節(jié)輸出流OutputStream舞吭。

OutputStream的繼承關(guān)系

OutputStream是一個抽象類,實現(xiàn)了Closeable接口和Flushable接口,通過這兩個接口羡鸥,繼承了他們各自的關(guān)閉方法和刷新方法蔑穴。同樣的,由于他是一個抽象類兄春,必須使用它的子類進行實例化澎剥,那么就會需要針對不同的操作,實現(xiàn)不同的子類實例化赶舆。對于文件的操作哑姚,使用FileOutputStream進行實例化。 FileOutputStream擁有不同的構(gòu)造函數(shù)芜茵,根據(jù)構(gòu)造函數(shù)的不同叙量,可以進行文件的覆蓋寫入和文件的追加寫入設置等。

FileOutputStream的不同構(gòu)造方法

  • 覆蓋寫入: FileOutputStream(File file)
  • 追加寫入:+ 覆蓋寫入: FileOutputStream(File file,boolean append)

FileOutputStream的寫入方法

  • 全部寫入: write(byte[] content)
  • 局部寫入: write(byte[] content,int start, int len)
  • 寫入單個字節(jié): write(int content)

范例:使用FileOutputStream進行文件內(nèi)容的寫入/追加等九串。

/** 文件內(nèi)容的寫入操作范例 */
public class OutputStreamDemo {
  public static void main(String[] args) throws IOException {
    // 1. 確定要操作的文件
    File file = new File("D:\\filewrite.txt");
    // 2. 實例化一個文件類型的OutputStream
    OutputStream os = new FileOutputStream(file); // 覆寫
    //      OutputStream os = new FileOutputStream(file, true);   // 追加

    // 3. 寫入文件
    // 3.1 全部寫入
    String content = "this is a test String!\r\n";
    os.write(content.getBytes());

    // 3.2 部分寫入
    os.write(content.getBytes(), 0, 9);

    // 3.3 寫入單個字節(jié)
    os.write(65);

    // 4. 關(guān)閉流
    os.close();
  }
}

說明:

  1. 使用FileOutputStream進行文件操作的時候绞佩,就不在需要進行文件的創(chuàng)建,調(diào)用寫入的方法時猪钮,會進行自動的創(chuàng)建品山。(只創(chuàng)建文件,如果有多級烤低,那么目錄一定要確保是存在的)
  2. 一定要記得關(guān)閉文件字節(jié)流肘交。

2.2 字節(jié)輸入流InputStream

InputStream是字節(jié)輸入流,其使用方法和OutputStream類幾乎一樣扑馁。
原理是通過read方法將流對象中的數(shù)據(jù)讀入的byte數(shù)組中涯呻,之后通過操作數(shù)組實現(xiàn)讀取到的內(nèi)容的操作。

import java.io.*;

public class InputStreamDemo {
  public static void main(String[] args) throws IOException {
    // 1. 定位到要處理的文件
    File file = new File("D:\\ProgramFiles\\kibana-5.6.2-windows-x86\\LICENSE.txt");

    // 2. 使用FileInputStream類實例化InputStream對象
    InputStream input = new FileInputStream(file);

    // 3. 讀取流的內(nèi)容到字節(jié)數(shù)組中
    byte[] content = new byte[1024];
    int len = input.read(content);
    
    System.out.println("讀取文件內(nèi)容為:【" + new String(content, 0, len) + "】");
    // 4. 關(guān)閉流
    input.close();
  }
}

2.3 字符輸出流Writer

Writer是一種字符輸出流的處理類腻要,使用方法也和OutputStream使用類似复罐,還是使用FileWriter進行父類對象的實例化。
比較有特色的就是雄家,可以直接向文件輸出字符數(shù)組或者字符串效诅。

范例:使用Writer類進行字符輸出。

package org.liyubo.java8demos.fileops;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterDemo {
  public static void main(String[] args) throws IOException {
      // 1. 定位到要操作的文件
      File file = new File("D:\\test\\fileops\\testwriter.txt");

      if(!file.getParentFile().exists()){  // 如果父目錄不存在的話趟济,創(chuàng)建父目錄
          file.getParentFile().mkdirs();
      }
      // 2. 創(chuàng)建Writer對象乱投,并使用FileWriter進行實例化
      Writer output  = new FileWriter(file);

      // 3. 執(zhí)行輸出,調(diào)用輸出字符串或者
      output.write("你好咙好,中國篡腌!");
      output.append('H');
      char[] content = new char[]{'s','v'};
      output.write(content);

      // 4. 關(guān)閉
      output.close();
  }
}
Writer寫入結(jié)果

2.4 字符輸入流Reader

Reader類是一個字符輸入類褐荷,使用方法和Writer類似勾效,不同的是,其只有將字符輸入流讀入字符數(shù)組的功能,沒有讀入字符串的功能层宫。

不寫例子了杨伙,沒啥意思。

字節(jié)輸入/出流和字符輸入/出流區(qū)別

其實萌腿,字符流的核心還是因為對中文操作更好限匣,但是現(xiàn)在使用一些方法也能將中文使用字節(jié)流很好的處理了。 在正常的開發(fā)中毁菱,還是字節(jié)流使用更多一些米死。

那么,所謂的一些操作又是怎么實現(xiàn)的呢贮庞?
原因就在于峦筒,其實,從流到文件中間窗慎,還有一層就是內(nèi)存的緩沖物喷。在流關(guān)閉之前,內(nèi)容都是緩沖在內(nèi)容中的遮斥,只有通過flush()操作強制刷新峦失,內(nèi)容才會寫入到文件。因此术吗,所謂的一些操作尉辑,就是如何在內(nèi)存中對流的緩沖進行操作的問題。在內(nèi)存的緩沖區(qū)中藐翎,就可以進行字節(jié)流和字符流之間的相互轉(zhuǎn)換材蹬。

3. 轉(zhuǎn)換流

如何在緩沖區(qū)中進行字符流和字節(jié)流的互相轉(zhuǎn)換呢,此處就主要涉及兩個類:

  • OutputStreamWriter: 將字節(jié)輸出流轉(zhuǎn)換成字符輸出流吝镣。
  • InputStreamReader:將字節(jié)輸入流轉(zhuǎn)換成字符輸入流堤器。
image.png

范例: 使用轉(zhuǎn)換流的操作

public class OutputStreamWriterDemo {
  public static void main(String[] args) throws IOException {
      // 1. 定位到要操作的文件
      File file = new File("D:\\test\\fileops\\testwriter.txt");

      if(!file.getParentFile().exists()){  // 如果父目錄不存在的話,創(chuàng)建父目錄
          file.getParentFile().mkdirs();
      }
      OutputStream os = new FileOutputStream(file);
      OutputStreamWriter writer = new OutputStreamWriter(os);

      // 3. 執(zhí)行輸出末贾,調(diào)用輸出字符串或者
      writer.write("你好闸溃,中國!");
      writer.append('H');

      char[] content = new char[]{'s','v'};
      writer.write(content);

      // 4. 關(guān)閉
      writer.close();
      os.close();
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拱撵,一起剝皮案震驚了整個濱河市辉川,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拴测,老刑警劉巖乓旗,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異集索,居然都是意外死亡屿愚,警方通過查閱死者的電腦和手機汇跨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妆距,“玉大人穷遂,你說我怎么就攤上這事∮榫荩” “怎么了蚪黑?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長中剩。 經(jīng)常有香客問我忌穿,道長,這世上最難降的妖魔是什么结啼? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任伴网,我火速辦了婚禮,結(jié)果婚禮上妆棒,老公的妹妹穿的比我還像新娘澡腾。我一直安慰自己,他們只是感情好糕珊,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布动分。 她就那樣靜靜地躺著,像睡著了一般红选。 火紅的嫁衣襯著肌膚如雪澜公。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天喇肋,我揣著相機與錄音坟乾,去河邊找鬼。 笑死蝶防,一個胖子當著我的面吹牛甚侣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播间学,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼殷费,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了低葫?” 一聲冷哼從身側(cè)響起详羡,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘿悬,沒想到半個月后实柠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡善涨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年窒盐,在試婚紗的時候發(fā)現(xiàn)自己被綠了茶行。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡登钥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娶靡,到底是詐尸還是另有隱情牧牢,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布姿锭,位于F島的核電站塔鳍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呻此。R本人自食惡果不足惜轮纫,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望焚鲜。 院中可真熱鬧掌唾,春花似錦、人聲如沸忿磅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葱她。三九已至撩扒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吨些,已是汗流浹背搓谆。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留豪墅,地道東北人泉手。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像偶器,于是被迫代替她去往敵國和親螃诅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1 IONo18 1.1IO框架 【 IO:Input Output 在程序運行的過程中状囱,可能需要對一些設備進...
    征程_Journey閱讀 962評論 0 1
  • 一术裸、流的概念和作用。 流是一種有順序的亭枷,有起點和終點的字節(jié)集合袭艺,是對數(shù)據(jù)傳輸?shù)目偝苫虺橄蟆<磾?shù)據(jù)在兩設備之間的傳輸...
    布魯斯不吐絲閱讀 10,038評論 2 95
  • 之所以寫這個是因為Hadoop的IO與·這個類似 但要比這個深入叨粘,而且都還涉及到網(wǎng)絡傳輸原理的五個層次猾编。所以瘤睹,一...
    起個什么呢稱呢閱讀 1,004評論 0 6
  • 一轉(zhuǎn)眼,假期就快要開學了答倡,這周轰传,有好的事,也有壞的事瘪撇,我覺得壞的事比較多一些获茬,也許我這人比較記仇吧。 我的閱讀 這...
    牛涵葳閱讀 202評論 0 0
  • 第一階段:2017-04-12 ~ 2017-04-21 十天時間刷完leetcode上所有簡單的題倔既。 leetc...
    健時總向亂中忙閱讀 1,032評論 0 1