本文轉自我的博客缚柏,您可以閱讀原文.
File類
概覽
創(chuàng)建一個代表一個文件或者文件夾對象朦促,也就是你要操作的目標。
// 創(chuàng)建一個文件對象(不管是不是真實存在)
File file = new File("F:\\a.txt"); // Linux里面是一個正斜杠(windows也是支持的)
// 判斷文件對象是否存在
file.exists();
// 獲取系統(tǒng)的目錄分隔符
File.separator();
構造方法
// 指定文件或文件夾洪己,創(chuàng)建文件對象
File(String pathname);
// 將路徑拆開來(應用場景:先要操作父文件對象屡贺,再操作子文件)
File(File parent, String child);
// 沒太多意義蠢棱,純粹拆開路徑
File(String parent, String child);
注意:使用相對路徑時,當前路徑指的是項目根目錄甩栈。
File類中常用方法
創(chuàng)建
File file = new File("F:\\a.txt");
File dir = new File("F:\\a");
// 基于文件對象創(chuàng)建一個文件(會拋出異常泻仙,返回Boolean)
file.createNewFile();
// 基于文件對象創(chuàng)建一個單級文件夾
dir.mkdir();
// 創(chuàng)建一個多級文件夾
dir.mkdirs();
// 重命名(包含剪切)
file.renemeTo(destFile);
刪除
// 刪除文件或空文件夾
delete();
// 在虛擬機終止時,刪除此抽象路徑下的文件或目錄量没,保證程序異常時創(chuàng)建的臨時文件也可以刪除
deleteOnExit()
判斷
exists();
isFile();
isDirectory();
isHidden();
isAbsolute(); // 判斷該路徑是否為絕對路徑
獲取
getName();
getPath();
getAbsolutePath();
// 獲取文件大杏褡(字節(jié)數(shù)),如果文件不存在或者是文件夾則返回0L
length();
getParent();
lastModified();
// 列出系統(tǒng)根目錄
static File[] listRoots();
// 返回指定目錄中的子文件或子目錄
list();
// 返回指定目錄中符合過濾條件的子文件或子目錄
list(Filename filter);
// 列出指定目錄下的文件或目錄對象(File實例)
listFiles();
// 返回指定目錄下符合過濾條件的子文件或子目錄
listFiles(Filename filter);
實例
場景:分開列出目錄中所有子文件名與子目錄名允蜈。
public static viod listAllFilesAndDirs(String path) {
File dir = new File(path);
File[] name = dir.listFiles();
List<File> fileList = new ArrayList<File>();
List<File> dirList = new ArrayList<File>();
for(int i = 0; i < name.length; i++) {
File file = names[i];
if(file.isFile) {
fileList.add(file);
}else if(file.isDirectory) {
dirList.add(file);
}
}
System.out.println("子文件:");
for(int i = 0; i < fileList.size(); i++) {
System.out.println("\t" + fileList[i].getName());
}
System.out.println("子目錄:");
for(int i = 0; i < dirList.size(); i++) {
System.out.println("\t" + dirList[i].getName());
}
}
字節(jié)流
上面我們已經(jīng)知道File對象封裝的是文件或者路徑屬性冤吨,但是不包含向(從)文件讀(寫)數(shù)據(jù)的方法,此時就該是IO流粉墨登場的時候了饶套。
輸入流
read()
這種方式料率底下漩蟆,不推薦使用。
/* 一次讀取一個字節(jié)妓蛮,讀到文末返回-1 */
private viod showContent(String path) throws IOException {
// 打開流管道
FileInputStream fis = new FileInputStream(path);
int len;
while(len = fis.read() != -1) {
System.out.println((char)len);
}
fis.close();
}
read(byte[] b)
使用read()的時候怠李,流需要讀一次就處理一次。read(byte[] b)可以將讀到的數(shù)據(jù)裝入字節(jié)數(shù)組中蛤克,一次性地操作數(shù)組捺癞,可以提高效率。
read()就類似你從井里一次舀一杯水送到房間里給別人喝构挤;read(byte[] b)就相當于你從井里一次舀一杯水先放到桶子里髓介,等舀滿一桶水再將這桶水運到房間里給別人喝。
private viod showContent(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
byte[] byt = new byte[1024];
int len = 0;
while((len = fis.read(byt))! = -1) {
// 字節(jié)數(shù)組里面存的是二進制數(shù)據(jù)筋现,要將之解析出來需要借助字符串的構造方法
System.out.println(new String(byt, 0, len));
}
}
read(byte[] b, int off, int len)
其實就是把數(shù)組的一部分當作流的容器來使用唐础。告訴容器從什么地方開始裝多少。
輸出流
輸出流基本就是用來寫入數(shù)據(jù)的矾飞。
write(int b)
write(int b)一次寫出一個字節(jié)一膨。
雖然write(int b)接收的是int類型參數(shù),但是write(int b)的常規(guī)協(xié)定是:向輸入流寫入一個字節(jié)洒沦,要寫入的字節(jié)是參數(shù)的低八位豹绪,高24個高位將將被忽略。
write(byte[] b)
write(byte[] b)相比write(int b)效率更高申眼。原因就不多說了瞒津。
我們只需要將字符串轉化為字節(jié)數(shù)組蝉衣,然后通過該方法就可以一次寫入多個字節(jié)。
創(chuàng)建輸出字節(jié)流對象時巷蚪,如果不想覆蓋已存在內容买乃,而是追加內容只需如此這般:new FileOutputStream(path, true)
private static void writeTxtFile(String path) throwss IOException {
FileOutputStream fos = new FileOutputStream(path);
byte[] byt = "要插入的數(shù)據(jù)".getBytes();
fos.write(byt);
fos.close();
}
字節(jié)流文件拷貝
public static copyFile(String srcPath, String destPath) throwss IOException {
// 打開輸入輸出流
FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
// 讀取和寫入信息
int len = 0;
byte[] byt = [1024];
while((len = fis.read(byt)) != -1) {
fos.write(byt, 0, length);
}
// 關閉流
fis.close();
fos.close();
}
字節(jié)流的異常處理
上述例子中,我們使用了拋出異常的方式來處理異常钓辆。但實際上,這樣做是不合適的肴焊。
例如第一個通道關閉出錯會導致第二個通道無法關閉前联。正確的做法是使用try--catch--finelly
語句塊來處理異常。
字節(jié)緩沖流
字節(jié)緩沖流內部有一個緩沖區(qū)娶眷,其實內部也是封裝了字節(jié)數(shù)組似嗤,默認的字節(jié)是8192。
緩沖區(qū)輸入流與緩沖區(qū)輸出流要配合使用届宠。首先緩沖區(qū)輸入流會將讀取到的數(shù)據(jù)寫入緩沖區(qū)烁落,當緩沖區(qū)滿時,或者調用flush()方法豌注,緩沖輸出流會將數(shù)據(jù)寫出伤塌。
public static viod copyFile(String srcPath, String destPath) throws IOException {
// 打開輸入流,輸出流
FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
// 使用緩沖流
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 讀取和寫入信息
int len = 0;
while((len = bis.read()) != -1) {
bos.write(len);
}
// 關閉流
bis.close();
bos.close();
}
字符流(FileReader & FileWwiter)
字節(jié)流以字節(jié)為單位轧铁,而字符流是以字符為單位每聪。更方便地處理文本文檔。
常見的碼表
計算機不管是存文本文件還是二進制文件本質上都是存的二進制數(shù)據(jù)齿风。如果是文本文件的話药薯,計算機需要一套規(guī)則才能將二進制的數(shù)據(jù)翻譯成我們能看懂的字符。這套規(guī)則就是指的碼表救斑。
- ASCII:美國標準信息交換碼童本。一個字符占一個字節(jié),用一個字節(jié)的7位可以表示
- ISO8859-1:拉丁碼表脸候。歐洲碼表穷娱,用一個字節(jié)的8位表示
- GBG2312: 英文占一個字節(jié),中文占兩個字節(jié)
- GBK:中國的中文碼表升級纪他,融合了更多的中文文字符號
- Unicode:國際標準碼規(guī)范鄙煤。所有文字都用兩個字節(jié)來表示(java就是用的這個)
- UTF-8:英文一個字節(jié),中文三個字節(jié)
Reader
方法
int reader();
讀取一個字符茶袒。返回的是讀到的那個字符梯刚。如果讀到流的末尾則返回-1;
int read(char[]);
將讀到的字符存入指定的數(shù)組中薪寓,返回的是讀到的字符個數(shù)亡资,也就是往數(shù)組里裝的元素的個數(shù)澜共。讀到流的末尾則返回-1;
close();
使用完畢后锥腻,進行資源的釋放嗦董;
public static void readFileByReader(String path) throws Exception {
Reader reader = new FileReader(path);
int len = 0;
while((len = reader.read()) != -1) {
System.out.println((char)len);
}
reader.close();
}
Writer
write(ch)
將一個字符寫入到流中。
write(char[])
將一個字符數(shù)組寫入到流中瘦黑。
write(String)
將字符串寫入到流中京革。
flush()
刷新流,將流中的數(shù)據(jù)刷新到目的地中幸斥,流還存在匹摇。
close()
關閉資源。關閉前會先調用flush()
甲葬,刷新流中數(shù)據(jù)到目的地廊勃,然后流關閉。
public static void writeToFile(String path) throws Exception {
// 這里的第二個參數(shù)表示是否為追加
Write write = new FileWiter(path, true);
write.write('中');
write.write("世界".toCharArray());
write.write("中國");
// 這里沒有調用flush()是因為close()會調用flush()
write.close();
}
用字符流拷貝文本文件
public static void copyFile(String path1, String path2) throws Exception {
Reader reader = new FileReader(path1);
Writer writer = new FileWiter(path2);
int ch = -1;
char[] arr = new char[1024];
while((ch = reader.reader(arr)) != -1) {
writer.writer(arr, 0, ch);
}
reader.close();
writer.close();
}
字符流的緩沖區(qū)
緩沖的存在是為了增強流的功能而存在经窖,所以在建立緩沖區(qū)對象時坡垫,先要有流對象存在。
緩沖區(qū)的出現(xiàn)提高了對流的操作效率画侣。原理就是將數(shù)組進行封裝冰悠。
private static void copyFile(File srcFile, File destFile) throws IOException {
// 創(chuàng)建輸入輸出流
FileReader fr = new FileReader(srcFile);
FileWriter fw = new FileWriter(destFile);
// 創(chuàng)建字符輸出流
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
// 拷貝(可以一行一行地讀)
String line = null;
while((line = br.readLine()) != null) {
// 一次寫出一行
bw.write(line);
// 刷新緩沖
bw.flush();
// 換行,readLine方法默認沒有換行配乱,需要手動換行
bw.newLine();
}
// 關閉流
br.close();
bw.close();
}