文件操作(3)FileOutputStream與相關(guān)方法、文件復(fù)制

1、FileOutputStream 寫(xiě)文本文件

  • 構(gòu)造輸出流對(duì)象,將數(shù)據(jù)內(nèi)容寫(xiě)入文件,關(guān)閉文件流對(duì)象

    常用方法:
    void write(int b)
    一次寫(xiě)一個(gè)字節(jié),b - 要寫(xiě)入的字節(jié)。
    void write(byte[] b,int off,int len)
    一次寫(xiě)一個(gè)字節(jié)數(shù)組的一部分
    b - 數(shù)據(jù)。 off - 數(shù)據(jù)的起始偏移量。 len - 要寫(xiě)入的字節(jié)數(shù)。
    void flush()
    刷新此緩沖的輸出流。這迫使所有緩沖的輸出字節(jié)被寫(xiě)出到底層輸出流中。
    void close()
    關(guān)閉輸出流

    常用構(gòu)造方法
    FileOutputStream (File file)
    FileOutputStream(String name)
    FileOutputStream(String name,boolean append)

    注意:前兩種構(gòu)造方法在向文件寫(xiě)數(shù)據(jù)時(shí)將覆蓋文件中原有的內(nèi)容
    創(chuàng)建FileOutputStream實(shí)例時(shí),如果相應(yīng)的文件并不存在,則會(huì)自動(dòng)創(chuàng)建一個(gè)空的文件

2、示例

import java.io.FileOutputStream;
public class TestFileOutputStream {
    public static void main(String[] args) {
        //FileOutputStream
    
        // 如果輸出流寫(xiě)入文件,需要追加寫(xiě)入新的內(nèi)容,必須在創(chuàng)建輸出流對(duì)象時(shí),指定是否追加寫(xiě)入?yún)?shù)為true,默認(rèn)是false
        
        //1、創(chuàng)建文件輸出流對(duì)象
        try (
                //jdk1.7 之后,此寫(xiě)法支持自動(dòng)關(guān)閉自定義流對(duì)象
                //FileOutputStream fos = new FileOutputStream("/Users/xiayimiaoyijiuyonggan/Projects/Kh100/eee.txt")
                FileOutputStream fos = new FileOutputStream("/Users/xiayimiaoyijiuyonggan/Projects/Kh100/eee.txt",true)
                ){
            //2 使用文件輸出流對(duì)象,寫(xiě)對(duì)象
            //模擬程序內(nèi)數(shù)據(jù)
            String writeStr = "KH100,學(xué)習(xí)文件輸出流";
            
            //將數(shù)據(jù)寫(xiě)入目標(biāo)文件
            //fos.write(int b); 一次寫(xiě)一個(gè)字節(jié)
            fos.write(writeStr.getBytes());
            fos.flush();
            
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

3、文件復(fù)制(字節(jié))

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

/**
 * 利用文件輸入流與輸出流實(shí)現(xiàn)文件的復(fù)制操作
 */
public class CopyDemo {
  public static void main(String[] args) throws IOException {
    //用文件輸入流讀取待復(fù)制的文件
//        FileInputStream fis = new FileInputStream("image.jpg");
    FileInputStream fis = new FileInputStream("01.rmvb");
    //用文件輸出流向復(fù)制文件中寫(xiě)入復(fù)制的數(shù)據(jù)
//        FileOutputStream fos = new FileOutputStream("image_cp.jpg");
    FileOutputStream fos = new FileOutputStream("01_cp.rmvb");
        /*
            原文件image.jpg中的數(shù)據(jù)
            10100011 00111100 00001111 11110000....
            ^^^^^^^^
            讀取該字節(jié)

            第一次調(diào)用:
            int d = fis.read();
            d的2進(jìn)制:00000000 00000000 00000000 10100011
                                               讀到的字節(jié)


            fos向復(fù)制的文件image_cp.jpg中寫(xiě)入字節(jié)

            第一次調(diào)用:
            fos.write(d);
            作用:將給定的int值d的2進(jìn)制的"低八位"寫(xiě)入到文件中
            d的2進(jìn)制:00000000 00000000 00000000 10100011
                                               寫(xiě)出字節(jié)
            調(diào)用后image_cp.jpg文件數(shù)據(jù):
             10100011
         */
        /*
            循環(huán)條件是只要文件沒(méi)有讀到末尾就應(yīng)該復(fù)制
            如何直到讀取到末尾了呢?
            前提是:要先嘗試讀取一個(gè)字節(jié),如果返回值是-1就說(shuō)明讀到末尾了
            如果返回值不是-1,則說(shuō)明讀取到的是一個(gè)字節(jié)的內(nèi)容,就要將他寫(xiě)入到復(fù)制文件中
         */
    int d;//先定義一個(gè)變量,用于記錄每次讀取到的數(shù)據(jù)
    long start = System.currentTimeMillis();//獲取當(dāng)前系統(tǒng)時(shí)間
    while ((d = fis.read()) != -1) {
      fos.write(d);
    }
    long end = System.currentTimeMillis();
    System.out.println("復(fù)制完畢!耗時(shí):" + (end - start) + "ms");
    fis.close();
    fos.close();
  }
}

4、文件復(fù)制(塊讀寫(xiě))

  • int read(byte[] data) 一次性從文件中讀取給定的字節(jié)數(shù)組總長(zhǎng)度的字節(jié)量,并存入到該數(shù)組中。 返回值為實(shí)際讀取到的字節(jié)量。若返回值為-1則表示讀取到了文件末尾。

  • 塊寫(xiě)操作 void write(byte[] data) 一次性將給定的字節(jié)數(shù)組所有字節(jié)寫(xiě)入到文件中

  • void write(byte[] data,int offset,int len) 一次性將給定的字節(jié)數(shù)組從下標(biāo)offset處開(kāi)始的連續(xù)len個(gè)字節(jié)寫(xiě)入文件

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

/**
 * 通過(guò)提高每次讀寫(xiě)的數(shù)據(jù),減少讀寫(xiě)次數(shù)可以提高讀寫(xiě)效率。
 */
public class CopyDemo2 {
  public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("01.rmvb");
    FileOutputStream fos = new FileOutputStream("01_cp.rmvb");
        /*
            塊讀:一次性讀取一組字節(jié)
            塊寫(xiě):一次性將寫(xiě)出一組字節(jié)

            java.io.InputStream上定義了塊讀字節(jié)的方法:
            int read(byte[] data)
            一次性讀取給定字節(jié)數(shù)組length個(gè)字節(jié)并從頭開(kāi)始裝入到數(shù)組中。返回值為實(shí)際讀取到的字節(jié)量
            如果返回值為-1則表示流讀取到了末尾。
            文件流重寫(xiě)了該方法,作用是塊讀文件里的數(shù)據(jù)。

            java.io.OutputStream上定義了塊寫(xiě)字節(jié)的方法:
            void write(byte[] data)
            一次性將給定的字節(jié)數(shù)組中所有的字節(jié)寫(xiě)出。

            void write(byte[] data,int offset,int len)
            一次性將給定的字節(jié)數(shù)組data中從下標(biāo)offset處開(kāi)始的連續(xù)len個(gè)字節(jié)寫(xiě)出。


            原文件數(shù)據(jù)(假設(shè)文件共6個(gè)字節(jié)):
            11110000 00001111 01010101 11111111 00000000 10101010

            byte[] buf = new byte[4];//創(chuàng)建一個(gè)長(zhǎng)度為4的字節(jié)數(shù)組
            buf默認(rèn)的樣子(每個(gè)元素若以2進(jìn)制表現(xiàn)):{00000000,00000000,00000000,00000000}
            int len;//記錄每次實(shí)際讀取的字節(jié)數(shù)

            當(dāng)?shù)谝淮握{(diào)用:
            len = fis.read(buf);
            由于字節(jié)數(shù)組buf的長(zhǎng)度為4.因此可以一次性最多從文件中讀取4個(gè)字節(jié)并裝入到buf數(shù)組中
            返回值len表示的整數(shù)是這次實(shí)際讀取到了幾個(gè)字節(jié)。

            原文件數(shù)據(jù)(假設(shè)文件共6個(gè)字節(jié)):
            11110000 00001111 01010101 11111111 00000000 10101010
            ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                     第一次讀取的4個(gè)字節(jié)

            buf:{11110000,00001111,01010101,11111111}
            len:4 表示本次讀取到了4個(gè)字節(jié)


            第二次調(diào)用:
            len = fis.read(buf);

            原文件數(shù)據(jù)(假設(shè)文件共6個(gè)字節(jié)):
            11110000 00001111 01010101 11111111 00000000 10101010 文件末尾了
                                                ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                                                本次實(shí)際只能讀取到2個(gè)字節(jié)
            buf:{00000000,10101010,01010101,11111111}
                 |本次新讀的2字節(jié)數(shù)據(jù)| |---上次的舊數(shù)據(jù)---|
            len:2表示本次實(shí)際只讀取到了2個(gè)字節(jié)。它的意義就是告訴你buf數(shù)組中前幾個(gè)字節(jié)是本次真實(shí)
                讀取到的數(shù)據(jù)


            第三次調(diào)用:
            len = fis.read(buf);
            原文件數(shù)據(jù)(假設(shè)文件共6個(gè)字節(jié)):
            11110000 00001111 01010101 11111111 00000000 10101010 文件末尾了
                                                                  ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
            buf:{00000000,10101010,01010101,11111111} 沒(méi)有任何變化!
            len:-1 表示本次讀取時(shí)已經(jīng)是文件末尾了!!
         */
        /*
            00000000 8位2進(jìn)制 1byte  1字節(jié)
            1024byte = 1kb
            1024kb = 1mb
            1024mb = 1gb
            1024gb = 1tb
         */
        /*
            編譯完該句代碼:byte[] buf = new byte[10240];

            在實(shí)際開(kāi)發(fā)中,有時(shí)候用一個(gè)計(jì)算表達(dá)式更能表現(xiàn)這個(gè)值的含義時(shí),我們不妨使用計(jì)算表達(dá)式
            long t = 864000000;
            long t = 60 * 60 * 24 * 1000;

         */
    byte[] buf = new byte[1024 * 10];//10kb
    int len;//記錄每次實(shí)際讀取到的字節(jié)數(shù)
    long start = System.currentTimeMillis();
    while ((len = fis.read(buf)) != -1) {
      fos.write(buf, 0, len);
    }
    long end = System.currentTimeMillis();
    System.out.println("復(fù)制完畢,耗時(shí):" + (end - start) + "ms");
    fis.close();
    fos.close();
  }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容