Java基礎(chǔ) - IO流

6.IO流

6.1 File

系統(tǒng)中我們一眼看到的就是文件或者文件夾
本質(zhì)是一個路徑(字符串);用字符串來表示這個路徑不符合面向?qū)ο?/p>

File類對路徑的字符串進行面向?qū)ο蟮姆庋b,是文件和文件夾路徑的抽象表現(xiàn)形式

基本操作:

  • 構(gòu)造方法

      File(String pathname) 將給定的路徑名字符串轉(zhuǎn)為抽象路徑名來創(chuàng)建一個File實例
    
      例子:  new File("D:java/testDoc/test.java") //文件路徑
            new File("D:java/testDoc") //文件夾路徑
      
      File(String parent, String child) 根據(jù)父路徑字符串和子路徑字符串創(chuàng)建一個File實
    
      例子:new File("D:java","/testDoc/test.java") //文件
      例子:new File("D:java","/testDoc") //文件夾
    
  • 創(chuàng)建

    • 創(chuàng)建文件夾

        mkdir():創(chuàng)建文件夾
        
        mkdirs():?創(chuàng)建多級文件夾
      
    • 創(chuàng)建文件

        createNewFile():創(chuàng)建文件
      
    • 重命名

        renameTo():給文件或文件夾重命名
      
  • 判斷

      exists():判斷此路徑是否存在
    
      isFile():判斷是否文件
    
      isDirectory():判斷是否文件夾
    
  • 獲取

      getAbsolutePath():獲取絕對路徑,包括根路徑
    
      getName():獲取相對路徑(文件名或者文件夾名).不包括根路徑
    
      length():獲取文件的大小,單位是字節(jié)
    
  • 刪除

      delete():刪除文件
      
      deleteOnExit():在程序退出的時候刪除文件
    
  • 示例代碼:

      //創(chuàng)建File實例對象,路徑的抽象表現(xiàn)
      File file = new File("D:java/testDoc/test.java");
      // File file = new File("D:java/testDoc");
      // File file = new File("D:java","testDoc/test.java");
      //判斷路徑是否存在
      if (!file.exists()){
          //判斷是否是文件路徑
          if (file.isFile()){
              //創(chuàng)建文件
              file.createNewFile();
          }
          //判斷是否是文件夾路徑
          if (file.isDirectory()){
              //創(chuàng)建文件夾
              file.mkdir();
          }
      }
      //獲取絕對路徑
      System.out.println(file.getAbsoluteFile()); // 輸出 /D:java/testDoc/test.java
      //獲取相對路徑(文件名或者文件夾名)
      System.out.println(file.getName()); // 輸出test.java
    

File類的高級獲取

  • 方法:
    listFiles():返回一個File數(shù)組,包括了路徑名下的的所有文件和文件夾路徑名

    listRoots():此方法是靜態(tài)的,返回路徑名下的所有根路徑

    listFiles(FileFilter filter):返回File數(shù)組,數(shù)組是有經(jīng)過過濾器FileFilter篩選的

    FileFilter 重寫的方法: accept(File pathname)  返回true表示需包含在數(shù)組內(nèi),不要去掉
  • 示例代碼1:

      if (file != null && file.isDirectory()) {
          //打印文件夾
          System.out.println(file);
          //列出所有的文件和文件夾路徑
          File[] files = file.listFiles();
          for (File f : files) {
              //遞歸調(diào)用,找出所有的文件 文件夾
              testFileSearch(f);
          }
      } else {
          //打印文件
          System.out.println(file);
      }
    
  • 示例代碼2

      if (file != null && file.isDirectory()) {
          File[] files = file.listFiles(new FileFilter() {
              @Override
              public boolean accept(File file) {
                  //.class結(jié)尾的需要保留,不要去掉
                  return file.getName().endsWith(".class");
              }
          });
      }
    

6.2 IO流基類

  1. 字節(jié)輸入流 InputStream

  2. 字節(jié)輸出流 OutputStream

  3. 字符輸入流 Reader

  4. 字符輸出流 Writer

特點:

  • 四大基類都是抽象類,核心功能一句話總結(jié):讀進來,寫出去

    • 輸出流:將數(shù)據(jù)寫到目標中去

    • 輸入流:從源中讀取數(shù)據(jù)

  • 所有的流都是資源對象,最后使用完都必須關(guān)閉資源

  • 字節(jié)流比較通用

  • IO流的操作模板

      1):定義源或目標  源:輸入流  目標:輸出流
    
      2):根據(jù)源和目標創(chuàng)建流對象
    
      3):進行讀/寫操作
    
      4):關(guān)閉資源
    

6.2.1 字節(jié)流

字節(jié)輸入流  InputStream

字節(jié)輸出流  OutputStream 

字節(jié)文件流

1-1.FileOutputStream

將數(shù)據(jù)寫到目標文件中

  • 構(gòu)造方法

          FileOutputStream(File file) 創(chuàng)建向指定File對象的目標文件中寫入數(shù)據(jù)的文件輸出流 
    
          FileOutputStream(String name) 創(chuàng)建向指定名稱的目標文件中寫入數(shù)據(jù)的文件輸出流
    
          FileOutputStream(String name, boolean append) append 是否在源數(shù)據(jù)中追加
    
  • 常用方法

          write(int b) //將指定數(shù)量的字節(jié)寫到輸入流
    
          write(byte[] b,int off, int len ) 將指定的byte數(shù)組從off索引開始的len個字節(jié)寫到輸出流
    
  • 分析流對象的創(chuàng)建

          1.創(chuàng)建了輸出流對象
    
          2.通知系統(tǒng)去檢查目標文件,如果不存在則創(chuàng)建出來
    
          3.將這個輸出流對象與硬盤上的文件關(guān)聯(lián)起來
    
  • 示例代碼:

          String dest = "d:/java/test.txt"; //輸出的目標文件路徑
          try {
              //創(chuàng)建流對象,如果文件不存在,則會自動創(chuàng)建文件
              FileOutputStream fo = new FileOutputStream(dest);
              byte[] bytes = "hello".getBytes();//需要寫到流的數(shù)據(jù)
              fo.write(bytes,2,3);
              fo.close();//關(guān)閉流,釋放資源,等待GC回收
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          }
    

1-2.FileInputStream

從源文件讀取數(shù)據(jù)

  • 構(gòu)造方法

          FileInputStream(String name)
    
          FileInputStream(File file)   創(chuàng)建從源文件中讀取數(shù)據(jù)的輸入流對象
    
  • 常用方法

          read()  從輸入流中讀取數(shù)據(jù)的下一個字節(jié),
                  返回值是讀取到的字節(jié),如果為-1表示已讀完
    
          read(byte[] b)  從輸入流中讀取數(shù)據(jù)的一定數(shù)量字節(jié),并存儲到緩沖數(shù)組b中.
                          返回值是讀取的字節(jié)個數(shù),如果為-1表示已讀完
    
  • 示例代碼:

          //源
          String path = "d:/java/in.txt";
          //根據(jù)源創(chuàng)建輸入流對象
          try {
              FileInputStream fi = new FileInputStream(path);
              //定義一個緩沖數(shù)組
              byte[] bytes = new byte[1024 * 1024];
              fi.read(bytes);
              int len;//記錄讀取了多少個字節(jié)
              while ((len = fi.read(bytes)) != -1) { //不等于-1 表示還有數(shù)據(jù)
                  System.out.println(new String(bytes, 0, len));
              }
              fi.close();
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          }
    

緩沖流

  • 特點

    緩沖字節(jié)流和普通字節(jié)流在使用上沒有區(qū)別 ,在效率上緩沖流效率更高

  • 為什么會比較效率?

    • 緩沖流對象底層自帶一個8k的緩沖區(qū),這個緩沖區(qū)跟我們輸入流的自定義的緩沖數(shù)組沒有關(guān)系

    • 緩沖流對象的緩沖區(qū)指的是管道的粗細,而自定義的緩沖數(shù)組指的的是讀取到的數(shù)據(jù)儲存的地方

    • 緩沖流將管道加粗了,從而使輸入和輸出更加效率

字節(jié)緩沖流

2-1.BufferedInputStream

  • 構(gòu)造方法

      BufferedInputStream(InputStream in)
    
  • 示例代碼

      FileInputStream in = new FileInputStream("d:/java/test.java");
      BufferedInputStream bufin = new BufferedInputStream(in);
    

2-2.BufferedOutputStream

  • 構(gòu)造方法

      BufferedOutputStream(OutputStream out)
    
  • 示例代碼

      FileOutputStream out = new FileOutputStream("d:/java/test.java");
      BufferedOutputStream bufOut= new BufferedOutputStream(out);
    

對象流

  • 作用

    把內(nèi)存中的對象輸出到文件中或者把文件中保存的對象輸入到內(nèi)存

  • 為什么保存到文件中?

    目的是為了進程之間的數(shù)據(jù)做交流

  • 序列化和反序列化

    序列化:內(nèi)存中的對象寫出到文件

    反序列化:將文件中的對象讀進內(nèi)存

  • 序列化對象

    保存的對象需要經(jīng)過序列化,開啟序列化可以通過實現(xiàn)Serializable接口

    實現(xiàn)Serializable接口需要在對象中顯示聲明序列化ID;不顯式聲明時,會根據(jù)類上的信息產(chǎn)生不同的序列化ID,由于編譯器的不同,可能導(dǎo)致反序列化出現(xiàn)意外

3-1.ObjectOutputStream

ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants

序列化:把內(nèi)存中的對象保存到硬盤中

  • 構(gòu)造方法

      ObjectOutputStream(OutputStream out) 創(chuàng)建寫入指定OutputStream的對象
    
  • 常用方法

      void writeObject(Object obj) 將對象寫到流中
    
  • 示例代碼

      public class ShareData implements Serializable {
    
       private static final long serialVersionUID = -1190188205817401171L;
    
      }
    
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
      ShareData data = new ShareData();
      out.writeObject(data);
      out.close();
    

3-2.ObjectInputStream

ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants

反序列化:將文件中的對象讀取到內(nèi)存中

一個程序去讀取另一個程序序列化的數(shù)據(jù),達到進程通信

  • 構(gòu)造方法

      ObjectInputStream(InputStream in)
    
  • 常用方法

      readObject() 
    
  • 示例代碼

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
      Object object = in.readObject();
      in.close(); 
    

字節(jié)數(shù)組流

4-1.ByteArrayOutputStream

ByteArrayOutputStream extends OutputStream

  • 特點

    會將數(shù)據(jù)寫入到底層緩沖區(qū)的byte數(shù)組,緩沖區(qū)會隨著數(shù)據(jù)的不斷寫入而自動增長

  • 使用場景:

    在需要接收大量是數(shù)據(jù)時,有些數(shù)據(jù)不適合一次性全部接收,我們可以使用每次收集1小部分的形式,拿到零散的數(shù)據(jù),再將零散的數(shù)據(jù)統(tǒng)一收集起來,最后統(tǒng)一使用,此時就要用到這個ByteArrayOutputStream

  • 構(gòu)造方法

      ByteArrayOutputStream()
    
  • 常用方法

      byte[] toByteArray() //將緩沖數(shù)組的數(shù)據(jù)放到一個新的數(shù)組
    
      String toString()  用默認字符集將緩沖區(qū)數(shù)據(jù)解碼成字符串
    
      String toString(String charsetName)  用指定字符集將緩沖區(qū)數(shù)據(jù)解碼成字符串
    
      void write(byte[] b, int off, int len)  將數(shù)組b寫到流中
    
  • 示例代碼

      ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
      //模擬每次有一部分數(shù)據(jù)過來
      //這個方法就是將零散的數(shù)據(jù)先暫時保存起來
      byteOut.write(new byte[]{'a', 'b', 'c'});
      byteOut.write(new byte[]{'d', 'e', 'e'});
      byteOut.write(new byte[]{100, 127, 32});
    
      byte[] bytes = byteOut.toByteArray();//將保存的零散數(shù)據(jù)使用起來
      System.out.println(new String(bytes));
      System.out.println(byteOut.toString());//解碼流的數(shù)據(jù)為字符串
    

4-2.ByteArrayIntputStream

ByteArrayInputStream extends InputStream

  • 特點

    包含一個內(nèi)部緩沖區(qū),該緩沖區(qū)包含從流中讀取的字節(jié)

    關(guān)閉 ByteArrayIntputStream無效,其方法在關(guān)閉后仍可被調(diào)用,而不會產(chǎn)生IOException

  • 構(gòu)造方法

      ByteArrayInputStream(byte[] buf) 創(chuàng)建一個流對象,使用buf作為其緩沖區(qū)數(shù)組
    
  • 示例代碼

      byte[] bs = new byte[]{9,98,100};//把字節(jié)數(shù)組轉(zhuǎn)成流對象
      ByteArrayInputStream byteIn = new ByteArrayInputStream(bs);
      byte[] buf = new byte[1024];
      int len;
      while ((len = byteIn.read(buf)) != -1){
          System.out.println(new String(buf,0,len));
      }
    

6.2.2 字符流

字符輸入流  Reader

字符輸出流  Writer
  • 為什么使用字符流

    使用字節(jié)流讀取文件可能會出現(xiàn)亂碼的情況,因為字節(jié)流是一次只讀取一個字節(jié),而有些數(shù)據(jù)不是一個字節(jié)構(gòu)成,如漢字占兩個字節(jié)或3個字節(jié),在解析的時候不知道用幾個字節(jié)去解析,因此容易出現(xiàn)亂碼.

  • 字符流工作過程

    • 字符流底層有一個1kb大小的緩沖區(qū),讀寫都是跟緩沖區(qū)有關(guān)的

    • 字符輸入流的緩沖區(qū)的作用:用于讀取數(shù)據(jù)后解析數(shù)據(jù),如果解析成功就會存入緩沖數(shù)組中;如果解析失敗,則會再讀一個數(shù)據(jù)一起解析;如果要解析的字節(jié)在編碼表中找不到對應(yīng)的就會轉(zhuǎn)成問號!

    • 字符輸出流的緩沖區(qū)作用: 先寫入數(shù)據(jù)到緩沖區(qū),然后調(diào)用flush()方法將數(shù)據(jù)從緩沖數(shù)組中寫到文件中,或者緩沖數(shù)組滿了也會寫出去

1-1. FileReader

FileReader extends InputStreamReader

擅長從文件讀取字符的類

  • 構(gòu)造方法

      FileReader(String fileName)
    
  • 常用方法

      int read() 每次讀取一個字符
      
      int read(char[] cbuf) 將字符讀入緩沖數(shù)組中
    
  • 示例代碼

      String path = "d:/java/test.txt";
      try {
          FileReader fr = new FileReader(path);
          char[] chrs = new char[3];//讀取多少個字符到緩沖數(shù)組
          int len;//記錄讀取了多少個字符
          while ((len = fr.read(chrs)) != -1) {
              String s = new String(chrs, 0, len);
              System.out.println(s);
          }
          fr.close();
      } catch (FileNotFoundException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }
    

1-2.FileWriter

FileWriter extends OutputStreamWriter

擅長寫出字符到文件的類

  • 構(gòu)造方法

      FileWriter(String fileName)
    
  • 常用方法

      void write(String str) 將字符串寫出到文件
    
      flush() 將緩沖的數(shù)據(jù)寫出到文件 ,在關(guān)閉流之前調(diào)用
    
  • 注意事項

    字符流底層存在一個緩沖數(shù)組,調(diào)用write方法時,會將數(shù)據(jù)臨時保存在緩沖數(shù)組中,當緩沖數(shù)組存滿后,會自動把數(shù)組中的數(shù)據(jù)真正寫到文件中.我們可以手動調(diào)用flush()方法,刷新緩存區(qū),讓數(shù)據(jù)寫到文件

  • 示例代碼

      String dest = "d:/java/write.txt";
      try {
          FileWriter fw = new FileWriter(dest);
          String needData = "hossss";
          fw.write(needData);
          //刷新數(shù)據(jù)
          fw.flush();
          fw.close();
      } catch (IOException e) {
          e.printStackTrace();
      }
    

轉(zhuǎn)換字符流

特點:

  • 將字節(jié)流轉(zhuǎn)換成字符流

為什么要轉(zhuǎn)換?

  1. 字節(jié)流是基本流,一般流對象都設(shè)計成字節(jié)流,比較通用

  2. 有時流對象并不是我們自己創(chuàng)建的,而是別的地方返回的,而返回的一般是字節(jié)流,如果字節(jié)流用來處理文本數(shù)據(jù)可能會出現(xiàn)亂碼,所以必須將字節(jié)流轉(zhuǎn)成字符流

2-1.InputStreamReader

轉(zhuǎn)換輸入流

  • 構(gòu)造方法

      InputStreamReader(InputStream in)
    
      InputStreamReader(InputStream in, String charsetName)  指定字符集讀取字節(jié)并解碼為字符
    
  • 示例代碼

      FileInputStream in = new FileInputStream("d:/java/test.java");
      InputStreamReader reader = new InputStreamReader(in, "UTF-8");
      char[] chars = new char[1024];
      int len;
      while ((len = reader.read(chars)) != -1){
          System.out.println(new String(chars,0,len));
      }
      reader.close();
    

2-2.OutputStreamWriter

轉(zhuǎn)換輸出流

  • 構(gòu)造方法

      OutputStreamWriter(OutputStream out)
    
      OutputStreamWriter(OutputStream out, String charsetName) 指定字符集將字符編碼成字節(jié)寫到流中
    
  • 示例代碼

      FileOutputStream out = new FileOutputStream("d:/java/test.java");
      OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8");
      writer.write("你好啊");
      writer.close();//轉(zhuǎn)換流的close包含了刷新數(shù)據(jù),關(guān)閉資源操作
    

字符緩沖流

3-1.BufferedReader

  • 構(gòu)造方法

      BufferedReader(Reader in)   
    
  • 特有方法

      String readLine()  讀取一行文本
    
  • 示例代碼

      BufferedReader reader =new BufferedReader(new FileReader("d:/java/test2.java"));
      String data; //記錄讀取到的內(nèi)容
      while ((data = reader.readLine()) != null){
          System.out.println(data);
      }
      reader.close();
    

3-2.BufferedWriter

  • 構(gòu)造方法

      BufferedWriter(Writer out)
    
  • 特有方法

      void newLine()  寫入一個行分隔符(換行)
    
  • 示例代碼

      BufferedWriter writer = new BufferedWriter(new FileWriter("d:/java/test.java"));
      writer.write("哈哈");
      writer.newLine();//換行
      writer.write("我是哈哈");
      writer.flush();
      writer.close();
    

6.3 文件拷貝

  • 字節(jié)流拷貝

    字節(jié)流可以讀寫文本文件和二進制文件

      //需求:將test1.java的內(nèi)容拷貝到test2.java
      FileInputStream in = new FileInputStream("d:/java/test1.java");
      FileOutputStream out = new FileOutputStream("d:/java/test2.java");
      byte[] bytes = new byte[1024];
      int len;
      while ((len = in.read(bytes)) != -1) {
          //將讀取到的數(shù)據(jù)寫出去,邊讀邊寫
          out.write(bytes, 0, len);
      }
      in.close();
      out.close();
    
  • 字符流拷貝

    字符流只能拷貝純文本文件,拷貝二進制文件肯定是打不開的

    拷貝二進制文件的問題:

    讀取回來的字節(jié)數(shù)據(jù)在轉(zhuǎn)換成字符的過程中,發(fā)現(xiàn)找不到對應(yīng)的字符和它對應(yīng),而轉(zhuǎn)成了?(63)只有一個字節(jié),所以寫出去的就丟失了字節(jié),最終導(dǎo)致拷貝的數(shù)據(jù)變少了

      //需求:將test1.java的內(nèi)容拷貝到test2.java
       FileReader reader = new FileReader("d:/java/test1.java");
       FileWriter writer = new FileWriter("d:/java/test2.java");
       char[] chars = new char[1024];
       int len;
       while ((len = reader.read(chars)) != -1) {
           writer.write(chars, 0, len);
           writer.flush();
       }
       reader.close();
       writer.close();
    

6.4 IO流異常處理

  • 異常處理的核心:

    • 所有的編譯時期異常必須try-catch

    • 保證流對象得到關(guān)閉

  • 異常一般處理示例代碼

      FileReader reader = null;
      FileWriter writer = null;
      try {
          reader = new FileReader("d:/java/test1.java");
          writer = new FileWriter("d:/java/test2.java");
          //需求:將test1.java的內(nèi)容拷貝到test2.java
          char[] chars = new char[1024];
          int len;
          while ((len = reader.read(chars)) != -1) {
              writer.write(chars, 0, len);
              writer.flush();
          }
      } catch (Exception e) {
          e.printStackTrace();
      }finally {
          if (reader != null){
              try {
                  reader.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }finally {
                  if (writer != null){
                      try {
                          writer.close();
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
    

從上面的代碼可以看出處理異常的代碼邏輯比IO操作還多,結(jié)構(gòu)嵌套很深

  • 異常高級處理

    • try-with-resource

      • java1.7開始出現(xiàn)的跟資源有關(guān)的

      • 相關(guān)的對象需要實現(xiàn)AutoCloseable接口,流對象都實現(xiàn)了此接口

      • 應(yīng)用了此語法的流對象不用關(guān)閉資源,會自動關(guān)閉

      • 這個語法只能在Java7或者更高的版本使用

    • 語法

        try (
                ...
                創(chuàng)建AutoCloseable對象的代碼
                ...
        ) {
              可能出現(xiàn)異常的代碼
        } catch (異常類型  變量名) {
        }
      
    • 示例代碼

         try (
            //創(chuàng)建資源對象的代碼放在這里
            FileReader reader = new FileReader("d:/java/test1.java");
            FileWriter writer = new FileWriter("d:/java/test2.java");
        ) {
            char[] chars = new char[1024];
            int len;
            while ((len = reader.read(chars)) != -1) {
                writer.write(chars, 0, len);
                writer.flush();
            }
            //不用關(guān)閉資源
            //reader.close();
            //writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
      

6.5 字符的編碼和解碼

  1. 編碼表

    所謂編碼表就是用一個整數(shù)去對應(yīng)一個字符

    如: ASCII編碼表字符's' s --> 10 -->0000 1010(二進制)

    • ASCII
    - 是用**一個 8 位的字節(jié)**來表示空格、標點符號、數(shù)字、大小寫字母或者控制字符的,其中最高位為 "0",其他位可以自由組合成 128 個字符的碼表

    - **ASCII的漢字是1個字節(jié)**

- IOS-8859-1

    是國際標準化組織 ISO 字符編碼標準 ISO-8859 的一部分,它在 ASCII 編碼空置的 0xA0-0xFF 的范圍內(nèi)加入了其他符號字母以供西歐來使用,所以也叫 "西歐語言",另外 ISO 的編碼還有其他的一些語言編碼,這些都是**單字節(jié) 8 位編碼**。

- GB*
    
    - GB2312 共收錄了七千個字符,由于 GB2312 支持的漢字太少而且不支持繁體中文,所以 GBK 對 GB2312 進行了擴展,對低字節(jié)不再做大于 127 的規(guī)定,以支持繁體中文和更多的字符,GBK 共支持大概 22000 個字符,GB18030 是在 GBK 的基礎(chǔ)上又增加了藏文、蒙文、維吾爾文等主要的少數(shù)民族文字。

    - **GBK的漢字是2個字節(jié)**

- Unicode

    - 一個全球性的編碼方案把所有字母和符號都統(tǒng)一編碼進去

    - UTF-8以字節(jié)為單位對Unicode進行編碼

    - **UTF-8的漢字是3個字節(jié)**
  1. 編碼和解碼

    編碼和解碼都必須依靠一個工具作為橋梁,這個工具就是編碼表

    • 編碼: 把字符變成字節(jié)(整數(shù))

      String類的編碼方法:

        byte[] getBytes() 使用平臺默認字符集(一般默認GBK)將String編碼為byte,并存到byte數(shù)組中
      
        byte[] getBytes(String charsetName) 使用指定字符集將String編碼為byte,并存到byte數(shù)組中
      
    • 解碼: 把字節(jié)(整數(shù))變成字符

      String類的解碼方法:

        String(byte[] bytes) 使用默認字符集將字節(jié)數(shù)組解碼成一個String對象
      
        String(byte[] bytes,String charsetName) 使用指定字符集將字節(jié)數(shù)組解碼成一個String對象
      
    • 編碼和解碼的字符集必須一致,不然在多個字節(jié)的數(shù)據(jù)中,會出現(xiàn)亂碼

    • 示例代碼

        String str = "你好啊";
        byte[] bytes = str.getBytes();//使用默認字符集GBK進行編碼
        String s = new String(bytes); //使用默認字符集GBK進行解碼
      
        //編碼和解碼的字符集必須一致
        byte[] bUtf =  str.getBytes("UTF-8");//使用UTF-8編碼
        String sUtf = new String(bUtf,"UTF-8");//使用UTF-8解碼
      

6.6 屬性文件 properties

  • 使用背景

    一般來說,一些簡單的改動都需要經(jīng)過修改源碼-編譯-運行,這樣拓展不強,不好維護,靈活性不夠.

    我們可以把一些程序中的變量提取出來,放在java代碼的外部,用一個文件保存,這個文件是不需要編譯的,在程序運行的時候再去動態(tài)的讀取這些變量信息.

  • 實際應(yīng)用

    在項目中使用屬性文件,文件必須以.properties結(jié)尾,在程序運行時用流去讀取信息,Java中專門去讀取屬性文件并解析的類Properties

  • Properties

    Properties extends Hashtable<Object, Object>

    • Properties 可以從流中加載數(shù)據(jù)或者將數(shù)據(jù)保存在流中,屬性列表中的鍵值都是字符串

    • 構(gòu)造方法

        Properties()
      
    • 常用方法

        void load(Reader reader) 從輸入字符流中讀取屬性鍵值對
      
        String getProperty(String key) 獲得指定鍵的屬性值
      
    • 屬性文件的寫法

        src=e:/qq.exe
        dest=d:/java/test.java
      
    • 示例代碼

        Properties properties = new Properties();
        FileReader reader =new FileReader("local.properties");
        //從流中加載屬性文件
        properties.load(reader);
      
        //根據(jù)屬性鍵獲得屬性值
        String src = properties.getProperty("src");
        String dest = properties.getProperty("dest");
      

6.7 RandomAccessFile

RandomAccessFile implements DataOutput, DataInput, Closeable

支持對隨機訪問文件的讀取和寫入

  • 特征:

    1. 可以讀也可以寫

    2. 底層是byte[]

    3. 包含一個索引叫文件指針

    4. 發(fā)送讀或?qū)懖僮骱笪募羔槙耙苿?/p>

  • 構(gòu)造方法

      RandomAccessFile(String name, String mode)
    
      RandomAccessFile(File file, String mode)
    
      mode參數(shù):
    
          r:表示只支持讀,調(diào)用write方法會拋出異常
          rw:表示支持讀寫操作,如文件不存在,則會嘗試創(chuàng)建文件
    
  • 常用方法

      long getFilePointer() 獲得當前指針索引
    
      seek(long offset) 設(shè)置指針位置
    
  • 示例代碼

      //創(chuàng)建讀寫的流對象
      RandomAccessFile rw = new RandomAccessFile("d:/java/test.txt", "rw");
      rw.writeInt(100);
      rw.writeChar(98);
      long index = rw.getFilePointer();//獲得指針索引
      //進行讀操作前,需要先將指針回到開始位置,因為之前進行寫操作,指針已移動至當前寫的位置
      rw.seek(0);
      int a = rw.readInt();
      char c = rw.readChar();
      rw.close();
    
  • 實際運用

    可用于斷點下載

    操作步驟:

    1. 先獲取到要下載的文件的大小
    2. 使用一個隨機讀寫文件記錄下載的最新位置
    3. 使用兩個隨機讀取文件對要下載的文件進行關(guān)聯(lián),一個負責(zé)讀,一個負責(zé)寫
    4. 每次操作都記錄下文件的最新位置并且存入硬盤
    5. 發(fā)送斷點后,讀取最新的記錄,從最新的歷史記錄繼續(xù)讀取

6.8 正則表達式

  • 使用場景

    使用正確的規(guī)則對字符串進行相關(guān)操作(匹配/替換/切割)

  • 基本字符

      x       字符x
    
      \\      反斜線字符
    
  • 字符類(多個中匹配1個)

      [abc]           a b 或c
    
      [^abc]          任何字符,除了a,b或c
    
      [a-zA-Z]            a到z,或   A到Z,兩頭的字母包含在內(nèi)
    
      [a-d[m-p]]      a到d,或者m到p:[a-dm-p](并集)
    
      [a-z&&[def]]        d,e或者f(交集)
    
  • 特殊意義字符(類似關(guān)鍵字)

      .           任何字符(與行結(jié)束符可能匹配也可能不匹配)
    
      \d          數(shù)字:[0-9]
    
      \D          非數(shù)字:[^0-9]
    
      \s          空白字符:[\t\n\x0B\f\r]
    
      \S          非空白字符:[^\s]
    
      \w          單詞字符:[a-zA-Z_0-9]
    
      \W          非單詞字符:[^\w]
    
  • 數(shù)量詞

      X?          X, 一次或者一次也沒有, <=1
    
      X*          X, 零次或者多次, >=0
    
      X+          X, 一次或多次, >=1
    
      X{n}        X, 恰好n次, =n
    
      X{n,}       X, 至少n次, >=n
    
      X{n,m}      X, 至少n次,但不超過m次, >=n <=m
    
  • 字符串正則的常用方法

      boolean matches(String regex)  判斷此字符串是否匹配給定的正則表達式
    
      String[] split(String regex) 根據(jù)給定的正則拆分字符串
    
      String replaceAll(String regex,String replacement) 用指定的字符串替換所有匹配正則的內(nèi)容
    
  • 正則中需要注意的

      匹配文本中含有的正則特殊字符: \\d , \\[ , \\{ , \\S
    
      匹配文本的一個反斜杠: \\\\
    
      匹配文本中的\r\n制表符時: \r\n
    
  • 示例代碼

      //1開頭,11位數(shù)字,第二個數(shù)字必須為3 5 7
      String tel = "13788888843";
      String regex1 = "1[357]\\d{9}";
      boolean ma = tel.matches(regex1);
      System.out.println(ma);
    
      String exe = "png-jpg;gif-jpeg";
      String regex2 = "[-;]";
      String[] split = exe.split(regex2);
      for (String s : split) {
          System.out.println(s);
      }
    
      String str = "你個S B";
      String regex3 = "S.*B";
      System.out.println(str.replaceAll(regex3,"*")); 
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 五、IO流 1、IO流概述 (1)用來處理設(shè)備(硬盤,控制臺,內(nèi)存)間的數(shù)據(jù)。(2)java中對數(shù)據(jù)的操作都是通過...
    佘大將軍閱讀 584評論 0 0
  • 一、基礎(chǔ)知識:1、JVM、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機...
    殺小賊閱讀 2,559評論 0 4
  • 1、IO流 1.1、概述 之前學(xué)習(xí)的File類它只能操作文件或文件夾,并不能去操作文件中的數(shù)據(jù)。真正保存數(shù)據(jù)的是文...
    Villain丶Cc閱讀 2,781評論 0 5
  • 啟動第一步--加載BIOS 當你打開計算機電源,計算機會首先加載BIOS信息,BIOS信息是如此的重要,以至于計算...
    石樂志的LK閱讀 276評論 0 0
  • “藝術(shù)能幫助你逃離現(xiàn)實、表達政治觀點或個人主張,可以幫助你思考,增強感知力,質(zhì)疑世界,講述故事,留存并保持記憶的鮮...
    大貓兒_Skyfire閱讀 768評論 0 1

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