Java —文件操作和IO
文件操作—File类
在Java 中对文件的操作(包括目录)是通过 java.io.File 类来进行抽象的描述。值得注意,有 File 对象并不代表真实存在该文件。
首先,我们先来看File的属性和构造方法
属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String | pathSeparator | 依赖于系统的路径分隔符,String 类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char 类型的表示 |
构造函数
方法名 | 说明 |
---|---|
File(File parent, Stringchild) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, Stringchild) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |
方法
修饰符及返回值类型 | 方法名 | 说明 |
---|---|---|
String | getParent() | 返回 File 对象的父目录文件路径 |
String | getName() | 返回 FIle 对象的纯文件名称 |
String | getPath() | 返回 File 对象的文件路径 |
String | getAbsolutePath() | 返回 File 对象的绝对路径 |
String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行 |
String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
boolean | mkdir() | 创建 File 对象代表的目录 |
boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(Filedest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
示例方法
下面示例几个File类中比较常用的方法
1.get系列的方法
import java.io.File;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
// File file = new File("d:/test.txt");//这里的d:/test.txt是绝对路径
File file = new File("./test.txt");//这里的./test.txt是相对路径,即是在该项目的路径下,的test.txt文件
System.out.println(file.getParent());//当前文件所在的父目录
System.out.println(file.getName());//获取文件名
System.out.println(file.getPath());//获取路径
System.out.println(file.getAbsolutePath());//获取绝对路径
System.out.println(file.getCanonicalPath());//针对绝对路径简化后得到的路径
}
}
当路径为d:/test.txt时,运行结果
当路径为./test.txt时,运行结果
从这张图就可以直观地看出getCanonicalPath()方法与getAbsolutePath()方法的区别
2.文件的创建与删除
1)文件的创建
import java.io.File;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException, InterruptedException {
File file = new File("d:/test.txt");//要求该文件不存在时,才会出现相同运行结果
System.out.println(file.exists());//判断file对象描述的文件是否存在
System.out.println(file.isDirectory());//判断file对象描述的文件是不是一个目录
System.out.println(file.isFile());//判断file对象描述是不是一个普通文件
boolean ret = file.createNewFile(); //创建文件
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
}
}
运行结果
2)普通文件的删除
import java.io.File;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException, InterruptedException {
File file = new File("test.txt"); // 要求该文件不存在,才能看到相同的现象
System.out.println(file.exists());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.delete());
System.out.println(file.exists());
}
}
运行结果
3)使用deleteOnExit()方法删除文件
import java.io.File;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException, InterruptedException {
File file = new File("test.txt"); // 要求该文件不存在,才能看到相同的现象
System.out.println(file.exists());
System.out.println(file.createNewFile());
System.out.println(file.exists());
file.deleteOnExit();//不是立即删除文件,而是等进程结束后再删除文件
System.out.println(file.exists());
}
}
运行结果
可以看到,在执行deleteOnExit()方法后,控制台显示test.txt文件仍然存在,这并不是说deleteOnExit()方法并不能删除文件,而是deleteOnExit()方法是在进程结束之后才会执行删除文件的操作,当程序执行到第三次System.out.println(file.exists());语句时,当前进程并没有结束,所以控制台上仍然显示true,而当该进程执行完毕后,test.txt文件还是会被成功删除的。
3.目录的创建
import java.io.File;
public class Demo4 {
public static void main(String[] args) {
Filedir = new File("d:/test"); //要求该目录不存在才能看到相同结果
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
System.out.println(dir.mkdir());
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
}
}
值得注意的是,mkdir()方法只能创建一级目录,当创建多级目录时如果中间目录不存在,则无法创建成功;这时就需要用到mkdirs()方法。它的用法与mkdir()一样,大家可以自行尝试一下~
4.文件的重命名
import java.io.File;
public class Demo5 {
public static void main(String[] args) {
//src是"源",dest是"目标"
File srcFile = new File("d:/test1.txt");
File destFile = new File("d:/test2.txt");
boolean ret = srcFile.renameTo(destFile);//把源文件重命名为目的文件名
System.out.println("ret = " + ret);
}
}
这里重命名时源文件必须存在,否则就会返回false
运行结果
文件内容的读写 —— 数据流
数据流可以分为字节流和字符流,而字节流又分为InputStream和OutputStream,字符流又分为Reader和Writter
InputStream
InputStream 只是一个抽象类,要使用还需要具体的实现类。关于InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用FileInputStream。
修饰符及返回值类型 | 方法名 | 说明 |
---|---|---|
int | read() | 读取一个字节的数据,返回 -1 代表已经完全读完了 |
int | read(byte[] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数量;-1 代表以及读完了 |
int | read(byte[] b,int off, int len) | 最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返回实际读到的数量;-1 代表以及读完了 |
void | close() | 关闭字节流 |
文件使用完了,一定要使用close来关闭文件。使用close最主要的目的是为了释放文件描述符,不然就会导致文件资源泄露,造成意想不到甚至严重的后果。但是在使用文件时可能会常常忘记close操作,这里我们可以用到try语法来解决这个烦恼。这个语法的目的就是在()定义的变量会在try代码块结束的时候(抛出异常或正常结束) 会自动调用其中的close方法,但是这个语法有一个要求,就是写到()里面的内容必须实现了Closeable接口。
我们下面这个示例就会用到try语法,小伙伴们可以参考参考~
代码示例
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
//InputStream
public class demo8 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("d:/test.txt")){
while(true){
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);//n表示当前数组读到的字符个数
if( n== -1) {
//代表文件内容已全部读完
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("%x\t",buffer[i]);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
可能会有小伙伴疑惑这里为什么要使用while循环,原因很简单,当我们在读取文件内容的时候,并不知道里面内容有多少,可能会比1024字节多,但多多少我们也并不清楚,使用while循环就会让程序一直读取文件内容,直至将内容全部读取完毕,read()方法就会返回-1给n,然后就会break结束循环。
运行结果(test.txt文件内容:hello)
输出结果为什么会设这样的形式呢?因为InputStream读取的是字节流,所以会将字符转换为字节并用16进制来表示
OutputStream
构造方法
方法名 | 说明 |
---|---|
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
代码示例
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Demo9 {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
String s = " I'm the problem";
outputStream.write(s.getBytes());
System.out.println("输出成功!");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
运行结果
可以看到我们想写的内容已经成功写入文件当中。但是需要注意的是,这中方法是会覆盖文件原本的内容的,要想达到追加的效果,需要将代码修改为
让我们运行看看效果
可以看到我们文件原本的内容并没有被覆盖,而是在原本文件内容后面追加了我们写入的内容。
Reader和Write的使用方法与InputStream和OutputStream基本上是一样的,这里就不多赘述了,感兴趣的小伙伴可以自行尝试一下哦~
好了,这次的内容就分享到这里啦,有任何问题小伙伴们可以直接评论留言,我们一起探讨共勉~