1. 程式人生 > 其它 >nginx 配置php

nginx 配置php

#IO

概述

  • IO流介紹

    • IO:輸入/輸出(Input/Output)
    • 流:是一種抽象概念,是對資料傳輸的總稱.也就是說資料在裝置間的傳輸稱為流,流的本質是資料傳輸
    • IO流就是用來處理裝置間資料傳輸問題的.常見的應用: 檔案複製; 檔案上傳; 檔案下載
    • 參照物:記憶體 記憶體在讀,記憶體在寫
  • IO流的分類

  • 按照資料的流向

    • 輸入流:讀資料
    • 輸出流:寫資料
  • 按照資料型別來分

    • 位元組流
      • 位元組輸入流
      • 位元組輸出流
    • 字元流
      • 字元輸入流
      • 字元輸出流
  • IO流的使用場景

    • 如果操作的是純文字檔案,優先使用字元流
    • 如果操作的是圖片、視訊、音訊等二進位制檔案,優先使用位元組流
    • 如果不確定檔案型別,優先使用位元組流.位元組流是萬能的流

純文字檔案?

用windows記事本開啟能讀懂的檔案就是純文字檔案

純文字:字元流,否則:位元組流

位元組流

位元組流寫資料

  • 位元組流抽象基類

    • InputStream:這個抽象類是表示位元組輸入流的所有類的超類
    • OutputStream:這個抽象類是表示位元組輸出流的所有類的超類
    • 子類名特點:子類名稱都是以其父類名作為子類名的字尾
  • 位元組輸出流

    • FileOutputStream(String name):建立檔案輸出流以指定的名稱寫入檔案
  • 使用位元組輸出流寫資料的步驟

    • 建立位元組輸出流物件(呼叫系統功能建立了檔案,建立位元組輸出流物件,讓位元組輸出流物件指向檔案)
    • 呼叫位元組輸出流物件的寫資料方法
    • 釋放資源(關閉此檔案輸出流並釋放與此流相關聯的任何系統資源)
  • 示例程式碼

public class OutPutDemo {
    public static void main(String[] args) throws IOException {
        //1.建立位元組輸出流物件--- 告訴虛擬機器我要往哪個檔案中寫資料  下面兩個方法一樣的我們用第一個簡單的就行
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt");
        FileOutputStream fs = new FileOutputStream(new File("F:\\itheima\\a.txt"));
        //2.寫資料
        fos.write(97);
        //3.釋放資源
        fos.close();
    }
}

注意事項:

  1. 建立位元組輸出流物件

    1.如果檔案不存在,會幫我們建立
    2.如果檔案存在,會把檔案清空

  2. 寫資料

    傳遞一個整數時,那麼實際上寫到檔案中的,是這個整數在碼錶中對應的字元

  3. 釋放資源

    告訴作業系統,我現在已經不需要再用這個檔案了

    每次使用完流必須要釋放資源

位元組流寫資料的三種方式

  • 寫資料的方法分類

    方法名 說明
    void write(int b) 將指定的位元組寫入此檔案輸出流 一次寫一個位元組資料
    void write(byte[] b) 將 b.length位元組從指定的位元組陣列寫入此檔案輸出流 一次寫一個位元組陣列資料
    void write(byte[] b, int off, int len) 將 len位元組從指定的位元組陣列開始,從偏移量off開始寫入此檔案輸出流 一次寫一個位元組陣列的部分資料
  • 示例程式碼

一次寫一個位元組

public class OutPutDemo1 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt");
        fos.write(97);
        fos.write(98);
        fos.write(99);
        fos.close();
    }
}

一次寫一個位元組陣列

public class OutPutDemo2 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt");
        byte[] arr = {97,98,99};
        fos.write(arr);
        fos.close();
    }
}

一次寫一個位元組陣列的一部分

public class OutPutDemo3 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt");
        byte[] arr = {97,98,99,100,101,102,103,104};
        fos.write(arr,1,3);
        fos.close();//bcd
    }
}

位元組流寫資料的兩個小問題

  • 位元組流寫資料如何實現換行

    • windows:\r\n
    • linux:\n
    • mac:\r
  • 示例程式碼

public class OutPutDemo4 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt");
        fos.write(97);
        fos.write("\r\n".getBytes());
        fos.write(98);
        fos.write("\r\n".getBytes());
        fos.write(99);
        fos.write("\r\n".getBytes());
        fos.write(100);
        fos.write("\r\n".getBytes());
        fos.write(101);
        fos.write("\r\n".getBytes());
        fos.close();
    }
}

位元組流寫資料如何實現追加寫入

  • public FileOutputStream(String name,boolean append)
  • 建立檔案輸出流以指定的名稱寫入檔案。如果第二個引數為true ,則位元組將寫入檔案的末尾而不是開頭
  • 示例程式碼
public class OutPutDemo4 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\itheima\\a.txt",true);
        fos.write(69);
        fos.write("\r\n".getBytes());
        fos.write(70);
        fos.write("\r\n".getBytes());
        fos.close();
    }
}

第二個引數是續寫開關,如果不寫就是false,表示不開啟續寫功能會清空檔案內容

位元組流寫資料加異常處理

  • 異常處理格式

    • try-catch-finally

      try{
      	可能出現異常的程式碼;
      }catch(異常類名 變數名){
      	異常的處理程式碼;
      }finally{
      	執行所有清除操作;
      }
      
    • finally特點

      • 被finally控制的語句一定會執行,除非JVM退出
  • 示例程式碼

public class OutPutDemo5 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("F:\\itheima\\a.txt", true);
            fos.write(69);
            fos.write("\r\n".getBytes());
            fos.write(70);
            fos.write("\r\n".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

位元組流讀資料

位元組流讀取資料方式

一次讀取一個位元組
  • 位元組輸入流

    • FileInputStream(String name):通過開啟與實際檔案的連線來建立一個FileInputStream,該檔案由檔案系統中的路徑名name命名
  • 位元組輸入流讀取資料的步驟

    • 建立位元組輸入流物件

      如果檔案存在,那麼正常

      如果檔案不存在會報FileNotFoundException

    • 呼叫位元組輸入流物件的讀資料方法

      一次讀取一個位元組,返回值就是本次讀到的那個位元組資料

      也就是字元在碼錶中的數字,如果先要看到字元資料,那麼一定要強轉為char

    • 釋放資源

  • 示例程式碼

public class OutPutDemo6 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\itheima\\a.txt");
        int read = fis.read();
        System.out.println(read);
        fis.close();//a
    }
}
讀多個位元組
public class OutPutDemo7 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\itheima\\a.txt");
        //檔案中多個位元組怎麼辦
      int b;
      while ((b = fis.read()) != -1){
          System.out.println((char)b);
      }
      fis.close();
    }
}

複製檔案

  • 案例需求

    ​ 把“E:\itcast\窗裡窗外.txt”複製到模組目錄下的“窗裡窗外.txt” (檔案可以是任意檔案)

  • 實現步驟

    • 複製文字檔案,其實就把文字檔案的內容從一個檔案中讀取出來(資料來源),然後寫入到另一個檔案中(目的地)

    • 資料來源:

      ​ E:\itcast\窗裡窗外.txt --- 讀資料 --- InputStream --- FileInputStream

    • 目的地:

      ​ myByteStream\窗裡窗外.txt --- 寫資料 --- OutputStream --- FileOutputStream

  • 程式碼實現

一次讀一個位元組陣列
  • 案例需求

    ​ 把“E:\itcast\mn.jpg”複製到模組目錄下的“mn.jpg” (檔案可以是任意檔案去)

  • 實現步驟

    • 根據資料來源建立位元組輸入流物件
    • 根據目的地建立位元組輸出流物件
    • 讀寫資料,複製圖片(一次讀取一個位元組陣列,一次寫入一個位元組陣列)
    • 釋放資源
  • 程式碼實現

public class OutPutDemo9 {
    public static void main(String[] args) throws IOException {
        //準備讀檔案
        FileInputStream fis = new FileInputStream("F:\\itheima\\a.txt");
        //準備寫檔案
        FileOutputStream fos = new FileOutputStream("F:\\setup\\a.txt");
        //一次讀一個拷貝速度慢怎麼辦
        //相當於買雞蛋的籃子  容器
        byte[] buf = new byte[1024];
        //本次讀到的有效位元組個數 -- 這次讀了幾個位元組
        int len;
        while ((len = fis.read(buf)) != -1){
        	//0索引開始len個位元組,這裡是檔案中字元個數
            fos.write(buf, 0, len);
        }
        fis.close();
        fos.close();
    }
}

位元組緩衝流

  • 位元組緩衝流介紹

    • lBufferOutputStream:該類實現緩衝輸出流.通過設定這樣的輸出流,應用程式可以向底層輸出流寫入位元組,而不必為寫入的每個位元組導致底層系統的呼叫
    • lBufferedInputStream:建立BufferedInputStream將建立一個內部緩衝區陣列.當從流中讀取或跳過位元組時,內部緩衝區將根據需要從所包含的輸入流中重新填充,一次很多位元組
  • 構造方法:

    方法名 說明
    BufferedOutputStream(OutputStream out) 建立位元組緩衝輸出流物件
    BufferedInputStream(InputStream in) 建立位元組緩衝輸入流物件
  • 為什麼構造方法需要的是位元組流,而不是具體檔案或路徑呢?

    位元組緩衝流僅僅提供緩衝區,而真正讀寫資料還得靠基本的位元組流物件進行操作

    緩衝流只是為了提高效率而存在的

一次讀取一個位元組資料
  • 示例程式碼
public class OutPutDemo10 {
    public static void main(String[] args) throws IOException {
        //建立位元組緩衝輸入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\itheima\\a.txt"));
        //建立位元組緩衝輸出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\setup\\a.txt"));
        int b;
        while ((b = bis.read()) != -1){
            bos.write(b);
        }
        //方法的底層會把位元組流給關閉
        bis.close();
        bos.close();
    }

BufferedInputStream、BufferedOutputStream相當於在底層建立了一個長度為8192的位元組陣列

一次讀寫一個位元組陣列
public class OutPutDemo11 {
    public static void main(String[] args) throws IOException {
        //建立位元組緩衝輸入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\itheima\\a.txt"));
        //建立位元組緩衝輸出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\setup\\a.txt"));
        byte[] buf = new byte[1024];
        int len;
        while ((len = bis.read(buf)) != -1){
            bos.write(buf, 0, len);
        }
        bis.close();
        bos.close();
    }
}

字元流

為什麼會出現字元流

  • 字元流的介紹

    由於位元組流操作中文不是特別的方便,所以Java就提供字元流

    字元流 = 位元組流 + 編碼表

  • 中文的位元組儲存方式

    用位元組流複製文字檔案時,文字檔案也會有中文,但是沒有問題,原因是最終底層操作會自動進行位元組拼接成中文,如何識別是中文的呢?

    漢字在儲存的時候,無論選擇哪種編碼儲存,第一個位元組都是負數

編碼表

  • 什麼是字符集

    是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數字等

    l計算機要準確的儲存和識別各種字符集符號,就需要進行字元編碼,一套字符集必然至少有一套字元編碼。常見字符集有ASCII字符集、GBXXX字符集、Unicode字符集等

  • 常見的字符集

    • ASCII字符集:

      lASCII:是基於拉丁字母的一套電腦編碼系統,用於顯示現代英語,主要包括控制字元(回車鍵、退格、換行鍵等)和可顯示字元(英文大小寫字元、阿拉伯數字和西文符號)

      基本的ASCII字符集,使用7位表示一個字元,共128字元。ASCII的擴充套件字符集使用8位表示一個字元,共256字元,方便支援歐洲常用字元。是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數字等

    • GBXXX字符集:

      GBK:最常用的中文碼錶。是在GB2312標準基礎上的擴充套件規範,使用了雙位元組編碼方案,共收錄了21003個漢字,完全相容GB2312標準,同時支援繁體漢字以及日韓漢字等

    • Unicode字符集:

      UTF-8編碼:可以用來表示Unicode標準中任意字元,它是電子郵件、網頁及其他儲存或傳送文字的應用 中,優先採用的編碼。網際網路工程工作小組(IETF)要求所有網際網路協議都必須支援UTF-8編碼。它使用一至四個位元組為每個字元編碼

      編碼規則:

      128個US-ASCII字元,只需一個位元組編碼

      拉丁文等字元,需要二個位元組編碼

      大部分常用字(含中文),使用三個位元組編碼

      其他極少使用的Unicode輔助字元,使用四位元組編碼

字串中的編碼解碼問題

  • 相關方法

    方法名 說明
    byte[] getBytes() 使用平臺的預設字符集將該 String編碼為一系列位元組
    byte[] getBytes(String charsetName) 使用指定的字符集將該 String編碼為一系列位元組
    String(byte[] bytes) 使用平臺的預設字符集解碼指定的位元組陣列來建立字串
    String(byte[] bytes, String charsetName) 通過指定的字符集解碼指定的位元組陣列來建立字串
  • 程式碼演示

public class OutPutDemo12 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String sf = "大吉大利,今晚吃雞!";
        byte[] bytes = sf.getBytes();
        //利用idea預設的UTF-8編碼為一系列位元組
        System.out.println(Arrays.toString(bytes));
        byte[] bytes1 = sf.getBytes("GBK");
        System.out.println(Arrays.toString(bytes1));
    }
}

執行結果

[-27, -92, -89, -27, -112, -119, -27, -92, -89, -27, -120, -87, -17, -68, -116, -28, -69, -118, -26, -103, -102, -27, -112, -125, -23, -72, -95, -17, -68, -127]
[-76, -13, -68, -86, -76, -13, -64, -5, -93, -84, -67, -15, -51, -19, -77, -44, -68, -90, -93, -95]
大吉大利,
大吉大利,今晚吃雞!

位元組流為什麼會出現亂碼

因為位元組流一次讀取一個位元組,而不管GBK還是UTF-8一箇中文都是多個位元組,用位元組流每次只能讀取其中一部分內容,所以就會出現亂碼問題。

字元流讀取中文過程

字元流 = 位元組流 + 碼錶;

基礎知識:

不管在哪張碼錶中,中文的第一個位元組一定是負數

字元流寫資料

  • 介紹

    Writer: 用於寫入字元流的抽象父類

    FileWriter: 用於寫入字元流的常用子類

  • 構造方法

    方法名 說明
    FileWriter(File file) 根據給定的 File 物件構造一個 FileWriter 物件
    FileWriter(File file, boolean append) 根據給定的 File 物件構造一個 FileWriter 物件
    FileWriter(String fileName) 根據給定的檔名構造一個 FileWriter 物件
    FileWriter(String fileName, boolean append) 根據給定的檔名以及指示是否附加寫入資料的 boolean 值來構造 FileWriter 物件
  • 成員方法

    方法名 說明
    void write(int c) 寫一個字元
    void write(char[] cbuf) 寫入一個字元陣列
    void write(char[] cbuf, int off, int len) 寫入字元陣列的一部分
    void write(String str) 寫一個字串
    void write(String str, int off, int len) 寫一個字串的一部分
  • 重新整理和關閉的方法

    方法名 說明
    flush() 重新整理流,之後還可以繼續寫資料
    close() 關閉流,釋放資源,但是在關閉之前會先重新整理流。一旦關閉,就不能再寫資料
  • 程式碼演示

一次寫出一個字元
public class OutPutDemo13 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        FileWriter fw = new FileWriter(new File("F:\\itheima\\a.txt"));
        //寫出資料
        fw.write(97);
        fw.write(98);
        fw.write(99);
        //釋放資源
        fw.close();
    }
}
一次寫出一個字元陣列
public class OutPutDemo13 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        FileWriter fw = new FileWriter(new File("F:\\itheima\\a.txt"));
        //寫出資料
        char [] chars = {97,98,99,100};
        fw.write(chars);
        //釋放資源
        fw.close();
    }
}
寫一個字串(常用)
public class OutPutDemo13 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        FileWriter fw = new FileWriter(new File("F:\\itheima\\a.txt"));
        //寫出資料
        String s = "大吉大利,今晚吃雞";
        fw.write(s);
        //釋放資源
        fw.close();
    }
}

注意事項

flush和close
//建立字元輸出流物件
FileWriter fw = new FileWriter(new File("F:\\itheima\\a.txt"));
//寫出資料
String s = "大吉大利,今晚吃雞";
fw.write(s);
//把資料重新整理到本地檔案中
fw.flush();
//釋放資源
fw.close();

使用flush()重新整理資料到本地後,還可以繼續錄入

close()也會重新整理資料到本地,但是就關流了,之後不能再輸入

字元流讀資料

一次讀取一個字元
public class OutPutDemo14 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        FileReader fr = new FileReader(new File("F:\\itheima\\a.txt"));

        //讀資料
        //一次讀取一個字元
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.println((char)ch);
        }

        //釋放資源
        fr.close();
    }
}
一次讀取多個字元
public class OutPutDemo15 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        FileReader fr = new FileReader(new File("F:\\itheima\\a.txt"));

        //讀資料
        //建立一個字元陣列
        //一次讀取多個字元
        char [] chars = new char[1024];
        int len;
        while ((len = fr.read(chars)) != -1) {
            System.out.println(new String(chars, 0, len));
        }

        //釋放資源
        fr.close();
    }
}

小練習

  • 案例需求

    將鍵盤錄入的使用者名稱和密碼儲存到本地實現永久化儲存

  • 實現步驟

    • 獲取使用者輸入的使用者名稱和密碼
    • 將使用者輸入的使用者名稱和密碼寫入到本地檔案中
    • 關流,釋放資源
  • 程式碼實現

public class OutPutDemo16 {
    public static void main(String[] args) throws IOException {
        //需求
        //將鍵盤錄入的使用者名稱和密碼儲存到本地實現永久化儲存

        //分析
        //1.實現鍵盤錄入,把使用者名稱密碼錄入進來

        Scanner sc = new Scanner(System.in);
        System.out.println("請錄入使用者名稱:");
        String username = sc.next();
        System.out.println("請錄入密碼:");
        String password = sc.next();

        //2.分別把使用者名稱密碼寫入到本地
        //建立字元輸出流物件
        FileWriter fw = new FileWriter("F:\\itheima\\b.txt");
        //把使用者名稱密碼寫入到本地
        fw.write(username);
        //表示一個回車換行符
        fw.write("\r\n");
        fw.write(password);
        //重新整理流
        fw.flush();
        //釋放資源
        fw.close();
    }
}

字元緩衝流

  • 字元緩衝流介紹

    • BufferedWriter:將文字寫入字元輸出流,緩衝字元,以提供單個字元,陣列和字串的高效寫入,可以指定緩衝區大小,或者可以接受預設大小。預設值足夠大,可用於大多數用途

    • BufferedReader:從字元輸入流讀取文字,緩衝字元,以提供字元,陣列和行的高效讀取,可以指定緩衝區大小,或者可以使用預設大小。 預設值足夠大,可用於大多數用途

  • 構造方法

    方法名 說明
    BufferedWriter(Writer out) 建立字元緩衝輸出流物件
    BufferedReader(Reader in) 建立字元緩衝輸入流物件
  • 程式碼演示

public class OutPutDemo17 {
    public static void main(String[] args) throws IOException {
        //建立字元輸出流物件
        BufferedReader br = new BufferedReader(new FileReader(new File("F:\\itheima\\a.txt")));

        //讀資料
        //建立一個字元陣列
        //一次讀取多個字元
        char [] chars = new char[1024];
        int len;
        while ((len = br.read(chars)) != -1) {
            System.out.println(new String(chars, 0, len));
        }

        //釋放資源
        br.close();
    }
}
字元緩衝輸出流
public class OutPutDemo18 {
    public static void main(String[] args) throws IOException {
        //字元緩衝輸出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\itheima\\c.txt"));
        //寫出資料
        bw.write(97);
        bw.write(98);
        bw.write(99);
        bw.write(100);
        bw.write("\r\n");
        char [] chars = {
            101,102,103,104,105
        };

        bw.write(chars);
        bw.write("\r\n");
        bw.write(chars,2,2);
        bw.write("\r\n");
        bw.write("大吉大利");
        bw.write("\r\n");

        bw.flush();
        bw.close();
    }
}
字元緩衝流特有功能
  • 方法介紹

    BufferedWriter:

    方法名 說明
    void newLine() 寫一行行分隔符,行分隔符字串由系統屬性定義

    BufferedReader:

    方法名 說明
    String readLine() 讀一行文字。 結果包含行的內容的字串,不包括任何行終止字元如果流的結尾已經到達,則為null
  • 程式碼演示

public class OutPutDemo19 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\itheima\\d.txt"));

        //寫出資料
        bw.write("大吉大利,今晚吃雞");
        bw.newLine();
        bw.write("abcdefg");
        bw.newLine();

        bw.flush();
        bw.close();

    }
}
public class OutPutDemo20 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("F:\\itheima\\d.txt"));

        //讀出資料
        String s = br.readLine();
        String l = br.readLine();
        String r = br.readLine();
        System.out.println(s);
        System.out.println(l);
        System.out.println(r);

        br.close();
    }
}

使用迴圈改進讀取

public class OutPutDemo21 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("F:\\itheima\\d.txt"));

        //讀出資料
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        //釋放資源
        br.close();
    }
}

readline為什麼可以讀取一整行?

可以讀取一整行資料,一直讀直到回車換行為止

但是它不會讀取回車換行符

字元緩衝流操作檔案中資料排序案例

  • 案例需求

    使用字元緩衝流讀取檔案中的資料,排序後再次寫到本地檔案

  • 實現步驟

    • 將檔案中的資料讀取到程式中
    • 對讀取到的資料進行處理
    • 將處理後的資料新增到集合中
    • 對集合中的資料進行排序
    • 將排序後的集合中的資料寫入到檔案中
  • 程式碼實現

public class OutPutDemo22 {
    public static void main(String[] args) throws IOException {
        //1.需要將檔案中的資料讀進來
        BufferedReader br = new BufferedReader(new FileReader("F:\\itheima\\f.txt"));
        //讀出資料
        int [] ints = {};
        String line;
        while ((line = br.readLine()) != null){
            String[] s = line.split(" ");
            //2.排序
            ints = sortList(s);
        }
        System.out.println(Arrays.toString(ints));
        //3.把排序後的結果寫出
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\itheima\\g.txt"));
        bw.write(Arrays.toString(ints));
        //釋放資源
        br.close();
        bw.close();
    }

    //陣列氣泡排序方法
    private static int[] sortList(String[] s) {
        //定義外層迴圈
        int[] ints = StringToInt(s);
        for (int i = 0; i < ints.length - 1; i++) {
            //定義內層迴圈
            for (int j = 0; j < ints.length - i -1; j++) {
                if (ints[j] > ints[j + 1]){
                    int temp = ints[j];
                    ints[j] = ints[j+1];
                    ints[j+1] = temp;
                }
            }
        }
        return ints;
    }
    //String陣列轉為int
    public static int[] StringToInt(String[] arr){
        int[] array = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            array[i] = Integer.parseInt(arr[i]);
        }
        return array;
    }
}

轉換流

  • InputStreamReader:是從位元組流到字元流的橋樑,父類是Reader

    ​ 它讀取位元組,並使用指定的編碼將其解碼為字元

    ​ 它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的預設字符集

  • OutputStreamWriter:是從字元流到位元組流的橋樑,父類是Writer

    ​ 是從字元流到位元組流的橋樑,使用指定的編碼將寫入的字元編碼為位元組

    ​ 它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的預設字符集

轉換流讀寫資料

  • 構造方法

    方法名 說明
    InputStreamReader(InputStream in) 使用預設字元編碼建立InputStreamReader物件
    InputStreamReader(InputStream in,String chatset) 使用指定的字元編碼建立InputStreamReader物件
    OutputStreamWriter(OutputStream out) 使用預設字元編碼建立OutputStreamWriter物件
    OutputStreamWriter(OutputStream out,String charset) 使用指定的字元編碼建立OutputStreamWriter物件
  • 程式碼演示
package com.cloudcore.iotest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

/**
 * @Author: hepeng
 * @Date: 2021/10/18 19:45
 */
public class OutPutDemo23 {
    public static void main(String[] args) throws IOException {
        //會產生亂碼
        method1();
        //如何解決亂碼?
        method2();
        
    }

    private static void method2() throws IOException {
        InputStreamReader is = new InputStreamReader(new FileInputStream("F:\\itheima\\a.txt"),"UTF-8");
        int ch;
        while ((ch = is.read()) != -1){
            System.out.println((char)ch);
        }
        is.close();
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("F:\\itheima\\aa.txt"),"UTF-8");
        out.write("我愛學習誰也別打擾我");
        out.close();
    }

    private static void method1() throws IOException {
        FileReader fr = new FileReader("F:\\itheima\\a.txt");
        int ch;
        while ((ch = fr.read()) != -1){
            System.out.println((char)ch);
        }
        fr.close();
    }
}

物件操作流

物件序列化流

  • 物件序列化介紹

    • 物件序列化:就是將物件儲存到磁碟中,或者在網路中傳輸物件
    • 這種機制就是使用一個位元組序列表示一個物件,該位元組序列包含:物件的型別、物件的資料和物件中儲存的屬性等資訊
    • 位元組序列寫到檔案之後,相當於檔案中持久儲存了一個物件的資訊
    • 反之,該位元組序列還可以從檔案中讀取回來,重構物件,對它進行反序列化
  • 物件序列化流: ObjectOutputStream

    • 將Java物件的原始資料型別和圖形寫入OutputStream。 可以使用ObjectInputStream讀取(重構)物件。 可以通過使用流的檔案來實現物件的持久儲存。 如果流是網路套接字流,則可以在另一個主機上或另一個程序中重構物件
  • 構造方法

    方法名 說明
    ObjectOutputStream(OutputStream out) 建立一個寫入指定的OutputStream的ObjectOutputStream
  • 序列化物件的方法

    方法名 說明
    void writeObject(Object obj) 將指定的物件寫入ObjectOutputStream
  • 示例程式碼

    學生類

public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //ObjectOutputStream(OutputStream out):建立一個寫入指定的OutputStream的ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));

        //建立物件
        Student s = new Student("佟麗婭",30);

        //void writeObject(Object obj):將指定的物件寫入ObjectOutputStream
        oos.writeObject(s);

        //釋放資源
        oos.close();
    }
}

注意事項

  • 一個物件要想被序列化,該物件所屬的類必須必須實現Serializable 介面
  • Serializable是一個標記介面,實現該介面,不需要重寫任何方法

物件反序列化流

  • 物件反序列化流: ObjectInputStream

    • ObjectInputStream反序列化先前使用ObjectOutputStream編寫的原始資料和物件
  • 構造方法

    方法名 說明
    ObjectInputStream(InputStream in) 建立從指定的InputStream讀取的ObjectInputStream
  • 反序列化物件的方法

    方法名 說明
    Object readObject() 從ObjectInputStream讀取一個物件
  • 示例程式碼

public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //ObjectInputStream(InputStream in):建立從指定的InputStream讀取的ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));

        //Object readObject():從ObjectInputStream讀取一個物件
        Object obj = ois.readObject();

        Student s = (Student) obj;
        System.out.println(s.getName() + "," + s.getAge());

        ois.close();
    }
}

serialVersionUID&transient

  • serialVersionUID

    • 用物件序列化流序列化了一個物件後,假如我們修改了物件所屬的類檔案,讀取資料會不會出問題呢?
      • 會出問題,會丟擲InvalidClassException異常
    • 如果出問題了,如何解決呢?
      • 重新序列化
      • 給物件所屬的類加一個serialVersionUID
        • private static final long serialVersionUID = 42L;
  • transient

    • 如果一個物件中的某個成員變數的值不想被序列化,又該如何實現呢?
      • 給該成員變數加transient關鍵字修飾,該關鍵字標記的成員變數不參與序列化過程
  • 示例程式碼

    學生類

public class Student implements Serializable {
    private static final long serialVersionUID = 42L;
    private String name;
//    private int age;
    private transient int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Properties集合

  • Properties介紹

    • 是一個Map體系的集合類
    • Properties可以儲存到流中或從流中載入
    • 屬性列表中的每個鍵及其對應的值都是一個字串
  • Properties基本使用

package com.cloudcore.iotest;

import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * @Author: hepeng
 * @Date: 2021/10/19 0:01
 */
public class properties {
    public static void main(String[] args) {
        Properties prop = new Properties();
        //增
        prop.put("小龍女","尹志平");
        prop.put("郭襄","楊過");
        prop.put("黃蓉","歐陽克");
        System.out.println(prop);
        //刪
        prop.remove("小龍女");
        System.out.println(prop);
        //改
        prop.put("黃蓉","小瀋陽");
        System.out.println(prop);
        //查
        Object value = prop.get("郭襄");
        System.out.println(value);
        //遍歷
        Set<Object> keys = prop.keySet();
        for (Object key : keys) {
            Object o = prop.get(key);
            System.out.println(key + "=" + o);
        }

        Set<Map.Entry<Object, Object>> entries = prop.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            Object key = entry.getKey();
            Object value1 = entry.getValue();
            System.out.println(key + "=" + value1);
        }
    }
}

Properties作為Map集合的特有方法

package com.cloudcore.iotest;

import java.util.Properties;
import java.util.Set;

/**
 * @Author: hepeng
 * @Date: 2021/10/19 0:08
 */
public class propertiesTest {
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.setProperty("山東","濟南");
        prop.setProperty("浙江","杭州");
        prop.setProperty("山西","太原");
        prop.setProperty("安徽","合肥");
        System.out.println(prop);

        String key = prop.getProperty("浙江");
        System.out.println(key);

        Set<String> keys = prop.stringPropertyNames();
        for (String s : keys) {
            Object value = prop.get(s);
            System.out.println(s + "=" + value);
        }
    }
}