Java IO學習總結

File

一.概念

java.io
    將字符串形式的路徑,封裝成File類,File類提供了大量的直接操作文件和文件夾的方法。

二.File的靜態常量

static String pathseparator
    與系統有關的路徑分隔符
    返回“;”--------路徑和路徑用“;”隔開 (比如環境變量)

static String separator
    與系統有關的默認名稱分隔符
    返回“\”--------文件名和文件名用“\”隔開

將來開發要求我們寫的代碼要跨平臺
Windows上的路徑名稱分隔符是 \\
Linux上的路徑名稱分隔符是 /

String path = "G:\\idea\\io";//如果這樣寫,到Linux系統上直接就廢廢了

String path = “G:”+File.separator+"idea"+File.separator+"io";//這纔是標準寫法!

三.構造方法

File(File parent, String child)
    根據 parent 抽象路徑名和 child 路徑名字符串創建一個新 File 實例。

File(String pathname)
    通過將給定路徑名字符串轉換爲抽象路徑名來創建一個新 File 實例。

File(String parent, String child)
    根據 parent 路徑名字符串和 child 路徑名字符串創建一個新 File 實例。

四.獲取File

File getAbsoluteFile()
    返回此抽象路徑名的絕對路徑名形式。

String getPath()
    將此抽象路徑名轉換爲一個路徑名字符串。

String getName()
    返回由此抽象路徑名錶示的文件或目錄的名稱。

long length()
    返回由此抽象路徑名錶示的文件的長度。

File getParentFile()
    返回此抽象路徑名父目錄的抽象路徑名;如果此路徑名沒有指定父目錄,則返回 null。

五.相對路徑和絕對路徑

    絕對路徑:
        從盤符開始寫

    相對路徑:
        都有一個參照,相對於那個路徑,那個路徑就是參照
idea中文件的路徑都是以我們項目(project)的根路徑爲參照的(哪個路徑作爲參照路徑,哪個路徑就可以不寫)
        idea中寫相對路徑:從模塊開始寫

六.File的創建方法

boolean createNewFile()
    當且僅當具有該名稱的文件尚不存在時,創建一個新的空文件。

boolean mkdir()
    創建單級文件夾

boolean mkdirs()
    創建多級文件夾

七.File類的刪除方法

public boolean delete():
    刪除由此File表示的文件或者文件夾

 結論:不要隨意使用
      1.刪除文件夾的時候,只能刪除空文件夾
      2.此方法刪除之後,不走回收站

八.File類的判斷方法

public boolean exists()
    判斷我們指定的文件或者文件夾是否存在的
    如果不存在,返回值false
    如果存在,返回的是true

public boolean isDirectory()
    判斷是否爲文件夾
    如果不是,返回false
    如果是,返回true

public boolean isFile():
    判斷是否爲文件
    如果不是,返回false
    如果是,返回true

九.File的遍歷方法

public String[] list():
    獲取指定文件夾路徑下的文件夾以及文件的名字(路徑)

public File[] listFiles():
    獲取指定文件夾路徑下的文件夾以及文件路徑,把他們封裝成File對象


IO

一.分類

字節流:一切皆字節(圖片/音樂/視頻/文字)
    字節輸出流:OutputStream
    字節輸入流:InputStream
字符流:操作字符的(主要操作的是保存在文本文檔中的內容比如.txt .html .css等)
    字符輸出流:Writer
    字符輸入流:Reader

二.字節流

字節輸出流

因爲是抽象類所以我們直接操作他的子類FileOutputStream
1.構造
參數指定我們數據寫到哪個位置
我們自定義的文件即使沒有,自動創建,如果已經存在,在創建,會把先創建的文件覆蓋掉。

  • FileOutputStream(File file)
  • FileOutputStream(String name)

2.所有的流通用的寫法
1.創建對象
2.寫數據或讀取數據
3.關流–>close()

3.方法

  • void write(int b)->一次寫一個字節
  • void write(byte[] b)->一次寫一個字節數組
  • void write(byte[] b, int off, int len)->一次寫一個字節數組一部分
                byte[] b:要寫哪個字節數組中的內容
                off:從數組的哪個索引開始寫
                len:寫多少個
  • void close()->關閉流對象

    當我們想要利用字節流隨意的往文件裏寫字符,但是又不知道該字符對應的ASCII碼錶對應的數字,那麼我們可以用下面這個方法
“要寫到文件的字符串”.getbytes();---->將字符串轉化爲字節數組。

4.FileOutputStream的續寫功能

  • FileOutputStream(String name,boolean append)
    append:默認false(不追加內容)
                        true(追加內容)

5.換行符:
windows:\r\n
Linux : \n
但是這樣換行也不能實現跨平臺

字節輸入流

    因爲是抽象類所以我們直接操作他的子類FileInputStream

1.構造
參數傳遞要讀取的文件位置

  • FileInputStream(File file)
  • FileInputStream(String name)

2.方法

  • int read():讀一個字節
  • int read(byte[] b):讀取一個字節數組
  • int read(byte[] b, int off, int len):讀一節字節數組
                b:要讀取的字節數組
                off:從哪個索引開始讀
                len:讀多少個
  • void close():關閉資源

3.循環讀取一個字節
我們在對應的.txt文件中存入abc三個字符

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day15\\a.txt");

        int read1 = fis.read();
        System.out.println(read1);

        int read2 = fis.read();
        System.out.println(read2);

        int read3 = fis.read();
        System.out.println(read3);

        int read4 = fis.read();
        System.out.println(read4);
    }

運行結果
通過以下代碼運行結果我們可以看到,當調用了4個讀取一個字節的方法時,最後以獲取到的是-1,至於爲什麼返回的負一,這個不得而知,因爲這方法的底層是native方法,c語言寫的本地方法。
這只是有3個字符,當有很多個字符一個一個的寫顯然不怎麼樣!那麼竟然讀不到數據返回-1,我們可以利用這個條件作爲循環條件來讀。

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day15\\a.txt");

        int len = 0;
        //如果讀不到數據了len = fis.read()這是len的值就是-1,就會停止循環
        while ((len = fis.read())!= -1){
            System.out.println(len);
        }
    }

4.讀取字節數組的問題
我們依舊在對應的.txt文件中存入abc三個字符

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day15\\a.txt");

        byte[] b = new byte[2];
        
        int len = 0;
        while ((len =fis.read(b)) != -1){
            System.out.println(new String(b));
        }

    }

結果
打印結果不盡人意,爲什麼會出現這個問題呢。
圖解
5.循環讀取字節數組正確姿勢

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day15\\a.txt");

        byte[] b = new byte[2];

        int len = 0;
        while ((len =fis.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }

        fis.close();
    }

二.字符流

    當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是因爲一箇中文字符可能佔用多個字節存儲。所以Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。

字節流讀取中文問題演示在a.txt文件中存入字符串"張三")

public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("day16\\a.txt");

        byte[] b = new byte[2];
        int len = 0;

        while ((len = fis.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
    }

運行結果
結果
出現亂碼的原因
    idea使用的編碼格式是utf-8,一箇中文佔三個字節。使用一次讀取一個字節數組的方法,一次只讀了兩個字節,兩個字節構不成一個漢字,所以出現亂碼。

字符輸入流

使用起來與字節流差別不大無非就是把byte數組改爲char數組了
1.構造:
創建對象,指定要操作的文件路徑

  • FileReader(File file)
  • FileReader(String fileName)

2.方法:

  • int read()->第一讀取一個字符,返回值int
  • int read(char[] cbuf)->一次讀取一個字符數組
  • int read(char[] cbuf, int off, int len)->一次讀取一個字符數組一部分
                cbuf:要讀取的字符數組
                off:從字符數組的哪個索引開始讀取
                len:讀多少個
  • void close()->關流

完美解決亂碼問題:因爲這個是每次讀取一個字符!

public static void main(String[] args) throws Exception{
        FileReader fr = new FileReader("day16\\a.txt");

        char[] c = new char[2];
        int len = 0;

        while ((len = fr.read(c)) != -1){
            System.out.println(new String(c,0,len));
        }
    }

運行結果
在這裏插入圖片描述

字符輸出流

字符輸出流自帶一個緩衝區
因爲是抽象類所以我們直接操作他的子類FileWriter
1.構造
參數指定我們數據寫到哪個位置
我們自定義的文件即使沒有,自動創建,如果已經存在,在創建,會把先創建的文件覆蓋掉。

  • FileWriter(File file)
  • FileWriter(String name)

3.方法

  • void write(int c)->一次寫一個字符
  • void write(char[] c)->一次寫一個字符數組
  • void write(char[] c, int off, int len)->一次寫一個字符數組一部分
                char[] c:要寫哪個字符數組中的內容
                off:從數組的哪個索引開始寫
                len:寫多少個
  • void write(String str)->一次寫一個字符串

    因爲內置緩衝區的原因,如果不關閉輸出流,無法寫出字符到文件中。
    如果關閉流對象,是無法繼續寫出數據的。如果我們既想寫出數據,又想繼續使用流,就需要flush 方法。

  • void flush()->刷新緩衝區。如果不刷新緩衝區
  • void close()->刷新緩衝區,並關閉流對象

4.FileWriter的續寫功能

  • FileWriter(String name,boolean append)
    append:默認false(不追加內容)
                        true(追加內容)

三.io異常處理

    平常練習,我們一直把異常拋出,而實際開發中並不能這樣處理,建議使用 try…catch…finally 代
碼塊,處理異常部分,代碼使用演示:

public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw  = new FileWriter("day16\\a.txt");
            fw.write("李四");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fw != null){
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    還可以使用JDK7優化後的 try-with-resource 語句,該語句確保了每個資源在語句結束時關閉。所謂的資源(resource)是指在程序完成後,必須關閉的對象。

public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("day16\\a.txt");){
            fw.write("張三");
        }catch (IOException e){
            e.printStackTrace();
        }
   }

Properties屬性集

特點

  • 數據結構是哈希表,無序
  • 線程安全
  • 不允許出現null值,null鍵
  • new對象的時候不用指定泛型,作爲雙列集合,key和value類型都是String
  • 可以和IO流結合使用,從流中將數據加載到集合中

構造方法

  • public Properties() :創建一個空的屬性列表

基本的存儲方法

  • public Object setProperty(String key, String value) : 保存一對屬性。
  • public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。
  • public Set< String > stringPropertyNames() :把所有鍵存到set集合中。

與流相關的方法

  • void load(輸入流對象)

演示

por.Properties文件內容
在這裏插入圖片描述

public static void main(String[] args)throws Exception {
        //創建Properties集合
        Properties properties = new Properties();

        //創建字節輸入流
        FileInputStream fis = new FileInputStream("day16\\pro.properties");

        //調用load方法,加載流中的信息,將信息加載到Properties集合中

        properties.load(fis);

        System.out.println(properties);

        System.out.println("========根據key獲取value=========");

        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        System.out.println(username+"="+password);

    }

ResourceBundle工具類

java.util.ResourceBundle:工具類
    作用:
        可以簡化使用Properties集合中load方法讀取文件

        ResourceBundle它是一個抽象類,無法直接創建對象,我們可以使用靜態方法獲取ResourceBundle的子類對象
        static ResourceBundle getBundle(String baseName)
        參數:String baseName:傳遞以.properties文件的名稱 prop.properties==>prop

    注意:.properties文件必須放在當前模塊的src下邊

一.ResourceBundle對象的創建

public class Demo01ResourceBundle {
    public static void main(String[] args) {
        //getBundle方法返回的是ResourceBundle的子類對象  
        //ResourceBundle(父類) 變量 = PropertyResourceBundle(子類對象)
        //多態
        ResourceBundle prop = ResourceBundle.getBundle("pro");
        System.out.println(prop);//java.util.PropertyResourceBundle@74a14482
    }
}

二.ResourceBundle類的getString方法

    ResourceBundle類中提供了一個方法getString,用於讀取配置文件
        String getString(String key)  根據key讀取配置文件中的value值
    注意:
    	文件一定要在src目錄下
        使用ResourceBundle讀取配置文件的時候,key不能是中文,不支持,會拋出異常
        使用ResourceBundle讀取配置文件的時候,value可以使用中文,但是讀取出來會出現亂碼
public class Demo02ResourceBundle {
    public static void main(String[] args) {
        //獲取ResourceBundle對象
        ResourceBundle bundle = ResourceBundle.getBundle("pro");
        //使用ResourceBundle對象中的方法getString,根據key獲取value值
        String v1 = bundle.getString("tangyan");
        System.out.println("v1:"+v1);
        System.out.println("----------------------------------");
        ResourceBundle bundle2 = ResourceBundle.getBundle("data");
        String username = bundle2.getString("username");
        System.out.println(username);
        String password = bundle2.getString("password");
        System.out.println(password);
    }
}

緩衝流

字節緩衝流

BufferedOutputStream exends OutputStream:字節緩衝輸出流->提高寫的效率
BufferedInputStream exends InputStream:字節緩衝輸入流->提高讀的效率

1.構造:

  • public BufferedInputStream(InputStream in) :創建一個 新的緩衝輸入流。
  • public BufferedOutputStream(OutputStream out) : 創建一個新的緩衝輸出流。

2.方法:
     和字節流方法一毛一樣

字符緩衝流

BufferedWriter extends Writer:字符緩衝輸出流->提高寫的效率

1.構造:

  • BufferedWriter(Writer out)->由於Writer是抽象類,使用要使用它的子類(FileWriter)

2.特有方法:

  • void newLine()->BufferedWriter中特有方法,換行

BufferedReader extends Reader->提高讀的效率

1.構造:

  • BufferedReader(Reader r)->Reader是抽象類,不能直接new對象,需要傳遞Reader的子類(FileReader)

2.特有方法:

  • String readLine() ->一次讀取一行

轉換流

    當我們使用字符輸入流對本地上的文件進行讀取的時候,可能會出現亂碼的問題,那是因爲:在Idea中的編碼是utf-8(一箇中文佔3個字節)但是Windows系統默認編碼是GBK(一箇中文佔兩個字節)編碼。那麼這個問題我們就可以使用轉換流來解決!

InputStreamReader extends Reader:轉換流->讀數據

1.概述:

  • InputStreamReader 是字節流通向字符流的橋樑:
                它使用指定的 charset 讀取字節並將其解碼爲字符

2.構造方法:

  • InputStreamReader(InputStream in, String charsetName)
                 in:傳遞的是字節輸入流對象->InputStream的子類
                charseName:指定什麼編碼去讀數據->不區分大小寫
                如果不指定編碼,默認UTF-8

OutputStreamWriter extends Writer:轉換流->寫數據

1.概述:

  • OutputStreamWriter 是字符流通向字節流的橋樑:
                可使用指定的 charset 將要寫入流中的字符編碼成字節

2.構造方法:

  • OutputStreamWriter(OutputStream out, String charsetName)
                out:OutputStream是抽象類,所以我們用子類
                charseName:指定以什麼編碼的方式去寫數據
        指定什麼編碼寫數據,造出來的文件就是什麼編碼的內容也就是什麼編碼的
    不指定編碼,默認是UTF-8

序列化流

    序列化:對象需要實現Serializable接口

1.序列化流_ObjectOutputStream

構造
    ObjectOutputStream(OutputStream out)

寫對象的方法:
    writeObject(對象)

2.反序列化_ObjectInputStream

構造:
    ObjectInputStream(InputStream in)

方法:
     readObject()->讀對象

3.如果不想被反序列化的操作
     1.將成員變量其變成:static
     2.瞬態關鍵字:transient(常用)

4.反序列化時出現的問題以及分析以及解決
序列化數據後,再次修改類文件,讀取數據會出問題,如何解決呢?

答:在實體類中加上:public static final long serialVersionUID = 42L;


Commons-io工具包

一.介紹

    IO技術開發中,代碼量很大,而且代碼的重複率較高。如果我們要遍歷目錄,拷貝目錄就需要使用方法的遞歸調用,也增大了程序的複雜度。
Apache軟件基金會,開發了IO技術的工具類commonsIO,大大簡化IO開發。

二.添加第三方jar包

    Apahce軟件基金會屬於第三方,(Oracle公司第一方,我們自己第二方,其他都是第三方)我們要使用第三方開發好的工具,需要添加jar包。
jar包:就是Java自己的壓縮包,包中是開發好的功能,全部以class文件形態出現,我們添加直接使用即可。

引入jar包:
    1.在module下創建文件夾lib
    2.將jar包文件複製到lib下面
    3.lib文件夾右鍵.選擇add as library
    4.level選項,選擇module

三.工具包的使用

IOUtils類

  • 靜態方法:IOUtils.copy(InputStream in,OutputStream out)傳遞字節流,實現文件複製。
  • 靜態方法:IOUtils.closeQuietly(任意流對象)悄悄的釋放資源,自動處理close()方法拋出的異常。
public class CommonsIO01 {
    public static void main(String[] args)throws Exception {
        //複製
        IOUtils.copy(new FileInputStream("G:\\idea\\io\\image\\2.jpg"),
                new FileOutputStream("G:\\idea\\io\\image\\bb\\julisha.jpg"));
    }
}

FileUtils類

  • 靜態方法:FileUtils.copyDirectoryToDirectory(File src,File dest);
                      傳遞File類型的目錄,進行整個目錄的複製,自動進行遞歸遍歷。
  • 靜態方法:writeStringToFile(File file,String str)寫字符串到文本文件中。
  • 靜態方法:readFileToString(File file)讀取文本文件,返回字符串。
public class CommonsIO02 {
    public static void main(String[] args)throws Exception {
       //複製文件夾
       // FileUtils.copyDirectoryToDirectory(new File("G:\\idea\\io\\image"),new File("G:\\idea"));
       //寫數據
       // FileUtils.writeStringToFile(new File("day16\\fileutils.txt"),"濤哥");
        //讀數據
        String s = FileUtils.readFileToString(new File("day16\\fileutils.txt"));
        System.out.println(s);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章