Java中IO總結

File介紹

在整個IO包了,唯一表示與文件本身有關的類就是File類。使用File類可以進行1創建或刪除文件等常用操作。要想使用File類。則首先要觀察File類的構造方法,此類的常用構造方法如下所示:

No. 方法或常量 類型 描述

  • 1 public static final String pathSeparator 常量 表示路徑的分隔符(windows是“;”)
  • 2 public static final String separator 常量 表示路徑的分隔符(windows是“\”)
  • 3 public File(String pathname) 構造 創建File類對象,傳入完整路徑
  • 4 public boolean createNewFile()throws IOException 普通 創建新文件
  • 5 public boolean delete() 普通 刪除文件
  • 6 public boolean exists() 普通 判斷文件是否存在
  • 7 public boolean isDirectory() 普通 判斷給定的路徑是否在一個目錄
  • 8 public long length() 普通 返回文件的大小
  • 9 public String[] list() 普通 列出指定目錄的全部內容,只是名稱
  • 10 public File[] listFiles() 普通 列出指定目錄的全部內容,會有路徑
  • 11 Public Boolean mkdir() 普通 創建一個目錄
  • 12 Public Boolean renameTo(File dest) 普通 為已有的文件重命名

代碼:

public static void testFile() throws Exception {
    //新建
    File hello = new File("J:"+File.separator+"hello.txt");
    if (!hello.exists()) {
        hello.createNewFile();
    }
    
    File hello2 = new File("J:"+File.separator+"hello.txt");
    System.out.println(hello2.exists());//說明如果文件存在就使用現有的文件
    
    System.out.println(hello.getAbsolutePath());//J:\hello.txt
    System.out.println(hello.getPath());//J:\hello.txt
    hello.renameTo(new File("J:\\h.txt"));
    //刪除
    if (hello.exists()) {
//          hello.delete();
    }
    
    //新建文件夾
    File zhtFiles = new File("J:"+File.separator+"zhtFiles");
    if (!zhtFiles.exists()) {
        zhtFiles.mkdirs();
    }
    System.out.println(zhtFiles.getPath());//J:\zhtFiles
    //If this abstract pathname is already absolute, 
    //then the pathname string is simply returned as if by the getPath method. 
    System.out.println(zhtFiles.getAbsolutePath());//J:\zhtFiles
    
    //新建了多個文件
    for (int i=1; i<11; i++) {
        File fi = new File(zhtFiles.getPath() + File.separator +"zht"+i+".txt");
        fi.createNewFile();
    }
    
    File[] fs = zhtFiles.listFiles();
    for (File f : fs) {
        System.out.println(f);//帶路徑打印文件名
    }
    
    String[] strs = zhtFiles.list();
    for (String s : strs) {
        System.out.println(s);//只打印文件名
    }
    
    if (zhtFiles.isDirectory()) {
        zhtFiles.delete();//只能刪除空文件夾
    }
    
    deleteFile(zhtFiles.getAbsolutePath());
    
}

//使用遞歸進行文件刪除操作
static void deleteFile(String pathName) {
    File file = new File(pathName);
    
    if (!file.exists()) return;//文件不存在
    
    if (!file.isDirectory()) {//是文件
        file.delete();
    } else {//是文件夾
        //刪除文件夾下的文件
        File[] fs = file.listFiles();
        for (File f : fs) {
            deleteFile(f.getAbsolutePath());
        }
        file.delete();//刪除空文件夾
    }
}

IO介紹

IO就相當于程序對數據源的讀入或者寫出的操作方法API的集合。

參考:
http://www.lxweimin.com/p/0b86343232d2

http://www.cnblogs.com/liuhongfeng/p/5175109.html

http://www.lxweimin.com/p/328f4f67714b

IO是輸入和輸出的簡稱,在實際的使用時,輸入和輸出是有方向的。就像現實中兩個人之間借錢一樣,例如A借錢給B,相對于A來說是借出,而相對于B來說則是借入。所以在程序中提到輸入和輸出時,也需要區分清楚是相對的內容。

在程序中,輸入和輸出都是相對于當前程序而言的,例如從硬盤上讀取一個配置文件的內容到程序中,則相當于將文件的內容輸入到程序內部,因此輸入和“讀”對 應,而將程序中的內容保存到硬盤上,則相當于將文件的內容輸出到程序外部,因此輸出和“寫”對應。熟悉輸入和輸出的對應關系,將有助于后續內容的學習。

在Java語言中,輸入和輸出的概念要比其它語言的輸入和輸出的概念涵蓋的內容廣泛得多,不僅包含文件的讀寫,也包含網絡數據的發送,甚至內存數據的讀寫以及控制臺數據的接收等都由IO來完成。

為了使輸入和輸出的結構保持統一,從而方便程序員使用IO相關的類,在Java語言的IO類設計中引入了一個新的概念——Stream(流)。

由于在進行IO操作時,需要操作的種類很多,例如文件、內存和網絡連接等,這些都被稱作數據源(data source),對于不同的數據源處理的方式是不一樣的,如果直接交給程序員進行處理,對于程序員來說則顯得比較復雜。所以在所有的IO類設計時,在讀數據時,JDK API將數據源的數據轉換為一種固定的數據序列,在寫數據時,將需要寫的數據以一定的格式寫入到數據序列,由JDK API完成將數據序列中的數據寫入到對應的數據源中。這樣由系統完成復雜的數據轉換以及不同數據源之間的不同的變換,從而簡化程序員的編碼。

IO的 這種設計就和城市中的供水和排水系統設計是一樣的,在供水的時候,水源有江河水、湖水和地下水等不同類型,由自來水公司完成把水源轉換為對應的水流(InputStream)。而在 排水系統設計時,只需要將污水排入污水管道即可(OutputStream),至于這些污水是怎么被處理的,則不需要關心,這樣也簡化了家庭用水的處理。

IO設計中這種數據序列被形象的稱作流(Stream)。通過使用流的概念,使程序員面對不同的數據源時只需要建立不同的外殼流即可,不同的外殼流里面都是統一的內部流,程序員面對的就這個外殼流,外殼流封裝了很方便統一的操作API,而外殼流和內部流之間的復雜轉換則由系統完成,從而使程序員不必深入的了解每種數據源的讀寫方式,從而降低了IO編程的復雜度。

如圖所示:

QQ截圖20170729150115.jpg

字節流

流序列中的數據既可以是未經加工的原始二進制數據,也可以是經一定編碼處理后符合某種格式規定的特定數據。因此Java中的流分為兩種:

  1. 字節流:數據流中最小的數據單元是字節
  2. 字符流:數據流中最小的數據單元是字符, Java中的字 符是Unicode編碼,一個字符占用兩個字節。

InputStream(二進制格式操作):抽象類,基于字節的輸入操作,是所有輸入流的父類。定義了所有輸入流都具有的共同特征。

InputStream 為字節輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示字節輸入流的所有類的超類。 繼承自InputStream 的流都是向程序中輸入數據的,且數據單位為字節(8bit);
InputStream是輸入字節數據用的類,所以InputStream類提供了3種重載的read方法.Inputstream類中的常用方法:

(1) public abstract int read( ):讀取一個byte的數據,返回值是高位補0的int類型值。若返回值=-1說明沒有讀取到任何字節讀取工作結束。

(2) public int read(byte b[ ]):讀取b.length個字節的數據放到b數組中。返回值是讀取的字節數。該方法實際上是調用下一個方法實現的

(3) public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個字節的數據,存放到偏移量為off的b數組中。

(4) public int available( ):返回輸入流中可以讀取的字節數。注意:若輸入阻塞,當前線程將被掛起,如果InputStream對象調用這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類對象調用才有用,

(5) public long skip(long n):忽略輸入流中的n個字節,返回值是實際忽略的字節數, 跳過一些字節來讀取

(6) public int close( ) :我們在使用完后,必須對我們打開的流進行關閉.

主要的子類(截圖):

io2.jpg
  • 1) FileInputStream把一個文件作為InputStream,實現對文件的讀取操作
  • 2) ByteArrayInputStream:把內存中的一個緩沖區作為InputStream使用
  • 3) StringBufferInputStream:把一個String對象作為InputStream
  • 4) PipedInputStream:實現了pipe的概念,主要在線程中使用
  • 5) SequenceInputStream:把多個InputStream合并為一個InputStream

OutputStream(二進制格式操作):抽象類。基于字節的輸出操作。是所有輸出流的父類。定義了所有輸出流都具有的共同特征。 Java中字符是采用Unicode標準,一個字符是16位,即一個字符使用兩個字節來表示。為此,JAVA中引入了處理字符的流。

OutputStream提供了3個write方法來做數據的輸出,這個是和InputStream是相對應的。

  • 1. public void write(byte b[ ]):將參數b中的字節寫到輸出流。
  • 2. public void write(byte b[ ], int off, int len) :將參數b的從偏移量off開始的len個字節寫到輸出流。
  • 3. public abstract void write(int b) :先將int轉換為byte類型,把低字節寫入到輸出流中。
  • 4. public void flush( ) : 將數據緩沖區中數據全部輸出,并清空緩沖區。
  • 5. public void close( ) : 關閉輸出流并釋放與流相關的系統資源。

主要的子類(截圖):

IO3.jpg
    1. ByteArrayOutputStream:把信息存入內存中的一個緩沖區中
    1. FileOutputStream:把信息存入文件中
    1. PipedOutputStream:實現了pipe的概念,主要在線程中使用
    1. SequenceOutputStream:把多個OutStream合并為一個OutStream
      流結束的判斷:方法read()的返回值為-1時;readLine()的返回值為null時。

緩沖輸入輸出流 BufferedInputStream/ BufferedOutputStream

計算機訪問外部設備非常耗時。訪問外存的頻率越高,造成CPU閑置的概率就越大。為了減少訪問外存的次數,應該在一次對外設的訪問中,讀寫更多的數據。為此,除了程序和流節點間交換數據必需的讀寫機制外,還應該增加緩沖機制。緩沖流就是每一個數據流分配一個緩沖區,一個緩沖區就是一個臨時存儲數據的內存。這樣可以減少訪問硬盤的次數,提高傳輸效率。
BufferedInputStream:當向緩沖流寫入數據時候,數據先寫到緩沖區,待緩沖區寫滿后,系統一次性將數據發送給輸出設備。
BufferedOutputStream :當從向緩沖流讀取數據時候,系統先從緩沖區讀出數據,待緩沖區為空時,系統再從輸入設備讀取數據到緩沖區。

字符流

字符流主要用來處理文本文件。
Reader(文件格式操作):抽象類,基于字符的輸入操作。
Writer(文件格式操作):抽象類,基于字符的輸出操作。

程序:

    static void testStream() throws Exception {
        //FileInputStream
        FileOutputStream fos = new FileOutputStream("J:\\stream1.txt",true);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");
        String dateStr = sdf.format(new Date()) + "你好啊 " +"\n";
        fos.write(dateStr.getBytes("utf-8"));
        fos.close();
        
        FileInputStream fis = new FileInputStream("J:\\stream1.txt");
        int len = fis.available();
        byte[] buf = new byte[len];
        fis.read(buf);
//      System.out.println(new String(buf, "utf-8"));
        
        dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n.txt"));
        dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n2.txt"));
        
        
        //byteArray ByteArrayInputStream 將byte數組作為數據源
        //ByteArrayOutputStream 新建的bos對象內部包含了一個用來存儲數據的byte數組,初始大小32,自動增大
        //Creates a ByteArrayInputStream so that it uses buf as its buffer array. 
        byte[] byteSoure = "hello world 你好啊".getBytes("utf-8");
        ByteArrayInputStream bis = new ByteArrayInputStream(byteSoure);

        //Creates a new byte array output stream. 
        //The buffer capacity is initially 32 bytes, 
        //though its size increases if necessary.
        ByteArrayOutputStream bos = new ByteArrayOutputStream(1024*10);
        byte[] buf2 = new byte[100];
        int len2 = 0;
        while ((len2 = bis.read(buf2)) != -1) {
            bos.write(buf2, 0, len2);
        }
        System.out.println(new String(bos.toByteArray(), "utf-8"));
        
        //data Stream 在基本的stream上做了一層封裝,可以方便對各種數據類型進行讀寫
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("J:\\data"));
        dos.writeInt(120);
        dos.writeFloat(88.45f);
        dos.writeUTF("hello data");
        dos.close();
        
        DataInputStream dis = new DataInputStream(new FileInputStream("J:\\data"));
        System.out.println(dis.readInt());
        System.out.println(dis.readFloat());
        System.out.println(dis.readUTF());
        
        
        //Object Stream 對類進行讀寫,類要實現serializable接口
        Person p1 = new Person("zht", 28);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("J:\\object"));
        oos.writeObject(p1);
        
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("J:\\object"));
        Person p2 = (Person) ois.readObject();
        System.out.println(p2.toString());
        
        //打印類轉換成的字符串
        ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
        ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
        oos2.writeObject(p1);
        System.out.println(new String(bos2.toByteArray()));
        
    }
    
    //文件復制
    static void dump(InputStream scr, OutputStream dest) {
        try (InputStream tscr = scr; OutputStream tdest = dest) {//自動關閉
            
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = tscr.read(buf)) != -1) {
                tdest.write(buf, 0, len);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
    
    //更高效的復制
    static void dumpHighSpeed(InputStream scr, OutputStream dest) {
        try (BufferedInputStream tscr = new BufferedInputStream(scr); 
             BufferedOutputStream tdest = new BufferedOutputStream(dest)) {//自動關閉
            
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = tscr.read(buf)) != -1) {
                tdest.write(buf, 0, len);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
    
    
    //編輯文檔
    static void testWriterReader() throws Exception {
        //Reader通過InputStreamReader轉換而來,在轉換的時候注意設置編碼格式
        //Writer通過OutputStreamWriter轉換而來
        InputStreamReader reader = new InputStreamReader(System.in, "gbk");//使用utf-8會有亂碼
        OutputStreamWriter writer = new OutputStreamWriter(System.out, "gbk");
//      writer.write("hello 你好");
        writer.flush();//控制臺打印輸出
        
        char[] buf = new char[1024];
//      
//      int len = reader.read(buf);//從控制臺讀取數據
//      writer.write("get:"+new String(buf));
//      writer.flush();
        
        //常用 的FileReader FileWriter,因為不能設置編碼格式,建議盡量少用
        FileWriter fileWriter1 = new FileWriter("J:\\fw1.txt");//使用系統默認編碼
        fileWriter1.write("你好zht");
        fileWriter1.close();
        
        FileReader fReader1 = new FileReader("J:\\fw1.txt");//使用系統默認編碼
        fReader1.read(buf);
        System.out.println(new String(buf));
        
        //正確的讀寫文件姿勢
        BufferedWriter bufferedWriter = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream("J:\\bw1.txt"), "utf-8"));
        bufferedWriter.write("你好 bufferWriter");
        bufferedWriter.flush();
        bufferedWriter.close();
        
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(new FileInputStream("J:\\bw1.txt"), "utf-8"));
        System.out.println(bufferedReader.readLine());
        
        charSetConvert("J:\\w.txt", "utf-8", "gbk");
        
    }
    
    //文件編碼格式轉換
    static void charSetConvert(String srcFileName, String readCharSet,
             String writeCharSet) throws Exception {
        File wFile = new File("J:\\"+new Date().getTime());//臨時生成新的文件存放編碼轉換后的結果
        char[] buf = new char[1024];
        int len = 0;
        //自動關閉文件
        try (InputStreamReader reader = new InputStreamReader(new FileInputStream(srcFileName), readCharSet);
             OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(wFile), writeCharSet)) {
            while ((len = reader.read(buf)) != -1) {//編碼轉換
                writer.write(buf, 0, len);
            }
            writer.flush();
            
            //將臨時生成的文件覆蓋原文件
            byte[] bs = new byte[1024];
            FileInputStream fis = new FileInputStream(wFile);
            FileOutputStream fos = new FileOutputStream(srcFileName);
            while ((len = fis.read(bs)) != -1) {
                fos.write(bs, 0, len);
            }
            fos.close();
            fis.close();
        }
        wFile.delete();//刪除臨時文件
    }


class Person implements Serializable {
    String name;
    int age;
    
    public Person(String n, int a) {
        name = n;
        age = a;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "["+name+","+age+"]";
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容