[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);
}
}
}
}
}
```