IO流的UML類圖
File類
File類概述和構造方法【應用】
-
File類介紹
- 它是檔案和目錄路徑名的抽象表示
- 檔案和目錄是可以通過File封裝成物件的
- 對於File而言,其封裝的並不是一個真正存在的檔案,僅僅是一個路徑名而已.它可以是存在的,也可以是不存在的.將來是要通過具體的操作把這個路徑的內容轉換為具體存在的
-
File類的構造方法
方法名 說明 File(String pathname) 通過將給定的路徑名字串轉換為抽象路徑名來建立新的 File例項 File(String parent, String child) 從父路徑名字串和子路徑名字串建立新的 File例項 File(File parent, String child) 從父抽象路徑名和子路徑名字串建立新的 File例項 -
示例程式碼
public class FileDemo01 { public static void main(String[] args) { //File(String pathname): 通過將給定的路徑名字串轉換為抽象路徑名來建立新的 File例項 File f1 = new File("E:\\itcast\\java.txt"); System.out.println(f1); //File(String parent, String child): 從父路徑名字串和子路徑名字串建立新的 File例項 File f2 = new File("E:\\itcast","java.txt"); System.out.println(f2); //File(File parent, String child): 從父抽象路徑名和子路徑名字串建立新的 File例項 File f3 = new File("E:\\itcast"); File f4 = new File(f3,"java.txt"); System.out.println(f4); } }
絕對路徑和相對路徑【理解】
-
絕對路徑
是一個完整的路徑,從碟符開始
-
相對路徑
是一個簡化的路徑,相對當前專案下的路徑
-
示例程式碼
public class FileDemo02 { public static void main(String[] args) { // 是一個完整的路徑,從碟符開始 File file1 = new File("D:\\itcast\\a.txt"); // 是一個簡化的路徑,從當前專案根目錄開始 File file2 = new File("a.txt"); File file3 = new File("模組名\\a.txt"); } }
File類建立功能【應用】
-
方法分類
方法名 說明 public boolean createNewFile() 當具有該名稱的檔案不存在時,建立一個由該抽象路徑名命名的新空檔案。若存在該名稱的檔案則返回false。
不管呼叫者有沒有字尾名,只能建立檔案public boolean mkdir() 建立由此抽象路徑名命名的目錄
只能重建單級資料夾,不能建立多級資料夾
不管有沒有字尾名,只能建立單級資料夾(一般不用該方法,mkdirs可以代替)public boolean mkdirs() 建立由此抽象路徑名命名的目錄,包括任何必需但不存在的父目錄
建立一個多級資料夾 也可以建立一個單級資料夾 -
示例程式碼
public class FileDemo02 { public static void main(String[] args) throws IOException { //需求1:我要在E:\\itcast目錄下建立一個檔案java.txt File f1 = new File("E:\\itcast\\java.txt"); System.out.println(f1.createNewFile()); System.out.println("--------"); //需求2:我要在E:\\itcast目錄下建立一個目錄JavaSE File f2 = new File("E:\\itcast\\JavaSE"); System.out.println(f2.mkdir()); System.out.println("--------"); //需求3:我要在E:\\itcast目錄下建立一個多級目錄JavaWEB\\HTML File f3 = new File("E:\\itcast\\JavaWEB\\HTML"); // System.out.println(f3.mkdir()); System.out.println(f3.mkdirs()); System.out.println("--------"); //需求4:我要在E:\\itcast目錄下建立一個檔案javase.txt File f4 = new File("E:\\itcast\\javase.txt"); // System.out.println(f4.mkdir()); System.out.println(f4.createNewFile()); } }
File類刪除功能【應用】
-
方法分類
方法名 說明 public boolean delete() 刪除由此抽象路徑名錶示的檔案或目錄,刪除的檔案不進入回收站
如果刪除的是檔案,那麼直接刪除;如果刪除的是資料夾,那麼只能刪除空資料夾
如果要刪除一個有內容的資料夾,只能先進入該資料夾中,把裡面的內容刪除完畢才能再次刪除這個資料夾
簡單來說:只能刪除檔案和空資料夾 -
示例程式碼
public class FileDemo03 { public static void main(String[] args) throws IOException { // File f1 = new File("E:\\itcast\\java.txt"); //需求1:在當前模組目錄下建立java.txt檔案 File f1 = new File("myFile\\java.txt"); // System.out.println(f1.createNewFile()); //需求2:刪除當前模組目錄下的java.txt檔案 System.out.println(f1.delete()); System.out.println("--------"); //需求3:在當前模組目錄下建立itcast目錄 File f2 = new File("myFile\\itcast"); // System.out.println(f2.mkdir()); //需求4:刪除當前模組目錄下的itcast目錄 System.out.println(f2.delete()); System.out.println("--------"); //需求5:在當前模組下建立一個目錄itcast,然後在該目錄下建立一個檔案java.txt File f3 = new File("myFile\\itcast"); // System.out.println(f3.mkdir()); File f4 = new File("myFile\\itcast\\java.txt"); // System.out.println(f4.createNewFile()); //需求6:刪除當前模組下的目錄itcast System.out.println(f4.delete()); System.out.println(f3.delete()); } }
File類判斷和獲取功能【應用】
-
判斷功能
方法名 說明 public boolean isDirectory() 測試此抽象路徑名錶示的File是否為目錄 public boolean isFile() 測試此抽象路徑名錶示的File是否為檔案 public boolean exists() 測試此抽象路徑名錶示的File是否存在 -
獲取功能
方法名 說明 public String getAbsolutePath() 返回此抽象路徑名的絕對路徑名字串 public String getPath() 將此抽象路徑名轉換為路徑名字串 public String getName() 返回由此抽象路徑名錶示的檔案或目錄的名稱
如果呼叫者是檔案,那麼獲取的是檔名和字尾名
如果呼叫者是一個資料夾,那麼獲取的是資料夾的名字public File[] listFiles() 返回此抽象路徑名錶示的目錄中的檔案和目錄的File物件陣列(包括隱藏檔案和隱藏資料夾) -
示例程式碼
public class FileDemo04 { public static void main(String[] args) { //建立一個File物件 File f = new File("myFile\\java.txt"); // public boolean isDirectory():測試此抽象路徑名錶示的File是否為目錄 // public boolean isFile():測試此抽象路徑名錶示的File是否為檔案 // public boolean exists():測試此抽象路徑名錶示的File是否存在 System.out.println(f.isDirectory()); System.out.println(f.isFile()); System.out.println(f.exists()); // public String getAbsolutePath():返回此抽象路徑名的絕對路徑名字串 // public String getPath():將此抽象路徑名轉換為路徑名字串 // public String getName():返回由此抽象路徑名錶示的檔案或目錄的名稱 System.out.println(f.getAbsolutePath()); System.out.println(f.getPath()); System.out.println(f.getName()); System.out.println("--------"); // public File[] listFiles():返回此抽象路徑名錶示的目錄中的檔案和目錄的File物件陣列 File f2 = new File("E:\\itcast"); File[] fileArray = f2.listFiles(); for(File file : fileArray) { // System.out.println(file); // System.out.println(file.getName()); if(file.isFile()) { System.out.println(file.getName()); } } } }
File類練習一【應用】
-
案例需求
在當前模組下的aaa資料夾中建立一個a.txt檔案
-
實現步驟
- 建立File物件,指向aaa資料夾
- 判斷aaa資料夾是否存在,如果不存在則建立
- 建立File物件,指向aaa資料夾下的a.txt檔案
- 建立這個檔案
-
程式碼實現
public class Test1 { public static void main(String[] args) throws IOException { //練習一:在當前模組下的aaa資料夾中建立一個a.txt檔案 /* File file = new File("filemodule\\aaa\\a.txt"); file.createNewFile();*/ //注意點:檔案所在的資料夾必須要存在. //1.建立File物件,指向aaa資料夾 File file = new File("filemodule\\aaa"); //2.判斷aaa資料夾是否存在,如果不存在則建立 if(!file.exists()){ //如果資料夾不存在,就建立出來 file.mkdirs(); } //3.建立File物件,指向aaa資料夾下的a.txt檔案 File newFile = new File(file,"a.txt"); //4.建立這個檔案 newFile.createNewFile(); } }
File類練習二【應用】
-
案例需求
刪除一個多級資料夾
-
實現步驟
- 定義一個方法,接收一個File物件
- 遍歷這個File物件,獲取它下邊的每個檔案和資料夾物件
- 判斷當前遍歷到的File物件是檔案還是資料夾
- 如果是檔案,直接刪除
- 如果是資料夾,遞迴呼叫自己,將當前遍歷到的File物件當做引數傳遞
- 引數傳遞過來的資料夾File物件已經處理完成,最後直接刪除這個空資料夾
-
程式碼實現
public class Test2 { public static void main(String[] args) { //練習二:刪除一個多級資料夾 //delete方法 //只能刪除檔案和空資料夾. //如果現在要刪除一個有內容的資料夾? //先刪掉這個資料夾裡面所有的內容. //最後再刪除這個資料夾 File src = new File("C:\\Users\\apple\\Desktop\\src"); deleteDir(src); } //1.定義一個方法,接收一個File物件 private static void deleteDir(File src) { //先刪掉這個資料夾裡面所有的內容. //遞迴 方法在方法體中自己呼叫自己. //注意: 可以解決所有資料夾和遞迴相結合的題目 //2.遍歷這個File物件,獲取它下邊的每個檔案和資料夾物件 File[] files = src.listFiles(); //3.判斷當前遍歷到的File物件是檔案還是資料夾 for (File file : files) { //4.如果是檔案,直接刪除 if(file.isFile()){ file.delete(); }else{ //5.如果是資料夾,遞迴呼叫自己,將當前遍歷到的File物件當做引數傳遞 deleteDir(file);//引數一定要是src資料夾裡面的資料夾File物件 } } //6.引數傳遞過來的資料夾File物件已經處理完成,最後直接刪除這個空資料夾 src.delete(); //這一步必須放在函式裡參與遞迴,把每一個空資料夾刪除 } }
File類練習三【應用】
-
案例需求
統計一個資料夾中每種檔案的個數並列印
列印格式如下:
txt:3個 doc:4個 jpg:6個 …
-
實現步驟
- 定義一個方法,引數是HashMap集合用來統計次數和File物件要統計的資料夾
- 遍歷File物件,獲取它下邊的每一個檔案和資料夾物件
- 判斷當前File物件是檔案還是資料夾
- 如果是檔案,判斷這種型別檔案字尾名在HashMap集合中是否出現過
- 沒出現過,將這種型別檔案的字尾名存入集合中,次數存1
- 出現過,獲取這種型別檔案的字尾名出現的次數,對其+1,在存回集合中
- 如果是資料夾,遞迴呼叫自己,HashMap集合就是引數集合,File物件是當前資料夾物件
-
程式碼實現
public class Test3 { public static void main(String[] args) { //統計一個資料夾中,每種檔案出現的次數. //統計 --- 定義一個變數用來統計. ---- 弊端:同時只能統計一種檔案 //利用map集合進行資料統計,鍵 --- 檔案字尾名 值 ---- 次數 File file = new File("filemodule"); HashMap<String, Integer> hm = new HashMap<>(); getCount(hm, file); System.out.println(hm); } //1.定義一個方法,引數是HashMap集合用來統計次數和File物件要統計的資料夾 private static void getCount(HashMap<String, Integer> hm, File file) { //2.遍歷File物件,獲取它下邊的每一個檔案和資料夾物件 File[] files = file.listFiles(); for (File f : files) { //3.判斷當前File物件是檔案還是資料夾 if(f.isFile()){ //如果是檔案,判斷這種型別檔案字尾名在HashMap集合中是否出現過 String fileName = f.getName(); String[] fileNameArr = fileName.split("\\."); if(fileNameArr.length == 2){ String fileEndName = fileNameArr[1]; if(hm.containsKey(fileEndName)){ //出現過,獲取這種型別檔案的字尾名出現的次數,對其+1,在存回集合中 Integer count = hm.get(fileEndName); //這種檔案又出現了一次. count++; //把已經出現的次數給覆蓋掉. hm.put(fileEndName,count); }else{ // 沒出現過,將這種型別檔案的字尾名存入集合中,次數存1 hm.put(fileEndName,1); } } }else{ //如果是資料夾,遞迴呼叫自己,HashMap集合就是引數集合,File物件是當前資料夾物件程式碼實現 getCount(hm,f); } } } }
位元組流
IO流概述和分類【理解】
- IO流介紹
- IO:輸入/輸出(Input/Output)
- 流:是一種抽象概念,是對資料傳輸的總稱.也就是說資料在裝置間的傳輸稱為流,流的本質是資料傳輸
- IO流就是用來處理裝置間資料傳輸問題的.常見的應用: 檔案複製; 檔案上傳; 檔案下載
- IO流的分類
- 按照資料的流向
- 輸入流:讀資料
- 輸出流:寫資料
- 按照資料型別來分
- 位元組流
- 位元組輸入流
- 位元組輸出流
- 字元流
- 字元輸入流
- 字元輸出流
- 位元組流
- 按照資料的流向
- IO流的使用場景
- 如果操作的是純文字檔案,優先使用字元流
- 如果操作的是圖片、視訊、音訊等二進位制檔案,優先使用位元組流
- 如果不確定檔案型別,優先使用位元組流.位元組流是萬能的流
位元組流寫資料【應用】
-
位元組流抽象基類
- InputStream:這個抽象類是表示位元組輸入流的所有類的超類
- OutputStream:這個抽象類是表示位元組輸出流的所有類的超類
- 子類名特點:子類名稱都是以其父類名作為子類名的字尾
-
位元組輸出流
- FileOutputStream(String name):建立檔案輸出流以指定的名稱寫入檔案
-
使用位元組輸出流寫資料的步驟
- 建立位元組輸出流物件(呼叫系統功能建立了檔案,建立位元組輸出流物件,讓位元組輸出流物件指向檔案)
- 呼叫位元組輸出流物件的寫資料方法
- 釋放資源(關閉此檔案輸出流並釋放與此流相關聯的任何系統資源)
-
示例程式碼
public class FileOutputStreamDemo01 { public static void main(String[] args) throws IOException { //建立位元組輸出流物件 /* 注意點: 1.如果檔案不存在,會幫我們建立 2.如果檔案存在,會把檔案清空 */ //FileOutputStream(String name):建立檔案輸出流以指定的名稱寫入檔案 FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt"); //void write(int b):將指定的位元組寫入此檔案輸出流 fos.write(97); // fos.write(57); // fos.write(55); //最後都要釋放資源 //void close():關閉此檔案輸出流並釋放與此流相關聯的任何系統資源。 fos.close(); } }
位元組流寫資料的三種方式【應用】
-
寫資料的方法分類
方法名 說明 void write(int b) 將指定的位元組寫入此檔案輸出流 一次寫一個位元組資料 void write(byte[] b) 將 b.length位元組從指定的位元組陣列寫入此檔案輸出流 一次寫一個位元組陣列資料 void write(byte[] b, int off, int len) 將 len位元組從指定的位元組陣列開始,從偏移量off開始寫入此檔案輸出流 一次寫一個位元組陣列的部分資料 -
示例程式碼
public class FileOutputStreamDemo02 { public static void main(String[] args) throws IOException { //FileOutputStream(String name):建立檔案輸出流以指定的名稱寫入檔案 FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt"); //FileOutputStream(File file):建立檔案輸出流以寫入由指定的 File物件表示的檔案 // FileOutputStream fos = new FileOutputStream(new File("myByteStream\\fos.txt")); //void write(int b):將指定的位元組寫入此檔案輸出流 // fos.write(97); // fos.write(98); // fos.write(99); // fos.write(100); // fos.write(101); // void write(byte[] b):將 b.length位元組從指定的位元組陣列寫入此檔案輸出流 // byte[] bys = {97, 98, 99, 100, 101}; //byte[] getBytes():返回字串對應的位元組陣列 byte[] bys = "abcde".getBytes(); // fos.write(bys); //void write(byte[] b, int off, int len):將 len位元組從指定的位元組陣列開始,從偏移量off開始寫入此檔案輸出流 // fos.write(bys,0,bys.length); fos.write(bys,1,3); //釋放資源 fos.close(); } }
位元組流寫資料的兩個小問題【應用】
-
位元組流寫資料如何實現換行
windows:\r\n
linux:\n
mac:\r
-
位元組流寫資料如何實現追加寫入
public FileOutputStream(String name,boolean append)
- 建立檔案輸出流以指定的名稱寫入檔案。如果第二個引數為true ,則位元組將寫入檔案的末尾而不是開頭
-
示例程式碼
public class FileOutputStreamDemo03 { public static void main(String[] args) throws IOException { //建立位元組輸出流物件 // FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt"); FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt",true); //寫資料 for (int i = 0; i < 10; i++) { fos.write("hello".getBytes()); fos.write("\r\n".getBytes()); } //釋放資源 fos.close(); } }
位元組流寫資料加異常處理【應用】
-
異常處理格式
-
try-catch-finally
try{ 可能出現異常的程式碼; }catch(異常類名 變數名){ 異常的處理程式碼; }finally{ 執行所有清除操作; }
-
finally特點
- 被finally控制的語句一定會執行,除非JVM退出
-
-
示例程式碼
public class FileOutputStreamDemo04 { public static void main(String[] args) { //加入finally來實現釋放資源 FileOutputStream fos = null; try { fos = new FileOutputStream("myByteStream\\fos.txt"); fos.write("hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if(fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
位元組流讀資料(一次讀一個位元組資料)【應用】
-
位元組輸入流
- FileInputStream(String name):通過開啟與實際檔案的連線來建立一個FileInputStream,該檔案由檔案系統中的路徑名name命名
-
位元組輸入流讀取資料的步驟
- 建立位元組輸入流物件
- 呼叫位元組輸入流物件的讀資料方法
- 釋放資源
-
示例程式碼
public class FileInputStreamDemo01 { public static void main(String[] args) throws IOException { //建立位元組輸入流物件 //FileInputStream(String name) FileInputStream fis = new FileInputStream("myByteStream\\fos.txt"); int by; /* fis.read():讀資料 by=fis.read():把讀取到的資料賦值給by by != -1:判斷讀取到的資料是否是-1 */ while ((by=fis.read())!=-1) { System.out.print((char)by); } //釋放資源 fis.close(); } }
位元組流複製檔案【應用】
-
案例需求
把“E:\itcast\窗裡窗外.txt”複製到模組目錄下的“窗裡窗外.txt” (檔案可以是任意檔案)
-
實現步驟
-
複製文字檔案,其實就把文字檔案的內容從一個檔案中讀取出來(資料來源),然後寫入到另一個檔案中(目的地)
-
資料來源:
E:\itcast\窗裡窗外.txt --- 讀資料 --- InputStream --- FileInputStream
-
目的地:
myByteStream\窗裡窗外.txt --- 寫資料 --- OutputStream --- FileOutputStream
-
-
程式碼實現
public class CopyTxtDemo { public static void main(String[] args) throws IOException { //根據資料來源建立位元組輸入流物件 FileInputStream fis = new FileInputStream("E:\\itcast\\窗裡窗外.txt"); //根據目的地建立位元組輸出流物件 FileOutputStream fos = new FileOutputStream("myByteStream\\窗裡窗外.txt"); //讀寫資料,複製文字檔案(一次讀取一個位元組,一次寫入一個位元組) int by; while ((by=fis.read())!=-1) { //(by=fis.read())小括號別忘了 fos.write(by); } //釋放資源 fos.close(); fis.close(); } }
位元組流讀資料(一次讀一個位元組陣列資料)【應用】
-
一次讀一個位元組陣列的方法
public int read(byte[] b)
:從輸入流讀取最多b.length個位元組的資料- 返回的是讀入緩衝區的總位元組數,也就是實際的讀取位元組個數
-
示例程式碼
public class FileInputStreamDemo02 { public static void main(String[] args) throws IOException { //建立位元組輸入流物件 FileInputStream fis = new FileInputStream("myByteStream\\fos.txt"); byte[] bys = new byte[1024]; //1024及其整數倍 int len; //len表示一次讀取到的有效位元組數量 //迴圈讀取 while ((len=fis.read(bys))!=-1) { System.out.print(new String(bys,0,len)); } //釋放資源 fis.close(); } }
位元組流複製檔案【應用】
-
案例需求
把“E:\itcast\mn.jpg”複製到模組目錄下的“mn.jpg” (檔案可以是任意檔案去)
-
實現步驟
- 根據資料來源建立位元組輸入流物件
- 根據目的地建立位元組輸出流物件
- 讀寫資料,複製圖片(一次讀取一個位元組陣列,一次寫入一個位元組陣列)
- 釋放資源
-
程式碼實現
public class CopyJpgDemo { public static void main(String[] args) throws IOException { //根據資料來源建立位元組輸入流物件 FileInputStream fis = new FileInputStream("E:\\itcast\\mn.jpg"); //根據目的地建立位元組輸出流物件 FileOutputStream fos = new FileOutputStream("myByteStream\\mn.jpg"); //讀寫資料,複製圖片(一次讀取一個位元組陣列,一次寫入一個位元組陣列) byte[] bys = new byte[1024]; int len; while ((len=fis.read(bys))!=-1) { fos.write(bys,0,len); } //釋放資源 fos.close(); fis.close(); } }
位元組緩衝流
位元組緩衝流構造方法【應用】
-
位元組緩衝流介紹
- BufferOutputStream:該類實現緩衝輸出流.通過設定這樣的輸出流,應用程式可以向底層輸出流寫入位元組,而不必為寫入的每個位元組導致底層系統的呼叫
- BufferedInputStream:建立BufferedInputStream將建立一個內部緩衝區陣列.當從流中讀取或跳過位元組時,內部緩衝區將根據需要從所包含的輸入流中重新填充,一次很多位元組
-
構造方法:
方法名 說明 BufferedOutputStream(OutputStream out) 建立位元組緩衝輸出流物件 BufferedInputStream(InputStream in) 建立位元組緩衝輸入流物件 -
底層原理
-
一次讀取一個位元組
-
一次讀取一個位元組陣列
-
建立了一個大小為8192位元組的緩衝陣列,減少了硬碟與記憶體之間資料傳遞的次數,提高效率。
-
-
示例程式碼
public class BufferStreamDemo { public static void main(String[] args) throws IOException { //位元組緩衝輸出流:BufferedOutputStream(OutputStream out) //緩衝流也叫包裝流(處理流),FileOutputStream叫節點流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\bos.txt")); //寫資料 bos.write("hello\r\n".getBytes()); bos.write("world\r\n".getBytes()); //釋放資源 bos.close(); //位元組緩衝輸入流:BufferedInputStream(InputStream in) BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myByteStream\\bos.txt")); //一次讀取一個位元組資料 // int by; // while ((by=bis.read())!=-1) { // System.out.print((char)by); // } //一次讀取一個位元組陣列資料 byte[] bys = new byte[1024]; int len; while ((len=bis.read(bys))!=-1) { System.out.print(new String(bys,0,len)); } //釋放資源 bis.close(); //包裝流關閉,節點流自動關閉 /* 原始碼如下 public void close() throws IOException { byte[] buffer; while ( (buffer = buf) != null) { if (U.compareAndSetReference(this, BUF_OFFSET, buffer, null)) { InputStream input = in; in = null; if (input != null) //關閉節點流 input.close(); return; } // Else retry in case a new buf was CASed in fill() } }*/ } }
位元組緩衝流複製視訊【應用】
-
案例需求
把“E:\itcast\位元組流複製圖片.avi”複製到模組目錄下的“位元組流複製圖片.avi”
-
實現步驟
- 根據資料來源建立位元組輸入流物件
- 根據目的地建立位元組輸出流物件
- 讀寫資料,複製視訊
- 釋放資源
-
程式碼實現
public class CopyAviDemo { public static void main(String[] args) throws IOException { //複製視訊 // method1(); method2(); } //位元組緩衝流一次讀寫一個位元組陣列 public static void method2() throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\itcast\\位元組流複製圖片.avi")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\位元組流複製圖片.avi")); byte[] bys = new byte[1024]; int len; while ((len=bis.read(bys))!=-1) { bos.write(bys,0,len); } bos.close(); bis.close(); } //位元組緩衝流一次讀寫一個位元組 public static void method1() throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\itcast\\位元組流複製圖片.avi")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\位元組流複製圖片.avi")); int by; while ((by=bis.read())!=-1) { bos.write(by); } bos.close(); bis.close(); } }
字元流
為什麼會出現字元流【理解】
-
字元流的介紹
由於位元組流操作中文不是特別的方便,所以Java就提供字元流
字元流 = 位元組流 + 編碼表
-
中文的位元組儲存方式
用位元組流複製文字檔案時,文字檔案也會有中文,但是沒有問題,原因是最終底層操作會自動進行位元組拼接成中文,如何識別是中文的呢?
漢字在儲存的時候,無論選擇哪種編碼儲存,第一個位元組都是負數
編碼表【理解】
-
什麼是字符集
是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數字等
l計算機要準確的儲存和識別各種字符集符號,就需要進行字元編碼,一套字符集必然至少有一套字元編碼。常見字符集有ASCII字符集、GBXXX字符集、Unicode字符集等
-
常見的字符集
-
ASCII字符集:
lASCII:是基於拉丁字母的一套電腦編碼系統,用於顯示現代英語,主要包括控制字元(Enter鍵、退格、換行鍵等)和可顯示字元(英文大小寫字元、阿拉伯數字和西文符號)
基本的ASCII字符集,使用7位表示一個字元,共128字元。ASCII的擴充套件字符集使用8位表示一個字元,共256字元,方便支援歐洲常用字元。是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數字等
-
GBXXX字符集:
GBK:最常用的中文碼錶。是在GB2312標準基礎上的擴充套件規範,使用了雙位元組編碼方案,共收錄了21003個漢字,完全相容GB2312標準,同時支援繁體漢字以及日韓漢字等.
注意GBK編碼以後一箇中文以兩個位元組的形式儲存。
Windows預設使用GBK -
Unicode字符集:
UTF-8編碼:可以用來表示Unicode標準中任意字元,它是電子郵件、網頁及其他儲存或傳送文字的應用 中,優先採用的編碼。網際網路工程工作小組(IETF)要求所有網際網路協議都必須支援UTF-8編碼。它使用一至四個位元組為每個字元編碼。注意UTF-8編碼以後一箇中文以三個位元組的形式儲存
編碼規則:
128個US-ASCII字元,只需一個位元組編碼
拉丁文等字元,需要二個位元組編碼
大部分常用字(含中文),使用三個位元組編碼
其他極少使用的Unicode輔助字元,使用四位元組編碼
-
字串中的編碼解碼問題【應用】
-
相關方法
方法名 說明 byte[] getBytes() 使用平臺的預設字符集將該 String編碼為一系列位元組 byte[] getBytes(String charsetName) 使用指定的字符集將該 String編碼為一系列位元組 String(byte[] bytes) 使用平臺的預設字符集解碼指定的位元組陣列來建立字串 String(byte[] bytes, String charsetName) 通過指定的字符集解碼指定的位元組陣列來建立字串 -
程式碼演示
public class StringDemo { public static void main(String[] args) throws UnsupportedEncodingException { //定義一個字串 String s = "中國"; //byte[] bys = s.getBytes(); //[-28, -72, -83, -27, -101, -67] //byte[] bys = s.getBytes("UTF-8"); //[-28, -72, -83, -27, -101, -67] byte[] bys = s.getBytes("GBK"); //[-42, -48, -71, -6] System.out.println(Arrays.toString(bys)); //String ss = new String(bys); //String ss = new String(bys,"UTF-8"); String ss = new String(bys,"GBK"); System.out.println(ss); } }
字元流寫資料【應用】
-
介紹
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 OutputStreamWriterDemo { public static void main(String[] args) throws IOException { //建立字元輸出流物件 FileWriter fw = new FileWriter("myCharStream\\a.txt"); //void write(int c):寫一個字元 // fw.write(97); // fw.write(98); // fw.write(99); //void writ(char[] cbuf):寫入一個字元陣列 char[] chs = {'a', 'b', 'c', 'd', 'e'}; // fw.write(chs); //void write(char[] cbuf, int off, int len):寫入字元陣列的一部分 // fw.write(chs, 0, chs.length); // fw.write(chs, 1, 3); //void write(String str):寫一個字串 // fw.write("abcde"); //void write(String str, int off, int len):寫一個字串的一部分 // fw.write("abcde", 0, "abcde".length()); fw.write("abcde", 1, 3); //釋放資源 fw.close(); } }
字元流讀資料【應用】
-
介紹
Reader: 用於讀取字元流的抽象父類
FileReader: 用於讀取字元流的常用子類
-
構造方法
方法名 說明 FileReader(File file) 在給定從中讀取資料的 File 的情況下建立一個新 FileReader FileReader(String fileName) 在給定從中讀取資料的檔名的情況下建立一個新 FileReader
-
成員方法
方法名 說明 int read() 一次讀一個字元資料 int read(char[] cbuf) 一次讀一個字元陣列資料 -
程式碼演示
public class InputStreamReaderDemo { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("myCharStream\\b.txt"); //int read():一次讀一個字元資料 // int ch; // while ((ch=fr.read())!=-1) { // System.out.print((char)ch); // } //int read(char[] cbuf):一次讀一個字元陣列資料 char[] chs = new char[1024]; int len; while ((len = fr.read(chs)) != -1) { System.out.print(new String(chs, 0, len)); } //釋放資源 fr.close(); } }
字元流使用者註冊案例【應用】
-
案例需求
將鍵盤錄入的使用者名稱和密碼儲存到本地實現永久化儲存
-
實現步驟
- 獲取使用者輸入的使用者名稱和密碼
- 將使用者輸入的使用者名稱和密碼寫入到本地檔案中
- 關流,釋放資源
-
程式碼實現
public class CharStreamDemo8 { 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("charstream\\a.txt"); //將使用者名稱和密碼寫到檔案中 fw.write(username); //表示寫出一個回車換行符 windows \r\n MacOS \r Linux \n fw.write("\r\n"); fw.write(password); //重新整理流 fw.flush(); //3.關流,釋放資源 fw.close(); } }
字元緩衝流【應用】
-
字元緩衝流介紹
-
BufferedWriter:將文字寫入字元輸出流,緩衝字元,以提供單個字元,陣列和字串的高效寫入,可以指定緩衝區大小,或者可以接受預設大小。預設值足夠大,可用於大多數用途
-
BufferedReader:從字元輸入流讀取文字,緩衝字元,以提供字元,陣列和行的高效讀取,可以指定緩衝區大小,或者可以使用預設大小。 預設值足夠大,可用於大多數用途
-
-
構造方法
方法名 說明 BufferedWriter(Writer out) 建立字元緩衝輸出流物件 BufferedReader(Reader in) 建立字元緩衝輸入流物件 -
程式碼演示
public class BufferedStreamDemo01 { public static void main(String[] args) throws IOException { //BufferedWriter(Writer out) BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt")); bw.write("hello\r\n"); bw.write("world\r\n"); bw.close(); //BufferedReader(Reader in) BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt")); //一次讀取一個字元資料 // int ch; // while ((ch=br.read())!=-1) { // System.out.print((char)ch); // } //一次讀取一個字元陣列資料 char[] chs = new char[1024]; int len; while ((len=br.read(chs))!=-1) { System.out.print(new String(chs,0,len)); } br.close(); } }
字元緩衝流特有功能【應用】
-
方法介紹
BufferedWriter:
方法名 說明 void newLine() 寫一行行分隔符,行分隔符字串由系統屬性定義 BufferedReader:
方法名 說明 String readLine() 讀一行文字。 結果包含行的內容的字串,不包括任何行終止字元如果流的結尾已經到達,則為null -
程式碼演示
public class BufferedStreamDemo02 { public static void main(String[] args) throws IOException { //建立字元緩衝輸出流 BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt")); //寫資料 for (int i = 0; i < 10; i++) { bw.write("hello" + i); //bw.write("\r\n"); bw.newLine(); bw.flush(); } //釋放資源 bw.close(); //建立字元緩衝輸入流 BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt")); String line; while ((line=br.readLine())!=null) { System.out.println(line); } br.close(); } }
字元緩衝流操作檔案中資料排序案例【應用】
-
案例需求
使用字元緩衝流讀取檔案中的資料,排序後再次寫到本地檔案
-
實現步驟
- 將檔案中的資料讀取到程式中
- 對讀取到的資料進行處理
- 將處理後的資料新增到集合中
- 對集合中的資料進行排序
- 將排序後的集合中的資料寫入到檔案中
-
程式碼實現
public class CharStreamDemo14 { public static void main(String[] args) throws IOException { //需求:讀取檔案中的資料,排序後再次寫到本地檔案 //分析: //1.要把檔案中的資料讀取進來。 BufferedReader br = new BufferedReader(new FileReader("charstream\\sort.txt")); //輸出流一定不能寫在這裡,因為會清空檔案中的內容 //BufferedWriter bw = new BufferedWriter(new FileWriter("charstream\\sort.txt")); String line = br.readLine(); System.out.println("讀取到的資料為" + line); br.close(); //2.按照空格進行切割 String[] split = line.split(" ");//9 1 2 5 3 10 4 6 7 8 //3.把字串型別的陣列變成int型別 int [] arr = new int[split.length]; //遍歷split陣列,可以進行型別轉換。 for (int i = 0; i < split.length; i++) { String smallStr = split[i]; //型別轉換 int number = Integer.parseInt(smallStr); //把轉換後的結果存入到arr中 arr[i] = number; } //4.排序 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); //5.把排序之後結果寫回到本地 1 2 3 4... BufferedWriter bw = new BufferedWriter(new FileWriter("charstream\\sort.txt")); //寫出 for (int i = 0; i < arr.length; i++) { bw.write(arr[i] + " "); bw.flush(); } //釋放資源 bw.close(); } }
IO流小結【理解】
- IO流小結
轉換流
字元流中和編碼解碼問題相關的兩個類【理解】
-
InputStreamReader:是從位元組流到字元流的橋樑,父類是Reader
它讀取位元組,並使用指定的編碼將其解碼為字元
它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的預設字符集
-
OutputStreamWriter:是從字元流到位元組流的橋樑,父類是Writer
是從字元流到位元組流的橋樑,使用指定的編碼將寫入的字元編碼為位元組
它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的預設字符集
轉換流讀寫資料【應用】
-
構造方法
方法名 說明 InputStreamReader(InputStream in) 使用預設字元編碼建立InputStreamReader物件 InputStreamReader(InputStream in,String chatset) 使用指定的字元編碼建立InputStreamReader物件 OutputStreamWriter(OutputStream out) 使用預設字元編碼建立OutputStreamWriter物件 OutputStreamWriter(OutputStream out,String charset) 使用指定的字元編碼建立OutputStreamWriter物件 -
程式碼演示
public class ConversionStreamDemo { public static void main(String[] args) throws IOException { //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt")); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"),"GBK"); osw.write("中國"); osw.close(); //InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt")); InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"),"GBK"); //一次讀取一個字元資料 int ch; while ((ch=isr.read())!=-1) { System.out.print((char)ch); } isr.close(); } }
- 在jdk11以後可以不使用轉換流,直接使用FileReader或者FileWriter,傳入Charset
- 程式碼例項
FileReader fr = new FileReader("D:\\file\\a.txt",Charset.forName("gbk"));
物件操作流
- 物件操作流介紹
- 如果把一個物件的資料以流的方式儲存在硬碟某個檔案裡,那麼任何人都可以檢視該檔案中物件的相關資訊,如果該物件包含賬號密碼等資訊則會被暴露的體無完膚。而物件流是把物件以位元組的形式寫到本地檔案,直接開啟檔案,是讀不懂的,需要再次使用物件操作流讀到記憶體中去。保證了安全性。
物件序列化流【應用】
-
物件序列化介紹
- 物件序列化:就是將物件儲存到磁碟中,或者在網路中傳輸物件
- 這種機制就是使用一個位元組序列表示一個物件,該位元組序列包含:物件的型別、物件的資料和物件中儲存的屬性等資訊
- 位元組序列寫到檔案之後,相當於檔案中持久儲存了一個物件的資訊
- 反之,該位元組序列還可以從檔案中讀取回來,重構物件,對它進行反序列化
-
物件序列化流: ObjectOutputStream
- 將Java物件的原始資料型別和圖形寫入OutputStream。 可以使用ObjectInputStream讀取(重構)物件。 可以通過使用流的檔案來實現物件的持久儲存。 如果流是網路套接字流,則可以在另一個主機上或另一個程式中重構物件
-
構造方法
方法名 說明 ObjectOutputStream(OutputStream out) 建立一個寫入指定的OutputStream的ObjectOutputStream -
序列化物件的方法
方法名 說明 void writeObject(Object obj) 將指定的物件寫入ObjectOutputStream -
示例程式碼
學生類
//如果想要這個類的物件能被序列化,那麼這個類必須要實現一個介面.Serializable //Serializable 介面的意義 //稱之為是一個標記性介面,裡面沒有任何的抽象方法 //只要一個類實現了這個Serializable介面,那麼就表示這個類的物件可以被序列化. public class Student implements Serializable { private String name; private 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
測試類
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 { //serialVersionUID 序列號 //如果我們自己沒有定義,那麼虛擬機器會根據類中的資訊會自動的計算出一個序列號. //問題:如果我們修改了類中的資訊.那麼虛擬機器會再次計算出一個序列號. //第一步:把User物件序列化到本地. --- -5824992206458892149 //第二步:修改了javabean類. 導致 --- 類中的序列號 4900133124572371851 //第三步:把檔案中的物件讀到記憶體. 本地中的序列號和類中的序列號不一致了. //解決? //不讓虛擬機器幫我們自動計算,我們自己手動給出.而且這個值不要變. 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; } // @Override // public String toString() { // return "Student{" + // "name='" + name + '\'' + // ", age=" + age + // '}'; // } }
測試類
public class ObjectStreamDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { // write(); read(); } //反序列化 private static void read() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt")); Object obj = ois.readObject(); Student s = (Student) obj; System.out.println(s.getName() + "," + s.getAge()); ois.close(); } //序列化 private static void write() throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt")); Student s = new Student("佟麗婭", 30); oos.writeObject(s); oos.close(); } }
物件操作流練習【應用】
-
案例需求
建立多個學生類物件寫到檔案中,再次讀取到記憶體中
-
實現步驟
- 建立序列化流物件
- 建立多個學生物件
- 將學生物件新增到集合中
- 將集合物件序列化到檔案中
- 建立反序列化流物件
- 將檔案中的物件資料,讀取到記憶體中
-
程式碼實現
學生類
public class Student implements Serializable{ private static final long serialVersionUID = 2L; private String name; private 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; } }
測試類
-
第一種方法(死迴圈)
public static void main(String[] args) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("g.txt")); Person p1 = new Person("zhangsan",12); Person p2 = new Person("lisi",14); Person p3 = new Person("wangwu",13); oos.writeObject(p1); oos.writeObject(p2); oos.writeObject(p3); oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("g.txt")); while (true){ try { Person p = (Person)ois.readObject(); System.out.println(p); } catch (Exception e) { break; } } }
-
第二種方法(物件放入集合)
public class Demo03 { /** * read(): * 讀取到檔案末尾返回值是 -1 * readLine(): * 讀取到檔案的末尾返回值 null * readObject(): * 讀取到檔案的末尾 直接丟擲異常 * 如果要序列化的物件有多個,不建議直接將多個物件序列化到檔案中,因為反序列化時容易出異常 * 建議: 將要序列化的多個物件儲存到集合中,然後將集合序列化到檔案中 */ public static void main(String[] args) throws Exception { /*// 序列化 //1.建立序列化流物件 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myCode\\oos.txt")); ArrayList<Student> arrayList = new ArrayList<>(); //2.建立多個學生物件 Student s = new Student("佟麗婭",30); Student s01 = new Student("佟麗婭",30); //3.將學生物件新增到集合中 arrayList.add(s); arrayList.add(s01); //4.將集合物件序列化到檔案中 oos.writeObject(arrayList); oos.close();*/ // 反序列化 //5.建立反序列化流物件 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myCode\\oos.txt")); //6.將檔案中的物件資料,讀取到記憶體中 Object obj = ois.readObject(); ArrayList<Student> arrayList = (ArrayList<Student>)obj; ois.close(); for (Student s : arrayList) { System.out.println(s.getName() + "," + s.getAge()); } } }
Properties集合
Properties作為Map集合的使用【應用】
-
Properties介紹
- 是一個Map體系的集合類
- Properties可以儲存到流中或從流中載入
- 屬性列表中的每個鍵及其對應的值都是一個字串
-
Properties基本使用
public class PropertiesDemo01 { public static void main(String[] args) { //建立集合物件 // Properties<String,String> prop = new Properties<String,String>(); //錯誤 Properties prop = new Properties(); //增 prop.put("itcast001", "佟麗婭"); prop.put("itcast002", "趙麗穎"); prop.put("itcast003", "劉詩詩"); //刪 prop.remove("itcast001"); //改: put 如果鍵不存在就新增,如果存在就覆蓋原值 prop.put("itcast002","趙本山"); //查 Object value = prop.get("itcast003"); //遍歷集合 Set<Object> keySet = prop.keySet(); for (Object key : keySet) { Object value = prop.get(key); System.out.println(key + "," + value); } } }
Properties作為Map集合的特有方法【應用】
-
特有方法
方法名 說明 Object setProperty(String key, String value) 設定集合的鍵和值,都是String型別,底層呼叫 Hashtable方法 put String getProperty(String key) 使用此屬性列表中指定的鍵搜尋屬性 Set stringPropertyNames() 從該屬性列表中返回一個不可修改的鍵集,其中鍵及其對應的值是字串 -
示例程式碼
public class PropertiesDemo02 { public static void main(String[] args) { //建立集合物件 Properties prop = new Properties(); //Object setProperty(String key, String value):設定集合的鍵和值,都是String型別 prop.setProperty("itcast001", "佟麗婭"); prop.setProperty("itcast002", "趙麗穎"); prop.setProperty("itcast003", "劉詩詩"); //String getProperty(String key):使用此屬性列表中指定的鍵搜尋屬性 // System.out.println(prop.getProperty("itcast001")); // System.out.println(prop.getProperty("itcast0011")); // System.out.println(prop); //Set<String> stringPropertyNames():從該屬性列表中返回一個不可修改的鍵集,其中鍵及其對應的值是字串 Set<String> names = prop.stringPropertyNames(); for (String key : names) { // System.out.println(key); String value = prop.getProperty(key); System.out.println(key + "," + value); } } }
Properties和IO流相結合的方法【應用】
-
和IO流結合的方法
方法名 說明 void load(Reader reader) 從輸入字元流讀取屬性列表(鍵和元素對) void store(Writer writer, String comments) 將此屬性列表(鍵和元素對)寫入此 Properties表中,以適合使用 load(Reader)方法的格式寫入輸出字元流,comments就是註釋資訊 -
示例程式碼
public class PropertiesDemo03 { public static void main(String[] args) throws IOException { //把集合中的資料儲存到檔案 // myStore(); //把檔案中的資料載入到集合 myLoad(); } private static void myLoad() throws IOException { Properties prop = new Properties(); //void load(Reader reader): FileReader fr = new FileReader("myOtherStream\\fw.txt"); prop.load(fr); fr.close(); System.out.println(prop); } private static void myStore() throws IOException { Properties prop = new Properties(); prop.setProperty("itcast001","佟麗婭"); prop.setProperty("itcast002","趙麗穎"); prop.setProperty("itcast003","劉詩詩"); //void store(Writer writer, String comments): FileWriter fw = new FileWriter("myOtherStream\\fw.txt"); prop.store(fw,null); fw.close(); } }
Properties集合練習【應用】
-
案例需求
在Properties檔案中手動寫上姓名和年齡,讀取到集合中,將該資料封裝成學生物件,寫到本地檔案
-
實現步驟
- 建立Properties集合,將本地檔案中的資料載入到集合中
- 獲取集合中的鍵值對資料,封裝到學生物件中
- 建立序列化流物件,將學生物件序列化到本地檔案中
-
程式碼實現
學生類
public class Student implements Serializable { private static final long serialVersionUID = 1L; private String name; private 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
測試類
public class Test { public static void main(String[] args) throws IOException { //1.建立Properties集合,將本地檔案中的資料載入到集合中 Properties prop = new Properties(); FileReader fr = new FileReader("prop.properties"); prop.load(fr); fr.close(); //2.獲取集合中的鍵值對資料,封裝到學生物件中 String name = prop.getProperty("name"); int age = Integer.parseInt(prop.getProperty("age")); Student s = new Student(name,age); //3.建立序列化流物件,將學生物件序列化到本地檔案中 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt")); oos.writeObject(s); oos.close(); } }