檔案:文字、圖片、視訊、程式等儲存在計算機上
檔案目錄:資料夾,管理檔案, linux 下有許可權、操作符、使用者組、使用者等
路徑分割符:
\ 表示 windows 系統檔案目錄分割符
/ 表示 mac/linux 下的路徑分割符
java 程式碼在 windows 下寫某個檔案的話需要下面的方式
D:\\soft\\sd.txt 其中一個單斜槓是用來轉義的
java 程式碼在 linux 或者 Mac 下寫某個檔案的話需要下面的方式
usr/local/soft/sd.txt 其中一個單斜槓是用來轉義的
程式碼和檔案目錄的關係: 對檔案和目錄增刪改查
IO,輸入和輸出 Input/Output
把持久化裝置上的資料讀取到記憶體中的動作稱為輸入, Input 操作
記憶體中的資料持久化到裝置上的動作, Output 輸出操作
一般把輸入和輸出動作稱為 IO 操作, IO 分為網路 IO 和檔案 IO
java 檔案類 File :
主要是對計算機檔案目錄的操作,對檔案和目錄的增刪改查, File 類表示磁碟中存在的檔案和目錄
實現了 Serializable, Comparable 兩大介面,可進行序列化和比較
File.separator 目錄分隔符,在不同的系統下不一樣, windows 下是 "\" , mac/Linux 下是 "/",操作檔案時可以用來連線目錄的分隔符
常見的建構函式:
//路徑和檔名的拼接
public File(String pathname)
//父路徑,子路徑
public File(String parent, String child)
// 獲取帶檔名的檔案路徑,即 new File 建構函式傳入的路徑
String getPath()
String dir = "C:\\Users\\79466\\Desktop\\";
String name = "a.txt";
File file = new File(dir, name);
// File file = new File(dir); 目錄物件
System.out.println(file.getPath()); // 列印檔案的路徑和檔名
System.out.println(File.separator); // 列印不同系統的檔案分隔符
// 常用的檔案操作 api
file.getPath(); // 獲取帶檔名的檔案路徑, C:\Users\79466\Desktop\a.txt
file.getName(); // 獲取檔名, a.txt
file.getAbsolutePath(); // 獲取檔案的絕對路徑 C:\Users\79466\Desktop\a.txt
file.getParent(); // 獲取檔案的父路徑 C:\Users\79466\Desktop
file.exists(); // 檔案或者目錄是否存在
file.isFile(); // 是否是一個檔案
file.isDirectory(); // 是否是一個目錄
file.isAbsolute(); //是否是絕對路徑
// 如果 file 是目錄,獲取檔案目錄下所有的檔案及目錄的名稱,操作物件是目錄,如果是檔案會報錯
String[] arr = file.list();
for (String temp : arr) {
System.out.println(temp);
}
// 建立指定目錄
File mkdir = new File(dir + "\\xd");
mkdir.mkdir(); //建立一級目錄
File mkdirs = new File(dir + "\\xd\\aa\\bb\\cc"); // 或者 dir + "\\xd\\aa\\bb\\cc\\"
mkdirs.mkdirs(); //建立多級目錄
File newFile = new File(dir + "\\xxxx.txt");
// 如果 dir 不存在或者建立檔案失敗需要捕獲異常
try {
newFile.createFile();
} catch (IOException e) {
e.printStackTrace();
}
newFile.delete(); //刪除操作,當前檔案如果是最終的檔案才可以刪除,如果是目錄,裡面還有檔案,需要先刪除檔案才能刪除該目錄
File 的建構函式只是建立一個 File 例項,即使目錄錯誤也不會報錯,因為沒有對檔案進行操作
輸出流: 程式到外界裝置 輸入流: 外界裝置到程式
處理資料型別分類
字元流: 處理字元相關,如文字資料( txt 檔案), Reader / Writer
位元組流: 處理位元組相關,聲音或者圖片等二進位制, InputStream/OutputStream
兩者區別:
位元組流以位元組(8bit)為單位,字元流以字元為單位,根據碼錶對映字元,一次可能讀多個位元組
位元組流可以處理幾乎所有檔案,字元流只能處理字元型別的資料,如果檔案都是中文文字的話可以使用字元流,速度更快,更省空間
功能不同,但是具有共性內容,抽象成4個抽象類
字元流 Reader/Writer
位元組流 InputStream/OutputStream
使用的時候都不會使用抽象類進行實現,開發使用對應的子類
位元組流:
InputStream: 實現類及子類有 FileInputStream (這個類用的最多, 可以用 BufferedInputStream 提高效能)、 ObjectInputStream (物件輸入流,序列化的時候) 、 ByteArrayInputStream
OutputStream 和 InputStream 一樣
int read(byte[] buf) // 從輸入流中讀取一定數量的位元組,並將其儲存在緩衝區陣列 buf 中,返回實際讀取的位元組數
int available() // 返回這個流中有多少個位元組數,可以把 buf 陣列長度定為這個
void close() throws IOException // 關閉輸入流並釋放與該流關聯的系統資源
FileInputStream 位元組輸入流:
// 傳入檔案所在地址
public FileInputStream(String name) throws FileNotFoundException
// 傳入檔案物件
public FileInputStream(File file) throws FileNotFoundException
public static void main (String [] args) {
File file = new File(dir, name);
InputStream inputStream = new FileInputStream(file);
// 讀取一個位元組
int read = inputStream.read();
// 位元組對應的 ASCII 碼
System.out.println(read);
// 強轉成字元
System.out.println((char)read);
}
inputStream.skip(); // 跳過,從輸入流中跳過並丟棄 n 個位元組的資料
byte[] buf = new byte[1024];
int length;
// 一次性讀取 buf.length 個位元組並放到 buf 陣列中,返回型別是讀取到的位元組數
while ((length = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, length)); // 從0開始,長度是3
System.out.println(new String(buf, 0, length, "UTF-8"));
}
FileOutputStream 位元組輸出流:
構造:
// 傳入輸出的檔案地址
public FileOutputStream(String name)
// 傳入目標輸出的檔案物件
public FileOutputStream(File file)
// 傳入目標輸出的檔案物件,是否可以追加內容
public FileOutputStream(File file, boolean append)
public static void main(String [] args) {
String target = "a.txt";
InputStream inputStream = new FileInputStream(file);
// 會建立檔案,但是不會建立多級目錄
// OutputStream outputStream = new FileOutputStream(dir + File.separator + target);
// 不覆蓋檔案,只追加資料
OutputStream outputStream = new FileOutputStream(dir + File.separator + target, true);
byte[] buf = new byte[1024];
int length;
// 一次性讀取 buf.length 個位元組並放到 buf 陣列中,返回型別是讀取到的位元組數
while ((length = inputStream.read(buf)) != -1) {
// 按位元組陣列的長度寫出
outputStream.write(buf, 0, length);
}
// 異常處理見下面,此處如果上面出現異常就無法關閉
inputStream.close();
outputStream.close();
}
緩衝 Buffer :
記憶體空間的一部分,在記憶體空間預留了一定的儲存空間,這些儲存空間用來緩衝輸入或輸出的資料,這部分空間就叫做緩衝區,緩衝區預設大小是8k,使用緩衝區暫存資料,
可以減少和磁碟的互動,讀入時與磁碟連線後讀入較多的資料到緩衝區,記憶體再慢慢去消耗
BufferInputStream 緩衝位元組輸入流,讀取資料時,與磁碟連線一次讀取到記憶體,緩衝區滿時會再讀取下一截資料重新填充到緩衝區
建構函式:
// 對輸入流進行包裝,裡面預設的緩衝區是8k
public BufferedInputStream(InputStream in);
// 對輸入流進行包裝,建立具有指定緩衝區大小的 Buffer
public BufferedInputStream(InputStream in, int size);
常用方法:
// 從輸入流中讀取一個位元組
public int read();
// 從位元組輸入流中給定偏移量處開始將各位元組讀取到指定的 byte 陣列中
public int read(byte[] buf, int off, int len);
// 關閉資源,關閉這個流即可, InputStream 會在裡面被關閉
void close();
BufferOutputStream 緩衝位元組輸出流,當緩衝區滿時,會自動寫出到磁碟
構造同 BufferInputStream
常用方法:
// 向輸出流中輸出一個位元組
public void write(int b);
// 將指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入緩衝的輸出流
public void write(byte[] buf, int off, int len);
// 重新整理此緩衝的輸出流,強制使所有緩衝的輸出位元組被寫出到底層輸出流中,當緩衝區的大小未滿時,需要手動刷到磁碟
public void flush();
// 關閉釋放資源, OutputStream 會在裡面被關閉, JDK7 新特性 try (在這裡宣告的 流 會自動關閉){}
void close();
緩衝輸入輸出流進行檔案拷貝:
try {
FileInputStream fis = new FileInputStream("C:\\Users\\79466\\Desktop\\test\\a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("C:\\Users\\79466\\Desktop\\test\\copy.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int size;
byte[] buf = new byte[1024];
while (( size = bis.read(buf)) != -1) {
// 將位元組輸出流寫到緩衝區裡面,等緩衝區滿後自動寫出
bos.write(buf, 0, size);
}
// 重新整理此緩衝區的輸出流,才可以保證資料全部輸出完成,關閉的時候也會進行重新整理,寫了也不要緊,也就是多刷一次, close 方法的關閉前會先進行重新整理
// bos.flush();
// 內部會關掉 InputStream 和 OutputStream 異常處理見下面,此處如果上面出現異常就無法關閉
bis.close();
// close 原始碼裡面會有 flush ,可以不用單獨呼叫 flush ,jdk7 之後 close 原始碼裡的 try 裡面宣告瞭 OutputStream ,會自動關閉 outputStream 流
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
流的關閉順序,後開的先關,如果A依賴B,先關閉B
IO 的異常處理:
大部分公司的做法: 在 finally 裡面進行關閉
catch (Exception e) {
e.printStackTrace();
} finally {
if(bis != null) {
try {
bis.close();
}catch () {
e.printStackTrace();
}finally {
if(bos != null) {
try {
bos.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
jdk7 之後的做法: try-with-resource
try 裡面宣告的 OutputStream 和 InputStream 會自動關閉, jdk7 之後的 InputStream 都實現了 AutoCloseable
在 try 裡面定義多個資源,關閉的順序是最後在 try() 定義的資源最先關閉
try (
FileInputStream fis = new FileInputStream("C:\\Users\\79466\\Desktop\\test\\a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("C:\\Users\\79466\\Desktop\\test\\copy.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);) {
int size;
byte[] buf = new byte[1024];
while(( size = bis.read(buf)) != -1 ) {
bos.write(buf, 0, size);
}
bos.flush();
} catch (Exception e) {
e.printStackTrace();
}