[TOC]
# 文件操作
## 什么是文件
文件是計算機中基本的數據存儲形式,在實際的存儲數據中,如果對數據的讀寫速度要求不高,而且存儲的數據量也不是很大,此時,可以選擇使用文件這種持久化的存儲方式。
所謂**持久化**,就是當程序退出,或者計算機關機以后,數據還是存在的。但是在程序內存中的數據會在程序關閉或計算機退出時丟失。
文件的組成:路徑+文件的全名(文件名和文件后綴)。
關于文件后綴:只是定義了文件的打開方式不一樣,如果更改后綴不會對文 件的內部數據產生變化。
在不同的操作系統中,文件的路徑表示形式是不一樣的。
比如:
`windows c:\windows\system\driver.txt`
`Linux /user/my/tomcat/startup.txt`
> 如果程序需要在不同的操作系統中運行,那么如果出現文件路徑相關的設置時,必須要進行操作系統的判斷,特別是windows和Linux關于斜杠的區別。
## 絕對路徑和相對路徑
絕對路徑指文件的完整路徑,例如:c:\hello\hello.java。該路徑包含文件的路徑和文件的文件名即后綴。
使用該路徑可以唯一的找到該文件。但是,在不同的操作系統下,文件的絕對路徑表現形式是不一樣的。這樣就會比較麻煩。
相對路徑是書寫文件的部分路徑:
如下文件結構
~~~
D
└─test
│ a.txt
│
└─A
b.txt
~~~
如使用 `D:\test` 作為基準目錄
* a.txt 相對路徑:a.txt
* b.txt 相對路徑:A\b.txt
如使用D:\text\A作為基準目錄
* a.txt的相對路徑:..\a.txt
* b.txt的相對路徑:b.txt
> 在Java中\是轉義字符,如果要是\進行路徑的描述時,要使用“\\”表示。
**相對路徑**
Java 中文件的相對路徑是相對 JVM 的啟動路徑而言的。
表現當前路徑的方式:`.` 、`.\`、 `不使用任何的符號`;
一個點表示當前路徑,兩個點”..”表示上級目錄。
在大部分的應用程序中,我們都會使用相對路徑去構建文件。
## File 類
> 為了方便的通過Java對文件進行基本的處理,在 `java.io` 包中設計了 File 類。
> File只能表現文件本身和目錄(文件中的內容不在File類的管理范疇內),即文件和文件夾都是用File代表。
### 創建一個文件對象
使用絕對路徑或者相對路徑創建File對象
```
package com.dodoke.util;
import java.io.File;
public class TestFile {
public static void main(String[] args) {
// 絕對路徑
File f1 = new File("d:/testfile");
System.out.println("f1的絕對路徑:" + f1.getAbsolutePath());
// 相對路徑,在Eclipse中,就是項目的目錄
File f2 = new File("Hero.java");
System.out.println("f2的絕對路徑:" + f2.getAbsolutePath());
// 把f1作為父目錄,創建文件的對象
File f3 = new File(f1,"Hero.java");
System.out.println("f3的絕對路徑:" + f3.getAbsolutePath());
}
}
```
### 文件的常用方法1
注意1: 需要在D:\testfile確實存在一個Hero.java,才可以看到對應的文件長度、修改時間等信息
注意2: renameTo方法用于對物理文件名稱進行修改,但是并不會修改File對象的name屬性。
```
package com.dodoke.util;
import java.io.File;
import java.util.Date;
public class TestFile2 {
public static void main(String[] args) {
File f = new File("d:/testfile/Hero.java");
System.out.println("當前文件是:" + f);
// 文件是否存在
System.out.println("判斷是否存在:" + f.exists());
// 是否是文件夾
System.out.println("判斷是否是文件夾:" + f.isDirectory());
// 是否是文件(非文件夾)
System.out.println("判斷是否是文件:" + f.isFile());
// 文件長度
System.out.println("文件長度:" + f.length());
// 文件最后修改時間
long time = f.lastModified();
Date d = new Date(time);
System.out.println("獲取文件的最后修改時間:" + d);
// 文件重命名
File f2 = new File("d:/testfile/ADHero.java");
f.renameTo(f2);
System.out.println("把Hero.exe改名為ADHero.java");
System.out.println("注: 需要在D:\testfile確實存在一個Hero.java,才可以看到對應的文件長度、修改時間等信息");
}
}
```
### 文件常用方法2
```
package com.dodoke.util;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class TestFile3 {
public static void main(String[] args) throws IOException {
File f = new File("d:/testfile");
// 以字符串數組的形式,返回當前文件夾下的所有文件(不包含子文件及子文件夾)
System.out.println(Arrays.toString(f.list()));
// 以文件數組的形式,返回當前文件夾下的所有文件(不包含子文件及子文件夾)
File[] fs = f.listFiles();
System.out.println(Arrays.toString(fs));
// 以字符串形式返回獲取所在文件夾
System.out.println(f.getParent());
// 以文件形式返回獲取所在文件夾
System.out.println(f.getParentFile());
File f1 = new File("d:/testfile/skin/demmo.ski");
// // 創建文件夾,如果父文件夾skin不存在,創建就無效
// System.out.println(f1.mkdirs());
// // 創建文件夾,如果父文件夾skin不存在,就會創建父文件夾
// System.out.println(f1.mkdirs());
// 創建一個空文件,如果父文件夾skin不存在,就會拋出異常
System.out.println(f1.createNewFile());
// 所以創建一個空文件之前,通常都會創建父目錄
System.out.println(f1.getParentFile().mkdirs());
// 列出所有的盤符c: d: e: 等等
System.out.println(Arrays.toString(f1.listRoots()));
// 刪除文件
System.out.println(f1.delete());
}
}
```
# 練習
## 1. 遍歷文件夾
一般說來操作系統都會安裝在C盤,所以會有一個 C:\WINDOWS目錄。
遍歷這個目錄下所有的文件(不用遍歷子目錄)
找出這些文件里,最大的和最小(非0)的那個文件,打印出他們的文件名
> 注: 最小的文件不能是0長度
```
package com.dodoke.util;
import java.io.File;
import java.io.IOException;
public class TestFile4 {
public static void main(String[] args) throws IOException {
File f = new File("c:\\windows");
File[] fs = f.listFiles();
if (null == fs) {
return;
}
long minSize = Integer.MAX_VALUE;
long maxSize = 0;
File minFile = null;
File maxFile = null;
for (File file : fs) {
if (file.isDirectory()) {
continue;
}
if (file.length() != 0 && file.length() < minSize) {
minSize = file.length();
minFile = file;
}
if (file.length() > maxSize) {
maxSize = file.length();
maxFile = file;
}
}
System.out.printf("最小的文件是%s,其大小是%d字節%n", minFile.getAbsolutePath(), minFile.length());
System.out.printf("最大的文件是%s,其大小是%d字節%n", maxFile.getAbsolutePath(), maxFile.length());
}
}
```
## 2. 遍歷子文件夾
同上的練習,要求遍歷子文件夾
> 使用遞歸來進行文件夾的遍歷
```
package com.dodoke.util;
import java.io.File;
import java.io.IOException;
public class TestFile5 {
static long minSize = Integer.MAX_VALUE;
static long maxSize = 0;
static File minFile = null;
static File maxFile = null;
public static void main(String[] args) throws IOException {
File f = new File("c:\\windows");
listFiles(f);
System.out.printf("最小的文件是%s,其大小是%d字節%n", minFile.getAbsolutePath(), minFile.length());
System.out.printf("最大的文件是%s,其大小是%d字節%n", maxFile.getAbsolutePath(), maxFile.length());
}
private static void listFiles(File f) {
if (f.isFile()) {
if (f.length() != 0 && f.length() < minSize) {
minSize = f.length();
minFile = f;
}
if (f.length() > maxSize) {
maxSize = f.length();
maxFile = f;
}
}
if (f.isDirectory()) {
File[] fs = f.listFiles();
if (null != fs) {
for (File file : fs) {
listFiles(file);
}
}
}
}
}
```