Java学习笔记4——I/O框架
目錄
- 1 流的概念
- 2 流的分類
- 3 字節流
- 文件字節流
- FileInputStream
- FileOutputStream
- 字節緩沖流
- BufferedInputStream
- BufferedOutputStream
- 對象流
- ObjectOutputStream
- ObjectInputStream
- 注意事項
- 5 字符流
- 文件字符流
- FileReader
- FileWriter
- 字符緩沖流
- BufferedReader
- BufferedWriter
- 轉換流
- InputStreamReader
- OutputStreamWriter
- 6 File類
- 對文件操作
- 對文件夾操作
- FileFilter接口
- 對文件夾遞歸操作
1 流的概念
內存與存儲設備之間傳輸數據的通道
2 流的分類
-
按方向
輸入流:將<存儲設備>中的內容讀到<內存>中
輸出流:將<內存>中的內容寫到<存儲設備>中 -
按單位
字節流:以字節為單位,可以讀寫所有數據
字符流:以字符為單位,只能讀寫文本數據 -
按功能
節點流:具有實際傳輸數據的讀寫功能
過濾流:在節點流的基礎之上增強功能
3 字節流
字節流的父類(抽象類):InputStream和OutputStream
//InputStream 字節輸入流 public int read(){} public int read(byte[] b){} public int read(byte[] b, int off, int len){}// OutputStream 字節輸出流 public void write(int n){} public void write(byte[] b){} public void write(byte[] b, int off, int len){}文件字節流
FileInputStream
-
FileInputStream從文件系統中的文件獲取輸入字節。 什么文件可用取決于主機環境。
-
構造方法:
FileInputStream(String name) throws FileNotFoundException:通過打開與實際文件的連接來創建一個 FileInputStream,該文件由文件系統中的路徑名 name命名。 -
public int read(byte[] b) throws IOException:從該輸入流讀取最多b.length字節的數據到字節數組。
讀入緩沖區的總字節數,如果沒有更多的數據,因為文件的結尾已經到達,則返回-1 。
FileOutputStream
- FileOutputStream用于寫入諸如圖像數據的原始字節流。
- 構造方法1:
public FileOutputStream(String name) throws FileNotFoundException:創建文件輸出流以指定的名稱寫入文件。 - 構造方法2:
public FileOutputStream(File file,boolean append) throws
FileNotFoundException:創建文件輸出流以指定的名稱寫入文件。 如果第二個參數是true
,則字節將寫入文件的末尾而不是開頭。 - public void write(byte[] b) throws IOException:將b.length字節從指定的字節數組寫入此文件輸出流。
復制文件(邊讀邊寫):
// 1 創建流 // 1.1 文件字節輸入流 FileInputStream fis = new FileInputStream("路徑"); // 1.2 文件字節輸出流 FileInputStream fos = new FileOutpuStream("路徑"); // 2 邊讀邊寫 byte[] buf = new byte[1024]; int count = 0; while((count = fis.read(buf)) != -1){fos.write(buf, 0, count); } // 3 關閉 fis.close(); fos.close();字節緩沖流
- 字節緩沖流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,減少訪問磁盤次數
- 數據存儲在緩沖區中,flush是將緩沖區的內容寫入文件中,也可以直接close
BufferedInputStream
- 構造函數:
public BufferedInputStream(InputStream in):創建一個BufferedInputStream并保存其參數,輸入流in供以后使用。 內部緩沖區數組創建并存儲在buf 。
默認緩沖流大小為8k,可以自定義緩沖流:
// 用自己創建的緩沖流byte[] buf = new byte[1024];int count = 0;while((count = bis.read(buf)) != -1){sout(new String(buf, 0, count));}BufferedOutputStream
-
構造方法1:
BufferedOutputStream(OutputStream out)
創建一個新的緩沖輸出流,以將數據寫入指定的底層輸出流。 -
構造方法2:
BufferedOutputStream(OutputStream out, int size)
創建一個新的緩沖輸出流,以便以指定的緩沖區大小將數據寫入指定的底層輸出流。
對象流
-
ObjectOutputStream / ObjectInputStream
-
增強了緩沖區功能
-
增強了讀寫8種基本數據類型和字符串的功能
-
增強了讀寫對象的功能
-
使用流傳輸對象的過程稱為序列化、反序列化
序列化:將對象轉換為序列,或者說將對象寫入流之中。一個對象可以被表示為一個字節序列,該字節序列包括該對象的數據、有關對象的類型的信息和存儲在對象中數據的類型。
反序列化:從流中讀取對象。
ObjectOutputStream
- 構造方法:
protected ObjectOutputStream(OutputStream out):創建一個寫入指定的OutputStream的ObjectOutputStream。
ObjectInputStream
-
構造方法:
protected ObjectInputStream(InputStream in):創建從指定的InputStream讀取的ObjectInputStream。 -
Object readObject() : 從ObjectInputStream讀取一個對象。
注意事項
- 某個類要想序列化必須實現Serializable接口
- 序列化類中對象屬性(屬性中的引用數據類型)也要求實現Serializable接口
- 序列化版本號ID(serialVersionUID )的作用:保證序列化的類和反序列化的類是同一個類
- 使用transient修飾的屬性,這個屬性就不能被序列化
- 靜態屬性不能被序列化
- 序列化多個對象,可以借助集合來實現
借助集合來實現序列化多個對象:
psvm(String[] args)throws Exception{// 1. 創建對象流FileOutputStream fos = new FileOutputStream("d:\\st.bin");ObjectOutputSream oos = new objectOutputSream(fos);// 2. 序列化(寫入操作)Student s1 = new Student("張三", 20);Student s2 = new Student("李四", 22);ArrayList<Student> list = new ArrayList<>();list.add(s1);list.add(s2);oos.WriteObject(list);// 3. 關閉oos.close();sout("序列化完畢"); } psvm(String[] args)throws Exception{// 1. 創建對象流FileInputStream fis = new FileInputStream("d:\\stu.bin");ObjectInputStream ois = new ObjectInputStream(fis);// 2. 讀取文件(反序列化)ArrayList<Student> list = (ArrayList<Student>)ois.readObject();//返回Object類型,需轉換// 3. 關閉ois.close();sout("執行完畢");sout(list.toString()); }5 字符流
-
注:在UTF-8編碼中,
一個中文字符 / 中文標點符號占3個字節;
一個英文字符 / 英文標點 / 數字符號占1個字節。因為字節流是逐個字節讀取,要是讀取漢字或者其他內容的文本的話會出現亂碼,因為一個字節無法組成漢字,所以要用到字符流。
-
字符流的兩個父類(抽象類):
Reader字符輸入流:
public int read()
public int read(char[] c)
public int read(char[] b, int off, int len)
Writer字符輸出流:
public void write(int n)
public void write(String str)
public void write(char[] c)
文件字符流
FileReader和FileWriter
FileReader
單個字符讀取:
// 1. 創建FileReader 文件字符輸入流 FileReader fr = new FileReader(".."); // 2. 讀取 // 2.1 單個字符讀取 int data = 0; while((data = fr.read()) != -1){sout((char)data);// 讀取一個字符 }// 3. 關閉 fr.close();使用自定義字符緩沖區讀取:
// 1. 創建FileReader 文件字符輸入流 FileReader fr = new FileReader(".."); // 2. 讀取 // 2.2 使用字符緩沖區讀取 char[] buf = new char[2]; //2表明2個字符2個字符地讀,緩沖區大小可以自定義 int count = 0; while((count = fr.read(buf) != -1)){sout(new String(buf, 0, count)); } // 3. 關閉 fr.close();FileWriter
// 1. 創建FileWriter對象 FileWriter fw = new FileWriter(".."); // 2. 寫入fw.write("Java是世界上最好的語言");fw.flush();// 3. 關閉 fw.close(); sout("執行完畢");復制文件(使用FileReader和FileWriter):
不能復制圖片或二進制文件(聲音、視頻、可編譯文件等),使用字節流可以復制任意文件。
字符緩沖流
BufferedReader和BufferedWriter
高效讀寫、支持輸入換行符、可一次寫一行讀一行
BufferedReader
從字符輸入流讀取文本,緩沖字符,以提供字符,數組和行的高效讀取
- 構造方法1:BufferedReader(Reader in):創建使用默認大小的輸入緩沖區的緩沖字符輸入流。
- public int read():讀一個字符,如果已經達到流的結尾,則為-1。
- public String readLine():讀一行文字。 一行被視為由換行符(’\ n’),回車符(’\ r’)中的任何一個或隨后的換行符終止。如果已達到流的末尾,則為null
BufferedWriter
將文本寫入字符輸出流,緩沖字符,以提供單個字符,數組和字符串的高效寫入。
psvm(String[] args) throws Exception{// 1. 創建BufferedWriter對象FileWriter fw = new FileWriter("...");//若已有該文件,則會覆蓋文件BufferedWriter bw = new BufferedWriter(fw);// 2. 寫入for(int i = 0; i < 10; i ++){//寫十遍bw.write("寫入的內容");bw.newLine(); // 寫入一個換行符bw.flush();}// 3. 關閉bw.close();轉換流
InputStreamReader
-
InputStreamReader是從字節流(硬盤)到字符流(內存)的橋:它讀取字節,并使用指定的charset將其解碼為字符 。
它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集。 -
構造方法1:
InputStreamReader(InputStream in)
創建一個使用默認字符集的InputStreamReader。 -
構造方法2:
InputStreamReader(InputStream in, String charsetName)
創建一個使用命名字符集的InputStreamReader。 -
String getEncoding() 返回此流使用的字符編碼的名稱。
-
int read() 讀一個字符
OutputStreamWriter
- OutputStreamWriter是字符的橋梁流以字節流:向其寫入的字符編碼成使用指定的字節charset 。
它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集。 - 構造方法1:
OutputStreamWriter(OutputStream out)
創建一個使用默認字符編碼的OutputStreamWriter。 - 構造方法2:
OutputStreamWriter(OutputStream out, String charsetName)
創建一個使用命名字符集的OutputStreamWriter。 - void flush() 刷新流。
- void write(int c) 寫一個字符
6 File類
-
文件和目錄路徑名的抽象表示。
-
常量:
static String pathSeparator
與系統相關的路徑分隔符字符,為方便起見,表示為字符串。 (即 ;)
static char pathSeparatorChar
與系統相關的路徑分隔符。(即 ;)
static String separator
與系統相關的默認名稱 - 分隔符字符,以方便的方式表示為字符串。 (即 \)
static char separatorChar
與系統相關的默認名稱分隔符。 (即 \) -
構造方法:
File(File parent, String child)
從父抽象路徑名和子路徑名字符串創建新的 File實例。
File(String pathname)
通過將給定的路徑名字符串轉換為抽象路徑名來創建新的 File實例。
File(String parent, String child)
從父路徑名字符串和子路徑名字符串創建新的 File實例。
File(URI uri)
通過將給定的 file: URI轉換為抽象路徑名來創建新的 File實例。
常用方法:
- boolean createNewFile() 當且僅當具有該名稱的文件尚不存在時,創建一個由該抽象路徑名命名的新的空文件。
- boolean mkdir() 創建由此抽象路徑名命名的單個目錄。
- boolean mkdirs() 創建由此抽象路徑名命名的多級目錄。
- boolean delete() 刪除由此抽象路徑名表示的文件或目錄。
- boolean exists() 測試此抽象路徑名表示的文件或目錄是否存在。
- String getAbsolutePath() 返回此抽象路徑名的絕對路徑名字符串。
- String getName() 返回由此抽象路徑名表示的文件或目錄的名稱。
- String getParent() 返回此抽象路徑名的父 null的路徑名字符串,如果此路徑名未命名為父目錄,則返回null。
- boolean isDirectory() 測試此抽象路徑名表示的文件是否為目錄。
- boolean isFile() 測試此抽象路徑名表示的文件是否為普通文件。
- long length() 返回由此抽象路徑名表示的文件的長度。
- File[] listFiles() 返回一個抽象路徑名數組,表示由該抽象路徑名表示的目錄中的文件。
- boolean renameTo(File dest) 重命名由此抽象路徑名表示的文件。
對文件操作
/* File類的使用 1. 分隔符 2. 對文件操作 3. 對文件夾操作 */ public class FileDemo {public static void main(String[] args) throws Exception{ // separator(); // fileOpe();directoryOpe();}//1. 分隔符public static void separator(){System.out.println("路徑分隔符" + File.pathSeparator);System.out.println("名稱分隔符" + File.separator);}// 2. 對文件操作public static void fileOpe() throws Exception {// 1. 創建文件File file = new File("G:\\360MoveData\\Users\\cheng\\Desktop\\demo1.txt");if(!file.exists()){ //如果不存在,則創建boolean b = file.createNewFile();System.out.println("創建結果:"+b);}// 2. 刪除文件// 2.1 直接刪除 // System.out.println("刪除結果:"+file.delete()); // 2.2 讓jvm退出時刪除 // file.deleteOnExit(); // Thread.sleep(3000);//3秒// 3. 獲取文件信息System.out.println("獲取絕對路徑"+file.getAbsolutePath());System.out.println("獲取路徑" + file.getPath());System.out.println("獲取文件名稱" + file.getName());System.out.println("獲取父目錄" + file.getParent());System.out.println("獲取文件長度" + file.length());System.out.println("文件創建時間" + new Date(file.lastModified()).toLocaleString());// 4. 判斷System.out.println("是否可寫" + file.canWrite());System.out.println("是否是文件" + file.isFile());System.out.println("是否隱藏" + file.isHidden());} }對文件夾操作
// 對文件夾操作public static void directoryOpe() throws Exception{// 1. 創建文件夾File dir = new File("G:\\360MoveData\\Users\\cheng\\Desktop\\aaa\\bbb\\ac");if(!dir.exists()){//dir.mkdir(); // 只能創建單級目錄dir.mkdirs(); // 創建多級目錄}// 2. 刪除文件夾// 2.1 直接刪除 // System.out.println("刪除結果:"+dir.delete()); // 1.只能刪除最里面的目錄;2.而且只刪除空目錄// 2.2 讓jvm退出時刪除 // dir.deleteOnExit(); // Thread.sleep(3000);//3秒// 3. 獲取文件夾信息System.out.println("獲取絕對路徑" + dir.getAbsolutePath());System.out.println("獲取路徑" + dir.getPath());System.out.println("獲取文件名稱" + dir.getName());System.out.println("獲取父目錄" + dir.getParent());System.out.println("獲取文件長度" + dir.length());System.out.println("文件夾創建時間" + new Date(dir.lastModified()).toLocaleString()); //// 4. 判斷System.out.println("是否是文件夾" + dir.isDirectory());System.out.println("是否隱藏" + dir.isHidden());// 5. 遍歷文件夾File dir2 = new File("G:\\360MoveData\\Users\\cheng\\Desktop\\雜項");String[] files = dir2.list();for(String string : files){System.out.println(string);}} }FileFilter接口
- public interface FileFilter
- boolean accept(File pathname) 測試指定的抽象路徑名是否應包含在路徑名列表中。
- 當調用File類的listFiles()方法時,支持傳入FileFilter接口實現類,對獲取文件進行過濾,只有滿足條件才可以出現在listFiles()的返回值中。
對文件夾遞歸操作
1.遞歸遍歷文件夾(顯示里面所有文件,包括其所有子文件夾里面的所有文件)
//遞歸遍歷文件夾public static void main(String[] args) { // listDir(new File("G:\\360MoveData\\Users\\cheng\\Desktop\\雜項1"));deleteDir(new File("G:\\360MoveData\\Users\\cheng\\Desktop\\雜項2"));}public static void listDir(File dir){File[] files = dir.listFiles();System.out.println(dir.getAbsolutePath());if(files != null && files.length > 0){for(File file : files){if(file.isDirectory()){listDir(file); // 遞歸}else {System.out.println(file.getAbsolutePath());}}}}2.遞歸刪除文件夾里所有文件(包括其所有子文件夾里的所有文件)
public static void deleteDir(File dir){File[] files = dir.listFiles();if(files != null && files.length > 0){for(File file : files){if(file.isDirectory()){deleteDir(file); // 遞歸}else{// 刪除文件System.out.println(file.getAbsolutePath() + "刪除" + file.delete());}}}System.out.println(dir.getAbsolutePath() + "刪除" + dir.delete());}總結
以上是生活随笔為你收集整理的Java学习笔记4——I/O框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Facebook 开源的快速文本分类器
- 下一篇: 微动探测原理及仪器介绍