1. 程式人生 > >day21(IO(字元流)&字元流其他內容&遞迴)

day21(IO(字元流)&字元流其他內容&遞迴)

###21.01_IO流(字元流FileReader)

* 1.字元流是什麼

* 字元流是可以直接讀寫字元的IO流

* 字元流讀取字元, 就要先讀取到位元組資料, 然後轉為字元. 如果要寫出字元, 需要把字元轉為位元組再寫出.    

* 2.FileReader

* FileReader類的read()方法可以按照字元大小讀取

*

FileReader fr = new FileReader("aaa.txt"); //建立輸入流物件,關聯aaa.txt

int ch;

while((ch = fr.read()) != -1) { //將讀到的字元賦值給ch

System.out.println((char)ch); //將讀到的字元強轉後列印

}

 

fr.close(); //關流

 

###21.02_IO流(字元流FileWriter)

* FileWriter類的write()方法可以自動把字元轉為位元組寫出

 

FileWriter fw = new FileWriter("aaa.txt");

fw.write("aaa");

fw.close();

 

###21.03_IO流(字元流的拷貝)

FileReader fr = new FileReader("a.txt");

FileWriter fw = new FileWriter("b.txt");

 

int ch;

while((ch = fr.read()) != -1) {

fw.write(ch);

}

 

fr.close();

fw.close();

###21.04_IO流(什麼情況下使用字元流)

* 字元流也可以拷貝文字檔案, 但不推薦使用. 因為讀取時會把位元組轉為字元, 寫出時還要把字元轉回位元組.

* 程式需要讀取一段文字, 或者需要寫出一段文字的時候可以使用字元流

* 讀取的時候是按照字元的大小讀取的,不會出現半個中文

* 寫出的時候可以直接將字串寫出,不用轉換為位元組陣列

 

###21.05_IO流(字元流是否可以拷貝非純文字的檔案)

* 不可以拷貝非純文字的檔案

* 因為在讀的時候會將位元組轉換為字元,在轉換過程中,可能找不到對應的字元,就會用?代替,寫出的時候會將字元轉換成位元組寫出去

* 如果是?,直接寫出,這樣寫出之後的檔案就亂了,看不了了  

 

###21.06_IO流(自定義字元陣列的拷貝)

*

 

FileReader fr = new FileReader("aaa.txt"); //建立字元輸入流,關聯aaa.txt

FileWriter fw = new FileWriter("bbb.txt"); //建立字元輸出流,關聯bbb.txt

 

int len;

char[] arr = new char[1024*8]; //建立字元陣列

while((len = fr.read(arr)) != -1) { //將資料讀到字元陣列中

fw.write(arr, 0, len); //從字元陣列將資料寫到檔案上

}

 

fr.close(); //關流釋放資源

fw.close();

 

###21.07_IO流(帶緩衝的字元流)

* BufferedReader的read()方法讀取字元時會一次讀取若干字元到緩衝區, 然後逐個返回給程式, 降低讀取檔案的次數, 提高效率

* BufferedWriter的write()方法寫出字元時會先寫到緩衝區, 緩衝區寫滿時才會寫到檔案, 降低寫檔案的次數, 提高效率

*

BufferedReader br = new BufferedReader(new FileReader("aaa.txt")); //建立字元輸入流物件,關聯aaa.txt

BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt")); //建立字元輸出流物件,關聯bbb.txt

 

int ch;

while((ch = br.read()) != -1) { //read一次,會先將緩衝區讀滿,從緩衝去中一個一個的返給臨時變數ch

bw.write(ch); //write一次,是將資料裝到字元陣列,裝滿後再一起寫出去

}

 

br.close(); //關流

bw.close();  

 

 

###21.08_IO流(readLine()和newLine()方法)

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

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

*

BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));

BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));

String line;

while((line = br.readLine()) != null) {

bw.write(line);

//bw.write("\r\n"); //只支援windows系統

bw.newLine(); //跨平臺的

}

 

br.close();

bw.close();

 

###21.09_IO流(將文字反轉)

* 將一個文字文件上的文字反轉,第一行和倒數第一行交換,第二行和倒數第二行交換

 

###21.10_IO流(LineNumberReader)

* LineNumberReader是BufferedReader的子類, 具有相同的功能, 並且可以統計行號

* 呼叫getLineNumber()方法可以獲取當前行號

* 呼叫setLineNumber()方法可以設定當前行號

*

LineNumberReader lnr = new LineNumberReader(new FileReader("aaa.txt"));

String line;

lnr.setLineNumber(100); //設定行號

while((line = lnr.readLine()) != null) {

System.out.println(lnr.getLineNumber() + ":" + line);//獲取行號

}

 

lnr.close();

 

###21.11_IO流(裝飾設計模式)

 

*

interface Coder {

public void code();

}

 

class Student implements Coder {

 

@Override

public void code() {

System.out.println("javase");

System.out.println("javaweb");

}

 

}

 

class HeiMaStudent implements Coder {

private Student s; //獲取到被包裝的類的引用

public HeiMaStudent(Student s) { //通過建構函式建立物件的時候,傳入被包裝的物件

this.s = s;

}

@Override

public void code() { //對其原有功能進行升級

s.code();

System.out.println("資料庫");

System.out.println("ssh");

System.out.println("安卓");

System.out.println(".....");

}

 

}

 

###21.12_IO流(使用指定的碼錶讀寫字元)

* FileReader是使用預設碼錶讀取檔案, 如果需要使用指定碼錶讀取, 那麼可以使用InputStreamReader(位元組流,編碼表)

* FileWriter是使用預設碼錶寫出檔案, 如果需要使用指定碼錶寫出, 那麼可以使用OutputStreamWriter(位元組流,編碼表)

*

BufferedReader br = //高效的用指定的編碼表讀

new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));

BufferedWriter bw = //高效的用指定的編碼表寫

new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));

int ch;

while((ch = br.read()) != -1) {

bw.write(ch);

}

 

br.close();

bw.close();

###21.13_IO流(轉換流圖解)

* 畫圖分析轉換流

 

###21.14_IO流(獲取文字上字元出現的次數)

* 獲取一個文字上每個字元出現的次數,將結果寫在times.txt上

分析:

     * 1,建立帶緩衝的輸入流物件

     * 2,建立雙列集合物件TreeMap

     * 3,將讀到的字元儲存在雙列集合中,儲存的時候要做判斷,如果不包含這個鍵,就將鍵和1儲存,如果包含這個鍵,就將該鍵和值加1儲存

     * 4,關閉輸入流

     * 5,建立輸出流物件

     * 6,遍歷集合將集合中的內容寫到times.txt中

     * 7,關閉輸出流

   public static void main(String[] args) throws IOException {

        //1,建立帶緩衝的輸入流物件

        BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));

        //2,建立雙列集合物件TreeMap

        TreeMap<Character, Integer> tm = new TreeMap<>();

        //3,將讀到的字元儲存在雙列集合中,儲存的時候要做判斷,如果不包含這個鍵,就將鍵和1儲存,如果包含這個鍵,就將該鍵和值加1儲存

        int ch;

        while((ch = br.read()) != -1) {

            char c = (char)ch;                  //強制型別轉換

            /*if(!tm.containsKey(c)) {

                tm.put(c, 1);

            }else {

                tm.put(c, tm.get(c) + 1);

            }*/

            tm.put(c, !tm.containsKey(c) ? 1 : tm.get(c) + 1);

        }

        //4,關閉輸入流

        br.close();

        //5,建立輸出流物件

        BufferedWriter bw = new BufferedWriter(new FileWriter("times.txt"));

        //6,遍歷集合將集合中的內容寫到times.txt中

        for(Character key : tm.keySet()) {

            switch (key) {

            case '\t':

                bw.write("\\t" + "=" + tm.get(key));    

                break;

            case '\n':

                bw.write("\\n" + "=" + tm.get(key));

                break;

            case '\r':

                bw.write("\\r" + "=" + tm.get(key));

                break;

            default:

                bw.write(key + "=" + tm.get(key));          //寫出鍵和值

                break;

            }

            bw.newLine();

        }

        //7,關閉輸出流

        bw.close();

    }

 

}

###21.15_IO流(試用版軟體)

* 當我們下載一個試用版軟體,沒有購買正版的時候,每執行一次就會提醒我們還有多少次使用機會用學過的IO流知識,模擬試用版軟體,試用10次機會,執行一次就提示一次您還有幾次機會,如果次數到了提示請購買正版

 

###21.16_File類(遞迴)

* 5的階乘

* 遞迴:方法自己呼叫自己

     * 5!

     * 5 * 4 * 3 * 2 * 1

     *

     * 5 * fun(4)(代表4!)

     *      4 * fun(3)(代表3!)

     *              3 * fun(2)(代表2!)

     *                      2 * fun(1)(代表1!)

     * 遞迴的弊端:不能呼叫次數過多,容易導致棧記憶體溢位

     * 遞迴的好處:不用知道迴圈次數

     *

     * 構造方法是否可以遞迴呼叫?

     * 構造方法不能使用遞迴呼叫

     *

     * 遞迴呼叫是否必須有返回值?

     * 不一定(可以有,也可以沒有)

public static void main(String[] args) {

        /*int result = 1;

 

        for(int i = 1; i <= 5; i++) {

            result = result * i;

        }

 

        System.out.println(result);*/

        System.out.println(fun(6000));

    }

 

    public static int fun(int num) {

        if(num == 1) {

            return 1;

        }else {

            return num * fun(num - 1);

        }

    }

}

###21.17_File類(練習)

* 需求:從鍵盤輸入接收一個資料夾路徑,打印出該資料夾下所有的.java檔名

分析:

     * 從鍵盤接收一個資料夾路徑

     * 1,如果錄入的是不存在,給與提示

     * 2,如果錄入的是檔案路徑,給與提示

     * 3,如果是資料夾路徑,直接返回

     *

     * 打印出該資料夾下所有的.java檔名

     * 1,獲取到該資料夾路徑下的所有的檔案和資料夾,儲存在File陣列中

     * 2,遍歷陣列,對每一個檔案或資料夾做判斷

     * 3,如果是檔案,並且字尾是.java的,就列印

     * 4,如果是資料夾,就遞迴呼叫

public static void main(String[] args) {

        File dir = getDir();

        printJavaFile(dir);

    }

 

    /*

     * 獲取鍵盤錄入的資料夾路徑

     * 1,返回值型別File

     * 2,不需要有引數

     */

    public static File getDir() {

        Scanner sc = new Scanner(System.in);                //建立鍵盤錄入物件

        System.out.println("請輸入一個資料夾路徑");

        while(true) {

            String line = sc.nextLine();                    //將鍵盤錄入的資料夾路徑儲存

            File dir = new File(line);                      //封裝成File物件

            if(!dir.exists()) {

                System.out.println("您錄入的資料夾路徑不存在,請重新錄入");

            }else if(dir.isFile()) {

                System.out.println("您錄入的是檔案路徑,請重新錄入資料夾路徑");

            }else {

                return dir;

            }

        }

    }

    /*

     * 獲取資料夾路徑下的所.java檔案

     * 1,返回值型別 void

     * 2,引數列表File dir

     */

    public static void printJavaFile(File dir) {

        //1,獲取到該資料夾路徑下的所有的檔案和資料夾,儲存在File陣列中

        File[] subFiles = dir.listFiles();

        //2,遍歷陣列,對每一個檔案或資料夾做判斷

        for (File subFile : subFiles) {

            //3,如果是檔案,並且字尾是.java的,就列印

            if(subFile.isFile() && subFile.getName().endsWith(".java")) {

                System.out.println(subFile);

            //4,如果是資料夾,就遞迴呼叫

            }else if (subFile.isDirectory()){

                printJavaFile(subFile);

            }

        }

    }

}

###21.18_IO流(總結)

* 1.會用BufferedReader讀取GBK碼錶和UTF-8碼錶的字元

* 2.會用BufferedWriter寫出字元到GBK碼錶和UTF-8碼錶的檔案中

* 3.會使用BufferedReader從鍵盤讀取一行