java中IO流詳細(xì)解釋

[TOC]

IO流

IO流概述及其分類

IO概念

IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸,Java對數(shù)據(jù)的操作是通過流的方式
Java用于操作流的類都在IO包中诵盼,

流按流向分為兩種:

輸入流(讀取數(shù)據(jù))
輸出流(寫數(shù)據(jù))

流按操作類型分為兩種:

字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因為在計算機中任何數(shù)據(jù)都是以字節(jié)的形式存儲的
字符流 : 字符流只能操作純字符數(shù)據(jù)惠豺,比較方便。

常用的IO流類

字節(jié)流的抽象父類

InputStream
OutputStream

字符流的抽象父類:

Reader
Writer

InputStream & FileInputStream 文件輸入流

InputStream是抽象類风宁,表示字節(jié)輸入流洁墙。

直接已知子類:
●AudioInputStream
●ByteArrayInputStream
●FileInputStream(學(xué)習(xí)文件輸入流)
●FilterInputStream
●ObjectInputStream
●PipedInputStream
●SequenceInputStream
●StringBufferInputStream

FileInputStream 文件輸入流

概述

FileInputStream 從文件系統(tǒng)中的某個文件中獲得輸入字節(jié)。FileInputStream 用于讀取諸如圖像數(shù)據(jù)之類的原始字節(jié)流戒财。要讀取字符流热监,請考慮使用 FileReader

構(gòu)造方法

FileInputStream(File file)
FileInputStream(String name)

成員方法

int read() 從此輸入流中讀取一個數(shù)據(jù)字節(jié)。

案例:讀取一個txt文件數(shù)據(jù)(方法一)

知識點

  • 1.FileInputStream用于讀取文件數(shù)據(jù)饮寞,在構(gòu)造方法中傳入文件對象
  • 2.構(gòu)造方法孝扛,有可能拋出文件找不到的異常
  • 3.read方法是每次讀取一個字節(jié)的數(shù)據(jù),把字節(jié)轉(zhuǎn)成int返回
    • 讀取數(shù)據(jù)也會拋出異常,比如突然文件某部份數(shù)據(jù)損壞了
    • 讀取的數(shù)據(jù)是文件編碼的表值(ascii,GBK,unicode)
    • ascii是包含在GBK或者unicode中的
    • 如果讀取數(shù)據(jù)到最后幽崩,會返回一個-1(代表讀完數(shù)據(jù)了)
  • 4.文件不用后苦始,要關(guān)閉輸入流,避免占用資源
    package lesson10;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    /**
     * 讀取txt文件內(nèi)容
     * 1.通過FileInputStream來讀取txt文件內(nèi)容
     * 2.讀取內(nèi)容通過read方法慌申,
     *   》read方法每次讀文件1個字節(jié)(byte),把byte轉(zhuǎn)成int返回
          》當(dāng)讀到后的時候陌选,返回-1,-1表示讀取文件結(jié)束
       3.當(dāng)讀完文件后,這個輸入流要關(guān)閉咨油,釋放資源
     *
     */
    public class Demo01 {
    
        public static void main(String[] args) throws IOException {
            //FileNotFoundException fnfe;
    
            //案例:讀取txt文件內(nèi)容
            //1.創(chuàng)建一個文件對象
            File file = new File("a.txt");
            
            //2.創(chuàng)建一個文件輸入流【讀取文件數(shù)據(jù)】對象
            FileInputStream fis1 = new FileInputStream(file);
            
            //再創(chuàng)建一個文件輸入 流對象 
            FileInputStream fis2 = new FileInputStream("b.txt");
            
            //3.讀取a.txt的數(shù)據(jù)
            /**
             * 1.read方法每次讀文件1個字節(jié)(byte),把byte轉(zhuǎn)成int返回
             * 2.當(dāng)讀到后的時候您炉,返回-1,-1讀取文件結(jié)束
             */
            System.out.println(fis1.read());
            System.out.println(fis1.read());
            System.out.println(fis1.read());
            System.out.println(fis1.read());
            
            //4.關(guān)閉流
            fis1.close();
            fis2.close();
    
        }
    }

案例:讀取一個txt文件數(shù)據(jù)(方法二)

//1.創(chuàng)建一個文件對象
File file = new File("abc.txt");
System.out.println(file.getAbsolutePath());
                
//2.創(chuàng)建一個文件輸入流
FileInputStream inputStream = new FileInputStream(file);
        
int b;
//while循環(huán)里臼勉,每次讀取字節(jié)賦值給b
while((b = inputStream.read()) != -1){
System.out.println(b);
}

面試題:read()方法讀取的是一個字節(jié),為什么返回是int,而不是byte 邻吭?

因為字節(jié)輸入流可以操作任意類型的文件,比如圖片音頻等,這些文件底層都是以二進(jìn)制形式的存儲的,如果每次讀取都返回byte,有可能在讀到中間的時候遇到111111111 那么這11111111是byte類型的-1,我們的程序是遇到-1就會停止不讀了,后面的數(shù)據(jù)就讀不到了,所以在讀取的時候用int類型接收,如果11111111會在其前面補上 24個0湊足4個字節(jié),那么byte類型的-1就變成int類型的255了這樣可以保證整個數(shù)據(jù)讀完,而結(jié)束標(biāo)記的-1就是int類型


image

package lesson12;

public class Demo01 {

    public static void main(String[] args) {
        //面試題:read()方法讀取的是一個字節(jié),為什么返回是int,而不是byte ?
        //如果使用FileInputStream讀取圖片數(shù)據(jù)
        /**
         * 00010111 00010111 00010111 00010111
         * 00010111 11111111 00010111 00010111
         * 
         * byte:11111111 表示的-1
         * int:00000000 00000000 00000000 11111111  byte轉(zhuǎn)成int 補0 了不是-1   因此往后讀數(shù)據(jù)
         * 
         * 為什么11111111是表示-1宴霸?
         * 因為計算機是以補碼的方式計算
         * 補碼: 11111111 (-1)
         * 反碼: 11111110
         * 原碼:  10000001
         * 
         * 假如使用FileInputStream讀取圖片的時候囱晴,
         * 圖片中間有一段數(shù)據(jù)剛好是 11111111,這八個一表示的-1瓢谢,用byte接收
         * java程序如果讀取的是-1畸写,后面的數(shù)據(jù)就不讀取
         * 如果把8個1轉(zhuǎn)成int,那就是00000000 00000000 00000000 11111111,這個表示255,
         * 就不是-1氓扛,歸避后面數(shù)據(jù)沒有讀取問題
         * 
         */
    }
}

OutputStream & FileOutputStream 文件輸出流

  • 文件輸出流是用于將數(shù)據(jù)寫入 File 的輸出流枯芬。

  • FileOutputStream 用于寫入諸如圖像數(shù)據(jù)之類的原始字節(jié)的流。

  • 查看文檔的構(gòu)造方法和成員方法

  • 案例:往一個abc.txt文件寫數(shù)據(jù)(知識點)

    • new FileOutputStream(file)這種構(gòu)造方法采郎,會把以前的內(nèi)容都刪除

    • new FileOutputStream(file,true);這種構(gòu)造方法能追加內(nèi)容

    • FileNotFoundException是IOException的子類

    • write(int b)千所,寫數(shù)據(jù)


    package lesson13;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class Demo01 {
    
        public static void main(String[] args) throws IOException {
            // TODO Auto-generated method stub
    
    /*      FileOutputStream:表示文件輸出流,用于往文件寫內(nèi)容
     *      
     *      構(gòu)造方法
     *      FileOutputStream(String name)
     *      FileOutputStream(File file) 
     *      
     *      方法
     *      write(int b);//每次寫一個字節(jié)
     *      write(byte[] b) ;//一次寫多個字節(jié)
     * */
            
            //案例:往b.txt 寫個內(nèi)容
            //1.創(chuàng)建文件輸出流對象
            //FileOutputStream fos = new FileOutputStream("b.txt");
            OutputStream fos = new FileOutputStream("b.txt");//多態(tài)寫法
            
            //2.寫數(shù)據(jù) 
    //      fos.write(97);//a
    //      fos.write(98);//b
    //      fos.write(99);//c
            
            //一次性寫多個字節(jié)
            byte[] bytes = {97,98,99,100,101};
            fos.write(bytes);
            //3.關(guān)閉流
            fos.close();
        }
    
    }

案例:拷貝圖片和音頻

  • 原理蒜埋,使用輸入流讀取數(shù)據(jù)淫痰,使用輸出流寫數(shù)據(jù)
  • 畫圖講原理和性能
    每次都讀一次字節(jié),太慢整份,效率太低

image

package lesson14;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        
        //案例:拷貝圖片
        /**
         * 目的:結(jié)合輸入流和輸出流使用
         * 
         * 圖片路徑:C:\Users\10301\Desktop\a\cm.jpg
         */
        
        //1.先創(chuàng)建輸入流對象和輸出流對象
        FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");
        FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm2.jpg");
        
        //2.通過輸入流讀取圖片的數(shù)據(jù)
        int b = 0;
        while( (b = fis.read()) != -1){
            //3.通過輸出流寫入圖片數(shù)據(jù)
            fos.write(b);
        }
        
        //4.關(guān)閉流
        fos.close();
        fis.close();
        System.out.println("圖片拷貝成功");
    }
}

字節(jié)數(shù)組拷貝之a(chǎn)vailable()方法

package lesson01;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //案例:拷貝圖片【優(yōu)化一待错、這種方式在大文件下不建議使用】
        /**
         * 前面拷貝圖片問題:每次只讀一個字節(jié),寫入的時候也是一個字節(jié)一個字節(jié)寫
         *                  如果有10W個字節(jié)烈评,就要讀10W次火俄,寫10W次
         * 
         * 字節(jié)數(shù)組拷貝之a(chǎn)vailable()方法
         */
        //1.文件輸入流
        FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");
        int size = fis.available();//是返回文件的長度【字節(jié)為單位】
        System.out.println("文件的大小:" + size);
        
        //2.現(xiàn)在一次讀文件大小的字節(jié)
        //2.1定義一個字節(jié)數(shù)組
        byte[] bytes = new byte[size];//相當(dāng)于現(xiàn)在是一個空杯子
        //2.2 把數(shù)據(jù)讀到字節(jié)數(shù)組中
        int r = fis.read(bytes);//這個方法的返回值讀取到的實際長度
        System.out.println("r:" + r);
        
        //3.把字節(jié)數(shù)組一次性寫入到文件
        //3.1 輸出流
        FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm-副本.jpg");
        //3.2 寫數(shù)據(jù)
        fos.write(bytes);
        
        //4.關(guān)閉流
        fis.close();
        fos.close();
    }
}

案例:正確的拷貝文件的方法(杯子思想、緩沖思想)

1.輸入流讀取數(shù)據(jù)的方法:
read(byte[] b) 讀取指定字節(jié)數(shù)的數(shù)據(jù)
2.輸出流寫數(shù)據(jù)的方法:
write(byte[] b)
write(byte[] b, int off, int len)寫出有效的字節(jié)個數(shù)


image

package lesson02;

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

/**
 * 杯子思想,緩沖思想
 * @author gyf
 *
 */
public class Demo01 {

    public static void main(String[] args) throws IOException {
        //案例:拷貝圖片【優(yōu)化二讲冠、這種方式開發(fā)中建議經(jīng)常使用】
        /**
         * 1.每次只讀一個字節(jié)瓜客,又覺得太慢
         * 2.一次性讀一個文件的所有數(shù)據(jù),又怕內(nèi)存裝不下
         *   內(nèi)存只有2G,視頻3G,這樣就會內(nèi)存溢出
         * 
         * 3.最終解決方法:折中竿开,定義每次讀8KB
         * 
         */
        
        //1.輸入流
        FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");
        //2.輸出流
        FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm-副本2.jpg");
        
        //3.定義個8kb字節(jié)數(shù)組谱仪,也叫緩沖區(qū)流
        byte[] bytes =  new byte[1024 * 8];
        
        int len = 0;
        int i = 0;
        while( (len = fis.read(bytes)) != -1){
            i++;
            //4.寫入文件
            fos.write(bytes,0,len);
        }
        
        System.out.println("讀取的次數(shù):" + i);
        
        //5.關(guān)閉流
        fis.close();
        fos.close();
    }
}

BufferedInputStream和BufferOutputStream

  • 這兩個流是內(nèi)置了緩沖區(qū)流,也就是說內(nèi)部有一個 字節(jié)數(shù)組
  • 緩沖思想
    字節(jié)流一次讀寫一個數(shù)組的速度明顯比一次讀寫一個字節(jié)的速度快很多,
    java本身在設(shè)計的時候,加入了數(shù)組這樣的緩沖區(qū)效果德迹,
    也考慮到了這樣的設(shè)計思想(裝飾設(shè)計模式后面講解)芽卿,所以提供了字節(jié)緩沖區(qū)流
  • BufferedInputStream
    BufferedInputStream內(nèi)置了一個緩沖區(qū)(數(shù)組)
    從BufferedInputStream中讀取一個字節(jié)時
    BufferedInputStream會一次性從文件中讀取8192個(8Kb), 存在緩沖區(qū)中, 返回給程序
    程序再次讀取時, 就不用找文件了, 直接從緩沖區(qū)中獲取
    直到緩沖區(qū)中所有的都被使用過, 才重新從文件中讀取8192個
  • BufferedOutputStream
    BufferedOutputStream也內(nèi)置了一個緩沖區(qū)(數(shù)組)
    程序向流中寫出字節(jié)時, 不會直接寫到文件, 先寫到緩沖區(qū)中
    直到緩沖區(qū)寫滿, BufferedOutputStream才會把緩沖區(qū)中的數(shù)據(jù)一次性寫到文件里

案例:使用緩沖輸入輸出流拷貝文件


image

package lesson03;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        //1.創(chuàng)建文件輸入流
        FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/ghsy.mp3");
        
        //2.創(chuàng)建文件輸出流
        FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/ghsy-副本.mp3");
        
        //3.輸入流讀數(shù)據(jù)揭芍、輸出流寫數(shù)據(jù)
        int b = 0;
        while( (b = fis.read()) != -1){
            fos.write(b);
        }
        
        //4.關(guān)流
        fis.close();
        fos.close();
        
        System.out.println("音頻拷貝完成...");
        
    }

    private static void test1() throws FileNotFoundException, IOException {
        /*  BufferedInputStream和BufferedOutputStream
            >這兩個流是內(nèi)置了緩沖區(qū)流,也就是說內(nèi)部有一個字節(jié)數(shù)組
            >這個兩個類沒有前面我們寫的好用胳搞,因為它內(nèi)部每次讀8kb字節(jié),如果想讀80kb,沒辦法
    */
            //案例:拷貝音頻文件
            //1.創(chuàng)建緩沖輸入流
            FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/ghsy.mp3");
            BufferedInputStream bis = new BufferedInputStream(fis);
            
            //2.創(chuàng)建緩沖輸出流
            FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/ghsy-副本.mp3");
            BufferedOutputStream bos =new BufferedOutputStream(fos);
            
            //3.輸入流讀數(shù)據(jù)、輸出流寫數(shù)據(jù)
            
            int b = 0;
            // bis.read()方法肌毅,內(nèi)部會讀8kb數(shù)據(jù)
            while( (b = bis.read()) != -1){
                bos.write(b);//內(nèi)部會寫8kb數(shù)據(jù)
            }
            
            //4.關(guān)流,只需要關(guān)緩沖流筷转,文件流不用關(guān)
            bis.close();//【內(nèi)部會關(guān)文件流輸入流】
            bos.close();//【內(nèi)部會關(guān)文件流輸出流】
            
            System.out.println("音頻拷貝完成...");
    }

}

帶Buffered的流和自己寫的數(shù)組緩沖對比

自己寫 的數(shù)組的讀寫和帶Buffered的讀取哪個更快?
自己寫數(shù)組會略勝一籌,因為讀和寫操作的是同一個數(shù)組
而Buffered操作的是兩個數(shù)組

BufferOutputStream的flush和close方法的區(qū)別

  • flush()方法
    用來刷新緩沖區(qū)的,刷新后可以再次寫出
  • close()方法
    用來關(guān)閉流釋放資源的的,如果是帶緩沖區(qū)的流對象的close()方法,不但會關(guān)閉流,還會再關(guān)閉流之前刷新緩沖區(qū),關(guān)閉后不能再寫出
    package lesson05;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Demo01 {
    
        public static void main(String[] args) throws IOException {
            //BufferedOutputStream的flush和close方法的區(qū)別
        /*  flush()方法
                1.用來刷新緩沖區(qū)的,刷新后可以再次寫出 
            close()方法
                2.用來關(guān)閉流釋放資源的
                3.如果是帶緩沖區(qū)的流對象的close()方法,不但會關(guān)閉流,還會再關(guān)閉流之前刷新緩沖區(qū),關(guān)閉后不能再寫出 
        */
            
            //案例:把a文件的內(nèi)容拷貝到b文件
            
            //1.輸入流
            FileInputStream fis = new FileInputStream("a.txt");
            BufferedInputStream bis = new BufferedInputStream(fis);
            
            //2.輸出流
            FileOutputStream fos = new FileOutputStream("b.txt");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            
            //3.讀寫操作
            int b = 0;
            while( (b = bis.read()) != -1){
                bos.write(b);
            }
            
            bos.flush();
            bos.write(97);
            //bos.flush();
            //4.關(guān)閉流
            bis.close();
            bos.close();
            
            
        }
    
    }

字節(jié)流讀寫中文亂碼問題

字節(jié)流讀取中文:
字節(jié)流讀取中文的問題
字節(jié)流在讀中文的時候有可能會讀到半個中文,造成亂碼

package lesson06;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo06 {

    public static void main(String[] args) throws IOException {
        //字節(jié)流讀寫中文亂碼問題

        //1.讀數(shù)據(jù)
        //創(chuàng)建文件輸入流
        FileInputStream fis = new FileInputStream("a.txt");

        //讀
        //定義字節(jié)數(shù)組[杯子思想,緩沖區(qū)思想]
        /**
         * 在UTF-8編碼表中悬而,一個中文占3個字節(jié),一個英文占1個字節(jié)
         * 在GBK編譯中呜舒,一個中文占2個字節(jié)
         */
        byte buf[] = new byte[3];
        int len = 0;
        while( (len = fis.read(buf)) != -1){
            System.out.println("len:" + len );
            //把字節(jié)轉(zhuǎn)成字符串
            String s = new String(buf, 0, len);
            System.out.println("s:" + s);
        }
    }
}

字節(jié)流寫入中文的問題
字節(jié)流直接操作的字節(jié),所以寫出中文必須將字符串轉(zhuǎn)換成字節(jié)數(shù)組
寫出回車換行 write("\r\n".getBytes());

package lesson07;

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

public class Demo01 {

    public static void main(String[] args) throws IOException { 
        //案例:往a.txt文件寫中文
        
        //1.輸出流
        FileOutputStream fos = new FileOutputStream("a.txt");
        
        //2.寫中文
        String s = "你好,Gosling最近好嗎笨奠?";
        
        //把字符轉(zhuǎn)成字節(jié)數(shù)組
        //byte[] bytes = s.getBytes();
        
        /**
         * charsetName 字符編碼 UTF-8(Unicode),GBK,ASCII
         */
        byte[] bytes = s.getBytes("UTF-8");
        fos.write(bytes);
        
        //3.關(guān)流
        fos.close();
        
    }

}

流的標(biāo)準(zhǔn)處理異常代碼1.6版本及其以前

package lesson08;

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

public class Demo01 {

    public static void main(String[] args) throws IOException{
        //流的標(biāo)準(zhǔn)處理異常代碼-jdk1.6版本及其以前
        //案例:a.txt的內(nèi)容拷貝到b.txt
        
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("b.txt");
        
        try {
            //讀寫數(shù)據(jù)會拋出
            int b = 0;
            while((b = fis.read()) != -1){
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //關(guān)流
            try {
                fis.close();
            }finally {
                fos.close();
            }
        }
    }

    public static void test1() throws FileNotFoundException {

        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("b.txt");
        
        try {
            //讀寫數(shù)據(jù)會拋出
            int b = 0;
            while((b = fis.read()) != -1){
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //關(guān)流
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

流的標(biāo)準(zhǔn)處理異常代碼1.7以上版本

原理:在try()中創(chuàng)建的流對象必須實現(xiàn)了AutoCloseable這個接口,如果實現(xiàn)了,在try后面的{}(讀寫代碼)執(zhí)行后就會自動調(diào)用,流對象的close方法將流關(guān)掉

package lesson09;

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

public class Demo01 {

    public static void main(String[] args)throws Exception {
        //流的標(biāo)準(zhǔn)處理異常代碼1.7版本
        /**
         * 1.把流對象的聲明放在try() 括號里面
         * 2.操作流【讀寫數(shù)據(jù)】的代碼放在花括號里面
         * 3.這樣寫不用關(guān)閉流袭蝗,java自動關(guān)閉流
         * 4.在try的括號里的對象,必須是實現(xiàn)AutoCloseable的接口
         */
        try(
            FileInputStream fis = new FileInputStream("a.txt");
            FileOutputStream fos = new FileOutputStream("b.txt");
            //Person p = new Person();
            //聲明一個自己輸入流
            MyInputStream myis = new MyInputStream();
        ){
            int b = 0;
            while((b = fis.read()) != -1){
                fos.write(b);
            }
        }
    }
}

class Person{
    
}

class MyInputStream implements AutoCloseable{

    @Override
    public void close() throws Exception {
        System.out.println("我的輸入流關(guān)閉了...");
    }
}

練習(xí):圖片加密

package lesson10;

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

public class Demo01 {

    public static void main(String[] args)throws IOException {
        // TODO Auto-generated method stub
        //練習(xí):圖片加密
        
        //1.輸入輸出流
        FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm2.jpg");
        FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm.jpg");
        
        //2.讀寫數(shù)據(jù)
        /**
         * 加密操作
         * 解密操作
         * 
         * 一個數(shù)異或2次般婆,數(shù)據(jù)不變
         */
        int b = 0;
        while((b = fis.read()) != -1){
            fos.write(b ^ 5);
        }
        
        //3.關(guān)流
        fis.close();
        fos.close();

        System.out.println("圖片加密完成");
    }

}

練習(xí):根據(jù)用戶輸入的文件拷貝文件到當(dāng)前項目目錄

package lesson11;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //練習(xí):根據(jù)用戶輸入的文件[圖片]拷貝文件到當(dāng)前項目目錄
        //C:/Users/10301/Desktop/a/cm2.jpg
        
        //1.獲取用戶輸入的文件路徑
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入一個文件的路徑[請不要輸入文件夾路徑]:");
        String path = scanner.nextLine();
        
        //2.判斷這個路徑是否為文件
        File file = new File(path);
        if(file.isDirectory()){
            System.out.println("您輸入的路徑不是一個文件");
            return;
        }
        
        //3.如果是文件就拷貝
        //3.1 輸入流
        FileInputStream fis = new FileInputStream(path);
        
        //3.2輸出流
        FileOutputStream fos = new FileOutputStream(file.getName());
        
        //3.3讀寫【性能】
        byte[] buf = new byte[8 * 1024];
        
        int len = 0;
        while((len = fis.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        
        //3.4關(guān)流
        fis.close();
        fos.close();
        
        System.out.println("文件拷貝完成...");
        
    }
}

練習(xí):錄入數(shù)據(jù)拷貝到文件

      /**
         * 根據(jù)用戶在鍵盤中輸入的內(nèi)容到腥,然后寫到一個文件中去
         * 
         */


package lesson12;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //練習(xí):錄入數(shù)據(jù)拷貝到文件

        
        //1.創(chuàng)建一個文件輸出流
        FileOutputStream fos = new FileOutputStream("new.txt");
        
        //2.創(chuàng)建一個Scanner對象
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入需要錄入內(nèi)容...輸入quit代表退出");
        
        //3.通過死循環(huán)來獲取用戶輸入【當(dāng)輸入quit,代表不錄入】
        while(true){
            //獲取用戶的輸入
            String line = scanner.nextLine();
            
            //退出循環(huán)
            if(line.equals("quit")){
                break;
            }
            
            //寫入文件
            fos.write(line.getBytes());
            //換行
            fos.write("\r\n".getBytes());
        }
        
        //4.關(guān)流
        fos.close();

    }
}

字符流概念

字符流是什么

1蔚袍、字符流是可以直接讀寫字符的IO流
2乡范、字符流讀取字符, 就要先讀取到字節(jié)數(shù)據(jù), 然后轉(zhuǎn)為字符.
3、寫入字符, 需要把字符轉(zhuǎn)為字節(jié)再寫出.

字符流有Reader和Writer兩大派,開發(fā)中使用它們的子類(查看API)

FileReader 讀取字符流類
FileWrite 寫入字符流類

FileReader 讀取字符流

查看API的方法
案例:使用FileReader 讀取一個文本數(shù)據(jù)(知識點):
1啤咽、read方法是讀取字符char
2晋辆、一個字符可能占用1個字節(jié),2個字節(jié)宇整,或者3個字節(jié)
3瓶佳、占用字節(jié)個的數(shù)根據(jù)碼表決定(ASCII:1字節(jié),GBK:2字節(jié) unicode:3個字節(jié))
4没陡、用int表示字節(jié)涩哟,假如讀取到2個字節(jié),int有4個字節(jié)盼玄,前個兩個字節(jié)可以補0
5贴彼、GBK,unicode中,中文的字符的第一個字節(jié)都是負(fù)數(shù)埃儿,所以知道怎么去讀取
6器仗、讀取的方式與FileInputStream字節(jié)流差不多,會用FileInputStream童番,就會用 FileReader

package lesson13;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * 以后讀純文本文件精钮,使用FileReader這個類,為什么剃斧?因為我們不用考慮亂碼問題
 */
public class Demo01 {

    public static void main(String[] args) throws IOException {
        //讀字節(jié)
        FileInputStream fis = new FileInputStream("a.txt");
        //int 00000000 00000000 00000000 11111111
        System.out.println((byte)fis.read());
        System.out.println((byte)fis.read());
        System.out.println((byte)fis.read());
        
        System.out.println((byte)fis.read());
    
        System.out.println((byte)fis.read());
        System.out.println((byte)fis.read());
        System.out.println((byte)fis.read());
    }

    public static void test1() throws FileNotFoundException, IOException {
        //FileReader 
        /**
         * FileReader 用于讀取字符
         */
        
        //1.創(chuàng)建對象
        FileReader reader = new FileReader("a.txt");
        
        //2.讀取數(shù)據(jù)
        /**
         * reader.read() : 先讀取到字節(jié)數(shù)據(jù), 然后轉(zhuǎn)為字符
         */
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println(reader.read());
        
        int c;
        while((c = reader.read()) != -1){
            System.out.println((char)c);
        }
        
        //3.關(guān)閉流
        reader.close();
    }
}

FileWiter 寫入字符流

查看API中FileWriter的方法

案例:使用FileWrite寫入數(shù)據(jù)(知識點)

1.其實內(nèi)部是通過一個字符數(shù)組緩沖區(qū)寫入文件
2.內(nèi)部方法轨香,創(chuàng)建一個字符串長度的字符數(shù)組緩存區(qū)

package lesson14;

import java.io.FileWriter;
import java.io.IOException;

/**
 * FileWiter:
 * 掌握:
 * 1.write方法使用
 * 2.write方法內(nèi)部實現(xiàn),內(nèi)部是通過一個字符數(shù)組緩沖區(qū)寫入文件
 *
 */
public class Demo01 {

    public static void main(String[] args) throws Exception {
        //FileWiter 文件寫入流幼东、文件寫入字符流

        //案例:使用FileWiter往一個文件a.txt寫內(nèi)容
        
        //1.創(chuàng)建writer對象
        FileWriter writer = new FileWriter("a.txt");
        
        //2.寫內(nèi)容
        writer.write("你好!");
        writer.write("\r\n");
        writer.write("你好!");
        writer.write("\r\n");
        writer.write("你好!");
        writer.write("\r\n");
        writer.write("你好!");
        
        //3.關(guān)閉
        writer.close();
    }
}

案例:字符流的拷貝

//案例:字符流的拷貝
//思路:用FileReader讀字符,用FileWriter寫字符

package lesson15;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //案例:字符流的拷貝
        //思路:用FileReader讀字符,用FileWriter寫字符
        
        //1.創(chuàng)建 “讀取流” 對象
        FileReader reader = new FileReader("a.txt");
        
        //2.創(chuàng)建 "寫入流" 對象
        FileWriter writer = new FileWriter("b.txt");
        
        //3.讀取和寫入【緩沖思想】
        char[] buf = new char[8 * 1024];
        int len = 0;
        while( (len = reader.read(buf)) != -1){
            writer.write(buf, 0, len);
        }
        
        //4.關(guān)閉流
        reader.close();
        writer.close();
    }

    public static void test1() throws FileNotFoundException, IOException {
        //1.創(chuàng)建 “讀取流” 對象
        FileReader reader = new FileReader("a.txt");
        
        //2.創(chuàng)建 "寫入流" 對象
        FileWriter writer = new FileWriter("b.txt");
        
        //3.讀取和寫入
        int c = 0;
        while((c = reader.read()) != -1){
            writer.write(c);
        }
            
        //4.關(guān)閉流
        reader.close();
        writer.close();
    }
}

使用字符流的場景

package lesson01;

import java.io.FileWriter;

public class Demo01 {

    public static void main(String[] args) {
        //使用字符流的場景
        /**
         * 1.使用FileReader讀取字符
         *      原理:先讀字節(jié)臂容,把字節(jié)轉(zhuǎn)成字符(byte -> char)
         * 2.使用FileWriter寫入字符
         *      原理:writer(String str),str 轉(zhuǎn)成 字符數(shù)組 再轉(zhuǎn)成 字節(jié)寫入文件
         *      (string -> char[] -> char -> byte)
         * 如果是讀取文本文件科雳,使用FileReader比較好,不考慮亂碼問題
         * 如果是寫入文本文件,不建議使用FileWriter,直接使用FileOutputStream好一點
         */
    

    }
}

帶緩沖的字符流 BufferedReader/BufferedWriter

  1. BufferedReader

    1. read()方法讀取字符時會一次讀取若干字符到緩沖區(qū),然后逐個返回給程序, 降低讀取文件的次數(shù), 提高效率
  2. BufferedWriter

    1. write()方法寫出字符時會先寫到緩沖區(qū)緩沖區(qū)寫滿時才會寫到文件, 降低寫文件的次數(shù), 提高效率
    2. 查看源碼:字符緩沖區(qū)的大小是8192

package lesson02;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        /**
         * 帶緩沖的字符流 BufferedReader/BufferedWriter
         * 1.這兩個類脓杉,內(nèi)部都一個緩沖區(qū)糟秘,字符數(shù)組
         * 2.br.read()方法,內(nèi)部會讀8192(8*1024)個字符
         * 3.bw.write(),內(nèi)部會寫8192(8*1024)個字符
         * 
         * 回顧:帶緩沖的字節(jié)流,BufferedInputStream/BufferedOutputStream
         * 1.這兩個類球散,內(nèi)部都一個緩沖區(qū)尿赚,字節(jié)數(shù)組
         */
        
        
        //需求:拷貝文件,a.txt -> b.txt
        //1.創(chuàng)建Reader
        FileReader fr = new FileReader("a.txt");
        BufferedReader br = new BufferedReader(fr);
        
        //2.創(chuàng)建Writer
        FileWriter fw =new FileWriter("b.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        
        //3.讀寫
        int c = 0;
        while( (c = br.read()) != -1){
            bw.write(c);
        }
        
        //4.關(guān)流
        br.close();//內(nèi)部關(guān)閉FileReader
        bw.close();//內(nèi)部關(guān)閉FileWriter
        
        
    }

}

BufferedReader的readLine()&BufferedWriter的newLine()方法

package lesson03;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //BufferedReader的readLine()&BufferedWriter的newLine()方法
        /**
         * 1.readLine(),每次讀取一行數(shù)據(jù)
         */
        
        
        //1.創(chuàng)建Reader
        FileReader fr = new FileReader("a.txt");
        BufferedReader br = new BufferedReader(fr);
        
        //2.讀一行數(shù)據(jù)
/*      System.out.println(br.readLine());
        System.out.println(br.readLine());
        System.out.println(br.readLine());
        System.out.println(br.readLine());
        System.out.println(br.readLine());
        System.out.println(br.readLine());*/
        String line = null;
        while((line = br.readLine()) != null){
            System.out.println(line);
        }
        
        //3.關(guān)流
        br.close();
    }
}

BufferedWriter的newLine()方法

package lesson04;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //BufferedWriter的newLine()方法
        // newLine()換行
        
        //往b.txt寫a.txt文件的內(nèi)容【一行一行拷貝,讀一行寫一行】
        //1.創(chuàng)建Reader
        FileReader fr = new FileReader("a.txt");
        BufferedReader br = new BufferedReader(fr);
        
        //2.創(chuàng)建writer
        FileWriter fw = new FileWriter("b.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        
        //3.讀一行寫一行
        String line = null;
        while((line = br.readLine()) != null){
            bw.write(line);
            /**
             * 當(dāng)使用readline讀取一行數(shù)據(jù)時蕉堰,不會讀回車換行"\r\n"字符
             */
            //bw.write("\r\n");
            bw.newLine();//換行
        }
        
        //4.關(guān)流
        br.close();
        bw.close();
    }
}

案例:使用帶緩沖的字符流拷貝文件

**BufferedReader的readLine()&BufferedWriter的newLine()方法 **

  1. BufferedReader的readLine()方法可以讀取一行字符(不包含換行符號)

  2. BufferedWriter的newLine()可以輸出一個跨平臺的換行符號"\r\n"

案例:將文本反轉(zhuǎn)

一個文本文檔上的文本反轉(zhuǎn),第一行和倒數(shù)第一行交換,第二行和倒數(shù)第二行交換

package lesson05;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 掌握思想:
 * 1.for循環(huán)的倒序遍歷
 */
public class Demo01 {

    public static void main(String[] args) throws IOException {
        //案例:將文本反轉(zhuǎn)寫入另一個文件
        
        //1.把文本每一行內(nèi)容讀取出來存在List<String> 集合
        //1.1 集合對象
        List<String> list = new ArrayList<String>();
        
        //1.2一行行讀取文件
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        String line = null;
        while((line = br.readLine()) != null){
            list.add(line);
        }
        
        System.out.println(list);
        
        //2.當(dāng)我們要寫入文件時凌净,倒序保存List集合中的內(nèi)容到文件中
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        for(int i = list.size() - 1 ; i>=0; i--){
            bw.write(list.get(i));
            bw.newLine();//換行 
        }
        
        //3.關(guān)閉流
        br.close();
        bw.close();
        System.out.println("finish....");
    }
}

裝飾(Decorator)設(shè)計模式

裝飾模式的概念:
動態(tài)的給一個對象添加一些額外的功能,就增加功能來說屋讶,裝飾模式比生成子類更為靈活泻蚊。
在不必改變原類文件和使用繼承的情況下,動態(tài)的擴(kuò)展一個對象的功能丑婿。
它是創(chuàng)建一個包裝對象性雄,也就是使用裝飾來包裹真實的對象。

適用性

  1. 需要擴(kuò)展一個類的功能羹奉,或給一個類添加附加職責(zé)秒旋。
  2. 當(dāng)不能采用生成子類來實現(xiàn),比如final類

裝飾模式的實現(xiàn)方式

  1. 裝飾對象和真實對象有相同的接口诀拭。
  2. 裝飾對象包含一個真實對象的引用(reference)
  3. 裝飾對象的所有方法迁筛,內(nèi)部實現(xiàn)都是通過真實對象的引用來調(diào)用,然后實現(xiàn)自己的功能

案例1:

package lesson06;

public class Demo01 {

    public static void main(String[] args) {
        //
        /**
         * 一耕挨、設(shè)計模式【一種固定代碼風(fēng)格】
         *     面試題:Java中有哪些設(shè)計模式
         *     常用設(shè)計模式:裝飾模式细卧、單例模式、模版模式筒占、適配器模式贪庙、代理模式、工廠模式...
         * 
         * 二翰苫、裝飾(Decorator)設(shè)計模式
         *  1.裝飾模式的概念:
            裝飾模式是動態(tài)的給一個對象添加一些額外的功能止邮,就增加功能來說,裝飾模式比生成子類更為靈活奏窑。
            裝飾模式是在不必改變原類文件和使用繼承的情況下导披,動態(tài)的擴(kuò)展一個對象的功能。
            裝飾模式是創(chuàng)建一個包裝對象埃唯,也就是使用裝飾來包裹真實的對象撩匕。  
            
            2.裝飾模式的實現(xiàn)方式
                1. 裝飾對象和真實對象有相同的接口/抽象類。
                2. 裝飾對象包含一個真實對象的引用(reference)
                3. 裝飾對象的所有方法墨叛,內(nèi)部實現(xiàn)都是通過真實對象的引用來調(diào)用止毕,然后實現(xiàn)自己的功能

            3.適用性
                1. 需要擴(kuò)展一個類的功能并村,或給一個類添加附加職責(zé)。
                2. 當(dāng)不能采用生成子類來實現(xiàn)滓技,比如final類    
         */
        
    /*  BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        BufferedOutputStream bos;
        BufferedReader br;
        BufferedWriter bw;*/
        
        /*GYFStudent stu = new GYFStudent();
        stu.code();*/
        
        GYFStudent stu = new GYFStudent(new UniversityStudent());
        stu.code();
    }

}

//1.接口
interface Person{
    public void code();
}

//2.接口實現(xiàn)類
final class UniversityStudent implements Person{

    @Override
    public void code() {
        // TODO Auto-generated method stub
        System.out.println("在大學(xué)期間學(xué)了一點點C語言...");
    }
}

/*class GYFStudent extends UniversityStudent{
    @Override
    public void code() {
        // TODO Auto-generated method stub
        super.code();
        System.out.println("在GYF IT EDU 學(xué)習(xí)Java語言...");
    }
}*/

class GYFStudent implements Person{

    private UniversityStudent us;
    public GYFStudent(UniversityStudent us){
        this.us = us;
    }
    
    //裝飾對象的所有方法,內(nèi)部實現(xiàn)都是通過真實對象的引用來調(diào)用棚潦,然后實現(xiàn)自己的功能
    @Override
    public void code() {
        us.code();
        System.out.println("在GYF IT EDU 學(xué)習(xí)Java語言...");
    }
    
}

案例2:

package com.gyf.lesson09;

public class Demo {

    public static void main(String[] args) {

        GYFStudent stu = new GYFStudent();
        
        stu.coding();
    }
}


interface Person {
    //人可以具備編碼的功能
    public void coding();
}


//大學(xué)生
class UniversityStudent implements Person{

    @Override
    public void coding() {
        System.out.println("我會一點c基礎(chǔ)編程...");
    }
    
    public void piano(){
        System.out.println("我會鋼琴...");
    }
}

//第一種繼承類的寫法
class GYFStudent extends UniversityStudent{
    @Override
    public void coding() {
        // TODO Auto-generated method stub
        super.coding();
        System.out.println("我會java基礎(chǔ)編程了...");
    }
}

//class GYFStudent implements Person{
//  
//  private UniversityStudent uStu;
//  
//  public GYFStudent(UniversityStudent uStu) {
//      super();
//      this.uStu = uStu;
//  }
//
//
//  @Override
//  public void coding() {
//      // TODO Auto-generated method stub
//      uStu.coding();
//      System.out.println("我會java基礎(chǔ)編程了...");
//  }
//}

InputStreamReader&OutputStreamWriter

  • 這兩個類用于使用指定的碼表讀寫字符

  • FileReader是使用默認(rèn)碼表讀取文件, 如果需要使用指定碼表讀取請使用InputStreamReader(字符流,編碼表)

  • FileWriter是使用默認(rèn)碼表寫出文件, 如果需要使用指定碼表寫入請使用OutputStreamWriter(字符流,編碼表)


package lesson07;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Demo01 {

    public static void main(String[] args) throws IOException {
/*      InputStreamReader&OutputStreamWriter
        1>這兩個類用于使用指定的碼表讀寫字符*/
        
        
        //案例1:使用指定 “碼表UTF-8&GBK” 讀取字符
        /**
         * charsetName:字符編碼的名稱
         */
        FileInputStream fis = new FileInputStream("a.txt");
        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
        
        //讀一個字符
    /*  System.out.println((char)isr.read());
        System.out.println((char)isr.read());*/
        
        //讀一行
        BufferedReader br = new BufferedReader(isr);
        System.out.println(br.readLine());
        
        br.close();
        
    }
}

案例2:

package lesson07;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * 掌握:
 * 1.當(dāng)讀取文件內(nèi)容令漂,還有寫入文件,可以指定編碼格式
 * 2.使用InputStreamReader&OutputStreamWriter這個類
 * @author gyf
 *
 */
public class Demo02 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
    /*  OutputStreamWriter
        1>使用指定的編碼 寫入文件
        */
        
        //1.創(chuàng)建Writer
        FileOutputStream fos = new FileOutputStream("c.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
        BufferedWriter bw = new BufferedWriter(osw);
        
        //2.寫
        bw.write("你好丸边,IO流...搞的我有點暈...");
        bw.newLine();
        bw.write("你好叠必,IO流...搞的我有點暈...");
        bw.newLine();
        
        //3.關(guān)流
        bw.close();
        
        
    }

}

編碼轉(zhuǎn)換流圖解

image

練習(xí):獲取文本上字符出現(xiàn)的次數(shù)

package lesson08;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 掌握:當(dāng)鍵盤敲 enter鍵,兩個字符\r\n : 回車換行
 *
 */
public class Demo01 {

    public static void main(String[] args) throws IOException {
        //練習(xí):獲取文本上字符出現(xiàn)的次數(shù),把數(shù)據(jù)寫入文件
/*      思路:
        1.遍歷文本每一個字符
        2.字符出現(xiàn)的次數(shù)存在Map中
        *//**
         * Map<Character,Integer> map = new HashMap<Character,Integer>();
         * map.put('a',18);
         * map.put('你',2);
         *//*
        3.把map中的數(shù)據(jù)寫入文件*/
        
        //==================================
        //1.創(chuàng)建Map集合
        Map<Character,Integer> map = new HashMap<Character,Integer>();
        //System.out.println(map.get('a'));
        
        //2.遍歷每一個字符,每一個字符出現(xiàn)的次數(shù)放到map中
        FileReader reader = new FileReader("a.txt");
        int c = 0;
        while((c = reader.read()) != -1){
            //int 還原 char
            char ch = (char)c;
            // 判斷char是否在map中第一次出現(xiàn)
            if(map.get(ch) == null){
                map.put(ch, 1);
            }else{
                map.put(ch, map.get(ch) + 1);
            }
        }
        
        //3.把map中數(shù)據(jù)存在文件count.txt
        //3.1 創(chuàng)建Writer
        BufferedWriter bw = new BufferedWriter(new FileWriter("count.txt"));
        
        //3.2 遍歷map,再寫入數(shù)據(jù)
        for(Entry<Character, Integer> entry :map.entrySet()){
            switch (entry.getKey()) {
            case ' ':
                bw.write("空格=" + entry.getValue());
                break;
            case '\t'://\t表示tab 鍵字符
                bw.write("tab鍵=" + entry.getValue());
                break;
            case '\r'://
                bw.write("回車=" + entry.getValue());
                break;
            case '\n'://
                bw.write("換行=" + entry.getValue());
                break;
            default:
                bw.write(entry.getKey() + "=" + entry.getValue());
                break;
            }
            bw.newLine();
        }
        
        //4.關(guān)流
        reader.close();
        bw.close();
    }
}

遞歸(5妹窖!-5個乘階)

概述

  • 遞歸做為一種算法,在程序設(shè)計語言中廣泛應(yīng)用纬朝。
    遞歸:就方法內(nèi)部調(diào)用自己
  • 遞歸的弊端:不能調(diào)用次數(shù)過多,容易導(dǎo)致棧內(nèi)存溢出
    遞歸的好處:不用知道循環(huán)次數(shù)
  • 構(gòu)造方法是否可以遞歸調(diào)用?
    構(gòu)造方法不能使用遞歸調(diào)用

  • 遞歸調(diào)用是否必須有返回值?
    不一定(可以有,也可以沒有)


package lesson09;

public class Demo01 {

    public static void main(String[] args) {
        //遞歸
        /**
         * 遞歸做為一種算法,在程序設(shè)計語言中廣泛應(yīng)用。 
              遞歸:就方法內(nèi)部調(diào)用自己
              
              遞歸的弊端:不能調(diào)用次數(shù)過多,容易導(dǎo)致棧內(nèi)存溢出
              遞歸的好處:不用知道循環(huán)次數(shù)
         */
        
        //使用遞歸來寫乘階
        int r = jiecheng(116);
        System.out.println("r=" + r);
        
    }
    
    /**
     * jiecheng(6)  i = 6
     * 6 * jecheng(5)
     * 6 * 5 * jecheng(4)
     * 6 * 5 * 4 * jecheng(3)
     * 6 * 5 * 4 * 3 * jecheng(2)
     * 6 * 5 * 4 * 3 * 2 * jecheng(1)
     * 6 * 5 * 4 * 3 * 2 * 1
     */
    public static int jiecheng(int i){
        if(i==1){
            return 1;
        }else{
            return i * jiecheng(i - 1);
        }
    }
    
    /**
     * 使用for循環(huán)寫階乘
     */
    public static void test1() {
        //5骄呼!-5的階乘共苛,5個乘階
        //5*4*3*2*1
        
        int r = 1;//結(jié)果
        for(int i=1;i<=5;i++){
            r = r * i;
            /**
             * i = 1 ; r = 1*1
             * i = 2 ; r = 1* 1 * 2
             * i = 3 ; r = 1* 1 * 2 * 3
             * .....
             */
        }
        System.out.println("r=" + r);
    }
}

遞歸:文件目錄

package lesson10;

import java.io.File;

/**
 * 任務(wù):計算一個文件夾大小:累加文件的大小
 * @author gyf
 *
 */
public class Demo01 {

    public static void main(String[] args) {
        //遞歸:文件目錄
        /**打印出a目錄所有文件名稱蜓萄,包括子文件夾的文件*/
        
        //1.創(chuàng)建目錄對象
        File dir = new File("C:/Users/10301/Desktop/a");
        
        //2.打印目錄的子文件
        printSubFile(dir);
    }
    
    public static void printSubFile(File dir){
        //打印目錄的子文件
        File[] subfiles = dir.listFiles();
        
        for(File f : subfiles){
            if(f.isDirectory()){//文件夾
                printSubFile(f);
            }else{//文件
                System.out.println(f.getAbsolutePath());
            }
            
        }
    }
}

練習(xí):從鍵盤輸入接收一個文件夾路徑,打印出該文件夾下所有的.jpg文件名

package lesson11;

import java.io.File;
import java.util.Scanner;

public class Demo02 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //練習(xí):從鍵盤輸入接收一個文件夾路徑,打印出該文件夾下所有的.jpg文件名

        //1.獲取文件路徑
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入一個文件夾路徑...");
        String path = scanner.nextLine();
        
        //2.把路徑封裝成File對象
        File file = new File(path);
        if(!file.exists()){
            System.out.println("此路徑對應(yīng)的文件不存在");
            return;
        }
        
        if(!file.isDirectory()){
            System.out.println("請輸入文件夾路徑隅茎,而不文件路徑");
            return;
        }
        
        //3.遍歷文件夾下的子文件
        printSubFile(file);
        
    }
    
    public static void printSubFile(File dir){
        //打印目錄的子文件
        File[] subfiles = dir.listFiles();
        
        for(File f : subfiles){
            if(f.isDirectory()){//文件夾
                printSubFile(f);
            }else{//文件
                if(f.getName().endsWith(".jpg")){
                    System.out.println(f.getAbsolutePath());
                }
            }
        }
    }
}


SequenceInputStream 序列流

什么是序列流

序列流可以把多個字節(jié)輸入流整合成一個, 從序列流中讀取數(shù)據(jù)時, 將從被整合的第一個流開始讀, 讀完一個之后繼續(xù)讀第二個, 以此類推.

案例:使用字節(jié)流把兩個件數(shù)據(jù)寫到另一個文件

案例:使用序列流把兩個件數(shù)據(jù)寫到另一個文件

package lesson12;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //SequenceInputStream 序列流
        /**
         * InputStream:輸入流
         * Sequence:序列 連續(xù)
         * 
         * 序列流可以把多個字節(jié)輸入流整合成一個, 從序列流中讀取數(shù)據(jù)時, 
         * 將從被整合的第一個流開始讀, 讀完一個之后繼續(xù)讀第二個, 以此類推.
         */
        test2();
        
    }

    public static void test2() throws FileNotFoundException, IOException {
        //需求:a.txt,b.txt 依次寫c.txt
        
        //創(chuàng)建序列流
        FileInputStream fis1 = new FileInputStream("a.txt");
        FileInputStream fis2 = new FileInputStream("b.txt");
        SequenceInputStream sis = new SequenceInputStream(fis1, fis2);
        
        //創(chuàng)建輸出流
        FileOutputStream fos = new FileOutputStream("c.txt");
        
        //讀寫 
        int b = 0;
        while((b = sis.read()) != -1){
            fos.write(b);
        }
        
        fis2.close();
        sis.close();
        fos.close();
    }

    public static void test1() throws FileNotFoundException, IOException {
        //需求:a.txt,b.txt 依次寫c.txt
        //1.創(chuàng)建兩個輸入流
        FileInputStream fis1 = new FileInputStream("a.txt");
        FileInputStream fis2 = new FileInputStream("b.txt");
        
        //2.創(chuàng)建一個輸出流
        FileOutputStream fos = new FileOutputStream("c.txt");
        
        //3.先把a文件的內(nèi)容寫到c.txt
        int b = 0;
        while((b=fis1.read()) != -1){
            fos.write(b);
        }
        
        fos.write("\r\n".getBytes());//換行
        
        //4.再把b文件內(nèi)容寫到c.txt
        while((b=fis2.read()) != -1){
            fos.write(b);
        }
        
        //5.關(guān)流
        fis1.close();
        fis2.close();
        fos.close();
    }
}

序列流整合多個字節(jié)流(了解)

package lesson13;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class Demo01 {

    public static void main(String[] args) throws Exception {
        //SequenceInputStream序列流使用二
        //需求,把a.txt b.txt c.txt 的內(nèi)容拷貝到d.txt
        //1.Vector是集合
        Vector<InputStream> vector = new Vector<InputStream>();
        vector.add(new FileInputStream("a.txt"));
        vector.add(new FileInputStream("b.txt"));
        vector.add(new FileInputStream("c.txt"));
        
        //2.Enumeration枚舉
        Enumeration<InputStream> e = vector.elements();
        
        //3.序列流
        SequenceInputStream sis = new SequenceInputStream(e);
        
        //4.創(chuàng)建輸出流
        FileOutputStream fos = new FileOutputStream("d.txt");
        
        //讀寫 
        int b = 0;
        while((b = sis.read()) != -1){
            fos.write(b);
        }
        
        sis.close();
        fos.close();
    }
}

ByteArrayOutputStream字節(jié)數(shù)組輸出流

此類實現(xiàn)了一個輸出流嫉沽,其中的數(shù)據(jù)被寫入一個 byte 數(shù)組辟犀。緩沖區(qū)會隨著數(shù)據(jù)的不斷寫入而自動增長〕袼叮可使用 toByteArray() 和 toString() 獲取數(shù)據(jù)堂竟。

image
package lesson01;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        //ByteArrayOutputStream 字節(jié)數(shù)組輸出流
        /**
         * 1.前面學(xué)習(xí)的流-必需關(guān)于一個文件
         * FileOutputStream fos = new FileOutputStream("a.txt")
         * 
         * 2.ByteArrayOutputStream 不需要關(guān)聯(lián)文件
         *  
         * 3.此類實現(xiàn)了一個輸出流,其中的數(shù)據(jù)被寫入一個 byte 數(shù)組玻佩。
         *    緩沖區(qū)會隨著數(shù)據(jù)的不斷寫入而自動增長出嘹。
         *   可使用 toByteArray() 和 toString() 獲取數(shù)據(jù)。
         */
                
        //1.創(chuàng)建字節(jié)數(shù)組輸出流對象
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                
        //2.輸入流
        FileInputStream fis = new FileInputStream("a.txt");
        
        //3.寫入輸出流
        int b = 0;
        while((b = fis.read()) != -1){
            baos.write(b);
        }
        
        //自動把字節(jié)數(shù)組 轉(zhuǎn)成 字符串
        System.out.println(baos.toString());
        System.out.println(baos.toString("UTF-8"));//指定編碼格式的字符串
        
        //獲取文件數(shù)據(jù)
        byte[] bytes = baos.toByteArray();
        System.out.println(new String(bytes));
        System.out.println(new String(bytes, "UTF-8"));//指定編碼格式的字符串
        
        //4.關(guān)流
        fis.close();
        
    }
}

面試題:找bug

定義一個文件輸入流,調(diào)用read(byte[] b)方法,將a.txt文件中的內(nèi)容打印出來(byte數(shù)組大小限制為5)

package lesson02;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
/*      面試題:找bug
        定義一個文件輸入流,調(diào)用read(byte[] b)方法,
        將a.txt文件中的內(nèi)容打印出來(byte數(shù)組大小限制為5)*/

        //1.文件輸入流
        FileInputStream fis = new FileInputStream("a.txt");
        
        //2.字節(jié)數(shù)組輸出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
        //3.字節(jié)數(shù)組【緩沖區(qū)思想咬崔,杯子思想】
        byte[] arr = new byte[5];
        int len;
        while((len = fis.read(arr)) != -1) {
            //通過字節(jié)緩沖數(shù)組寫入
            baos.write(arr, 0, len);
            
            //把字節(jié)轉(zhuǎn)成字符串
            /**
             * 中文亂碼問題
             */
            System.out.println(new String(arr,0,len));
        }
        
        //內(nèi)部會調(diào)用toString方法,把字節(jié)數(shù)組轉(zhuǎn)成字符串
        System.out.println(baos);
        
        fis.close();
    }
}

對象操作流ObjecOutputStream& ObjecInputStream (了解)

什么是對象操作流

該流可以將一個對象寫出, 或者讀取一個對象到程序中. 也就是執(zhí)行了序列化和反序列化的操作.

歸檔(序列化) :將對象存在一個文件
解歸檔=反序列化:把一個文件解析出對象

ObjecOutputStream對象輸出流疚漆,把一個對象存儲起來,存儲的對象必須實現(xiàn)Serializable接口
ObjecInputStream對象輸入流刁赦,把存的數(shù)據(jù)還原成一個對象

package lesson03;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Demo01 {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub
        //對象操作流ObjectOutputStream& ObjectInputStream
        /**
         * 一娶聘、ObjectOutputStream:將一個對象寫入文件
         *    1.如果使用這個類寫入對象,這個對象需要序列化
         *    2.序列化就是讓這個對象實現(xiàn)一個Serializable接口
         *    3.如果沒實現(xiàn)Serializable接口甚脉,會拋異常NotSerializableException

         * 二丸升、ObjectInputStream:從文件中讀一個對象
         */
        
        //案例:從文件中取出女朋友對象
        //1.創(chuàng)建一個對象輸入流
        FileInputStream fis = new FileInputStream("gf.data");
        ObjectInputStream ois = new ObjectInputStream(fis);
        
        //2.讀數(shù)據(jù)
        GirlFriend gf1 = (GirlFriend) ois.readObject();
        System.out.println(gf1);
        GirlFriend gf2 = (GirlFriend) ois.readObject();
        System.out.println(gf2);
        
        /**
         * 如果沒有數(shù)據(jù)可讀了,強制讀的時候報錯了EOFException牺氨,
         */
        System.out.println(ois.readObject());
    }

    public static void test1() throws FileNotFoundException, IOException {
        //案例:將對象直接存入文件
        //1.創(chuàng)建女朋友對象
        GirlFriend gf1 = new GirlFriend("林志玲", 1.78);
        GirlFriend gf2 = new GirlFriend("林心如", 1.68);
        
        //2.創(chuàng)建對象輸出流
        FileOutputStream fos = new FileOutputStream("gf.data");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        
        //3.往文件存入對象
        oos.writeObject(gf1);
        oos.writeObject(gf2);
        
        //4.關(guān)流
        oos.close();
    }

}

class GirlFriend implements Serializable{
    String name;
    double height;
    public GirlFriend(String name, double height) {
        super();
        this.name = name;
        this.height = height;
    }
    @Override
    public String toString() {
        return "GirlFriend [name=" + name + ", height=" + height + "]";
    }
}

對象操作流優(yōu)化

為了方便讀取多個對象
建立把將對象存儲在集合中狡耻,然后將集合對象存入取出

package lesson05;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Demo01 {

    public static void main(String[] args) throws IOException, IOException {
        //對象操作流優(yōu)化-思路墩剖,存多個對象時,把對象存在list里面
        
        //把女朋友對象存在List中夷狰,再把List寫入文件【序列化/歸檔】
        
        //1.創(chuàng)建集合
        List<GirlFriend> list = new ArrayList<GirlFriend>();
        
        //2.添加女朋友
        list.add(new GirlFriend("林志玲", 1.78));
        list.add(new GirlFriend("林心如", 1.68));
        list.add(new GirlFriend("林嘉欣", 1.58));
        
        //3.把list存入文件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.data"));
        oos.writeObject(list);
        
        //4.關(guān)流
        oos.close();
    }
}

class GirlFriend implements Serializable{
    String name;
    double height;
    public GirlFriend(String name, double height) {
        super();
        this.name = name;
        this.height = height;
    }
    @Override
    public String toString() {
        return "GirlFriend [name=" + name + ", height=" + height + "]";
    }
}

package lesson05;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.util.List;

public class Demo02 {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub

        //案例:從list.data 讀取所有的女朋友對象【反序列化岭皂、解歸檔】
        
        //1.創(chuàng)建對象輸入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.data"));
        
        //2.讀取List對象
        Object obj = ois.readObject();
        
        //把obj轉(zhuǎn)list
        @SuppressWarnings("unchecked")
        List<GirlFriend> list = (List<GirlFriend>)obj;
        System.out.println(obj.getClass());
        
        //遍歷
        for(GirlFriend gf : list){
            System.out.println(gf);
        }
        
        ois.close();
    }

}

Serializable接口的ID

要歸檔或者序列化的對象必須實現(xiàn)Serializable接口才能被序列化
Serializable 中有個id,但I(xiàn)D不是一定有加的
SerialVersionUid沼头,簡言之爷绘,其目的是序列化對象版本控制,有關(guān)各版本反序列化時是否兼容进倍。
如果在新版本中這個值修改了土至,新版本就不兼容舊版本,反序列化時會拋出InvalidClassException異常猾昆。
如果修改較小陶因,比如僅僅是增加了一個屬性,我們希望向下兼容垂蜗,老版本的數(shù)據(jù)都能保留楷扬,那就不用修改;
如果我們刪除了一個屬性贴见,或者更改了類的繼承關(guān)系毅否,必然不兼容舊數(shù)據(jù),這時就應(yīng)該手動更新版本號蝇刀,即SerialVersionUid螟加。

package lesson06;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Demo01 {

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        // TODO Auto-generated method stub

    /*  Serializable接口的ID
        1.要歸檔或者序列化的對象必須實現(xiàn)Serializable接口才能被序列化 
        2.Serializable 中有個id,但I(xiàn)D不是一定要加的
        3.SerialVersionUid吞琐,簡言之捆探,其目的是以序列化對象進(jìn)行版本控制,有關(guān)各版本
        反序列化時是否兼容站粟。
        4.如果在新版本中這個值修改了黍图,新版本就不兼容舊版本,反序列化時會拋出InvalidClassException異常奴烙。
        5.如果修改較小助被,比如僅僅是增加了一個屬性,我們希望向下兼容切诀,老版本
            的數(shù)據(jù)都能保留揩环,那就不用修改;
        6.如果我們刪除了一個屬性幅虑,或者更改了類的繼承關(guān)系丰滑,必然不兼容舊數(shù)據(jù),
                這時就應(yīng)該手動更新版本號倒庵,即SerialVersionUid褒墨。
        7.一般不會添加ID,就算添加了ID,版本號最好不要修改
*/
        
        //save();
        //取學(xué)生
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stu.data"));
        Student stu = (Student) ois.readObject();
        System.out.println(stu);
        
    }

    public static void save() throws IOException, FileNotFoundException {
        //1.創(chuàng)建學(xué)生對象
        Student stu = new Student("霍建華");
        
        //2.把學(xué)生存入文件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.data"));
        
        /**
         * 存的學(xué)生的版本號是1
         */
        oos.writeObject(stu);
        
        //3.關(guān)流
        oos.close();
    }

}


class Student implements Serializable{

    /**
     * 序列化版本ID
     */
    private static final long serialVersionUID = 1L;
    
    private String name;
    
    private String hometown;

    public Student(String name) {
        super();
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + "]";
    }
    
}

打印流的概述和特點 (掌握)

**什么是打印流 **

該流可以很方便的將對象的toString()結(jié)果輸出, 并且自動加上換行, 而且可以使用自動刷出的模式
System.out就是一個PrintStream, 其默認(rèn)向控制臺輸出信息
PrintStream和PrintWriter分別是打印的字節(jié)流和字符流

package lesson07;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        //打印流的概述和特點 (掌握)
    /*  什么是打印流 
        1.該流可以很方便的將對象的toString()結(jié)果輸出, 并且自動加上換行, 而且可以使用自動刷出的模式
        2.System.out就是一個PrintStream, 其默認(rèn)向控制臺輸出信息
        3.PrintStream和PrintWriter分別是打印的字節(jié)流和字符流*/
        
        //1.打印的字節(jié)流【打印到控制臺】
        PrintStream ps = System.out;
        ps.println("你好炫刷,元宵節(jié)快樂");//打印字符串
        ps.println(19.6);
        
        //2.打印的字符流
        /**
         * 1.PrintWriter調(diào)用打印方法,控制臺是沒有內(nèi)容郁妈,它是把內(nèi)容寫到文件中
         * 2.如果打印了內(nèi)容浑玛,沒有調(diào)用flush或者close,內(nèi)容在文件中也不存在
         */
        PrintWriter pw = new PrintWriter("test.txt");
        pw.println("吃湯圓了...");
        pw.print("超市一包湯圓10幾塊錢");
        pw.print(13.01);
        //pw.flush();
        pw.close();

    }

}

標(biāo)準(zhǔn)輸入輸出流概述和輸出語句(了解)

System.in是InputStream, 標(biāo)準(zhǔn)輸入流, 默認(rèn)可以從鍵盤輸入讀取字節(jié)數(shù)據(jù)

System.out是PrintStream, 標(biāo)準(zhǔn)輸出流, 默認(rèn)可以向Console中輸出字符和字節(jié)數(shù)據(jù)

package lesson08;

import java.io.InputStream;
import java.io.PrintStream;

public class Demo01 {

    public static void main(String[] args) {
        //標(biāo)準(zhǔn)輸入輸出流概述和輸出語句(了解)
/*      System.in是InputStream, 標(biāo)準(zhǔn)輸入流, 默認(rèn)可以從鍵盤輸入讀取字節(jié)數(shù)據(jù)
        System.out是PrintStream, 標(biāo)準(zhǔn)輸出流, 默認(rèn)可以向Console中輸出字符和字節(jié)數(shù)據(jù)*/
        
        InputStream is = System.in;//標(biāo)準(zhǔn)輸入流
        PrintStream ps = System.out;//標(biāo)準(zhǔn)輸出流



    }
}

隨機訪問流概述和讀寫數(shù)據(jù)

**隨機訪問流概述 **

RandomAccessFile概述
RandomAccessFile類不屬于流噩咪,是Object類的子類顾彰。但它融合了InputStream和OutputStream的功能。
支持對隨機訪問文件的讀取和寫入剧腻。

package lesson09;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * RandomAccessFile這個類用于文件斷點下載
 * @author gyf
 *
 */
public class Demo01 {

    public static void main(String[] args) throws IOException {
        //隨機訪問流概述和讀寫數(shù)據(jù)
/*      隨機訪問流概述
        RandomAccessFile概述
        RandomAccessFile類不屬于流,是Object類的子類涂屁。但它融合了InputStream和OutputStream的功能书在。
        支持對隨機訪問文件的讀取和寫入。*/

        /**
         * 構(gòu)造方法兩個參數(shù):
         * name:文件名稱拆又、路徑
         * mode:模式 儒旬,r=read 只讀、 w=write
         */
        //1.創(chuàng)建一個隨機訪問流對象帖族,以讀寫的方式打開文件
        RandomAccessFile raf = new RandomAccessFile("a.txt", "rw");
        
        //2.讀字符
        /**
         * 使用RandomAccessFile的readChar/readLine方法讀文件有亂碼問題
         */
/*      System.out.println(raf.readChar());
        System.out.println(raf.readChar());
        System.out.println(raf.readChar());
        System.out.println(raf.readLine());*/
        
        //使用字節(jié)數(shù)組來讀比較好
/*      byte[] buf = new byte[1024];
        int len;
        while((len = raf.read(buf)) != -1){
            System.out.println(new String(buf,0,len));
        }*/
        
        //3.寫數(shù)據(jù)
        //raf.writeChars("abc");
        //raf.writeBytes("abc");
        raf.seek(4);//指定位置
        raf.write(97);
        raf.write(98);
        raf.write(99);
    }
}

DataOutputStream&DataInputStream

什么是數(shù)據(jù)輸入輸出流

DataInputStream, DataOutputStream可以按照基本數(shù)據(jù)類型大小讀寫數(shù)據(jù)
例如:
按Long大小寫出一個數(shù)字, 寫出時該數(shù)據(jù)占8字節(jié). 讀取的時候也可以按照Long類型讀取, 一次讀取8個字節(jié).

package lesson10;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        //DataOutputStream&DataInputStream 數(shù)據(jù)輸入輸出流
/*      DataInputStream, DataOutputStream可以按照基本數(shù)據(jù)類型大小讀寫數(shù)據(jù) 
        例如按Long大小寫出一個數(shù)字, 寫出時該數(shù)據(jù)占8字節(jié). 
        讀取的時候也可以按照Long類型讀取, 一次讀取8個字節(jié).*/

        //讀3個long數(shù)據(jù)
        DataInputStream dis = new DataInputStream(new FileInputStream("a.txt"));
        System.out.println(dis.readLong());//讀8個字節(jié)
        System.out.println(dis.readLong());//讀8個字節(jié)
        System.out.println(dis.readLong());//讀8個字節(jié)
        
    }

    public static void test1() throws FileNotFoundException, IOException {
        long a = 997;
        long b = 998;
        long c = 999;
        
        //使用FileOutputStream沒法寫入long類型數(shù)據(jù)
        FileOutputStream fos = new FileOutputStream("a.txt");
        //byte -128~127 0~255
/*      fos.write(997);只會寫一個字節(jié)栈源,不會寫4個字節(jié)
        fos.write(998);
        fos.write(999);*/
        
        //fos.wr
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeLong(a);//寫4個字節(jié)
        dos.writeLong(b);
        dos.writeLong(c);
        
        dos.close();
    }

}

Properties的概述和作為Map集合的使用

Properties的概述

Properties 類表示了一個持久的屬性集。

Properties 可保存在流中或從流中加載竖般。

屬性列表中每個鍵及其對應(yīng)值都是一個字符串甚垦。

方法

Properties的load()和store()

public Object setProperty(String key,String value)

public String getProperty(String key)

public Enumeration<String> stringPropertyNames()

package lesson11;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.Period;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

public class Demo01 {

    public static void main(String[] args) throws IOException, IOException {
        //Properties的概述和作為Map集合的使用【掌握-經(jīng)常用】

        /**
         * Properties:屬性
            1.Properties 類表示了一個持久的屬性集。
            2.Properties 可保存在流中或從流中加載涣雕。
            3.屬性列表中每個鍵及其對應(yīng)值都是一個字符串艰亮。
         */
        
        //遍歷properties所有屬性key和值value
        //1.創(chuàng)建屬性對象
        Properties p = new Properties();
        
        //2.關(guān)聯(lián)文件
        p.load(new FileInputStream("info.properties"));
        
        //3.遍歷一
        Set<Object> keys = p.keySet();
        for(Object key : keys){
            System.out.println(key + "=" + p.get(key));
        }
        //System.out.println(keys);
        
        //4.遍歷二
        System.out.println("=====================");
        //p.entrySet();
        for(Entry<Object, Object> entry :p.entrySet()){
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }

    public static void test2() throws IOException, FileNotFoundException {
        //使用Properties讀取數(shù)據(jù)
        //1.創(chuàng)建屬性對象
        Properties p = new Properties();
        
        //2.關(guān)聯(lián)文件
        p.load(new FileInputStream("info.properties"));
        
        //3.通過key讀數(shù)據(jù)
        String name = p.getProperty("name");
        String city = p.getProperty("city");
        String hometown = p.getProperty("hometown");
        System.out.println(name);
        System.out.println(city);
        System.out.println(hometown);
    }

    /**
     * 使用Properties來存儲數(shù)據(jù)
     */
    public static void test1() throws IOException, FileNotFoundException {
        //1.創(chuàng)建屬性對象
        Properties p = new Properties();
        
        //2.存數(shù)據(jù)
        p.setProperty("name", "gyf");
        p.setProperty("city", "廣州");
        p.setProperty("hometown", "梅州");
        
        //3.關(guān)聯(lián)文件
        /**
         * 當(dāng)Properties把key和value存入文件,把中文轉(zhuǎn)成unicode編碼
         */
        p.store(new FileOutputStream("info.properties"), null);
    }
}

捋一捋IO流

package lesson12;

public class Demo01 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //捋一捋IO流
        
        /**
         * 一挣郭、IO流-輸入輸出流
         * I:input
         * O:out
         * IO流 操作文件迄埃,讀取文件內(nèi)容,往文件寫內(nèi)容
         * 
         * 二兑障、字節(jié)流
         * 
         * >InputStream
         *  -FileInputStream 文件輸入流侄非,讀的單位是字節(jié)
         *  -BufferedInputStream 緩沖輸入流,內(nèi)部有個byte[]字節(jié)數(shù)組
         *  -SequenceInputStream 序列流流译,把多個字節(jié)流整合成一個流
         *  -ObjectInputStream 對象輸入流逞怨,直接從文件中讀取一個對象,這個對象要實現(xiàn)serilazable接口
         *  -Sytem.in 標(biāo)準(zhǔn)輸入流-指鍵盤
         *  -DataInputStream 數(shù)據(jù)輸入流,按基本數(shù)據(jù)類型的大小(long) 讀取文件
         *  
         * >OutputStream
         *  -FileOutputStream 文件輸出流福澡,寫的單位是字節(jié)
         *  -BufferedOutputStream 緩沖輸出流骇钦,內(nèi)部有個byte[]字節(jié)數(shù)組
         *  -ByteArrayOutputStream 字節(jié)數(shù)組輸出流,把數(shù)據(jù)讀取到內(nèi)存中竞漾,這個類不需要關(guān)聯(lián)文件
         *  -ObjectOutputStream 對象輸出流眯搭,直接把一個對象存入文件窥翩,
         *  -PrintStream 打印流,把內(nèi)容打印到控制臺
         *  -System.out 標(biāo)準(zhǔn)輸出流-指控制臺
         *  -DataOutputStream 數(shù)據(jù)輸出流鳞仙,按基本數(shù)據(jù)類型的大小(long) 寫入文件
         *  
         * 三寇蚊、字符流
         * >Reader
         *  -FileReader 文件讀取流,讀取的單位是字符
         *  -BufferedReader 緩沖讀取流棍好,內(nèi)部有個char[] 字符數(shù)組
         *  -InputStreamReader 指定字符編碼讀取文件
         * 
         * >Writer
         *  -FileWriter 文件寫入流,寫入的單位是字符
         *  -BufferedWriter,緩沖寫入流仗岸,內(nèi)部有個char[] 字符數(shù)組
         *  -OutputStreamWriter 指定字符編碼寫入文件
         *  -PrintWriter 打印流,把內(nèi)容打印一個文件
         *  
         *  
         * RandomAccessFile 隨機訪問流借笙,特點:讀和寫都在一個類中
         * 
         * Properties 相當(dāng)于Map一樣使用扒怖,這個類把數(shù)據(jù)存在一個后綴名為.properties文件
         */
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市业稼,隨后出現(xiàn)的幾起案子盗痒,更是在濱河造成了極大的恐慌,老刑警劉巖低散,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俯邓,死亡現(xiàn)場離奇詭異,居然都是意外死亡熔号,警方通過查閱死者的電腦和手機稽鞭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來引镊,“玉大人朦蕴,你說我怎么就攤上這事〉芡罚” “怎么了梦重?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亮瓷。 經(jīng)常有香客問我琴拧,道長,這世上最難降的妖魔是什么嘱支? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任蚓胸,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己痪署,他們只是感情好仓坞,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布屹篓。 她就那樣靜靜地躺著,像睡著了一般混巧。 火紅的嫁衣襯著肌膚如雪细睡。 梳的紋絲不亂的頭發(fā)上叹哭,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天忍宋,我揣著相機與錄音,去河邊找鬼风罩。 笑死糠排,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的超升。 我是一名探鬼主播入宦,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼室琢!你這毒婦竟也來了乾闰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤盈滴,失蹤者是張志新(化名)和其女友劉穎涯肩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雹熬,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡宽菜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年谣膳,在試婚紗的時候發(fā)現(xiàn)自己被綠了竿报。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡继谚,死狀恐怖烈菌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情花履,我是刑警寧澤芽世,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站诡壁,受9級特大地震影響济瓢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妹卿,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一旺矾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夺克,春花似錦箕宙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春陷寝,著一層夾襖步出監(jiān)牢的瞬間锅很,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工盼铁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粗蔚,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓饶火,卻偏偏與公主長得像鹏控,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肤寝,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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