File类
访问文件和目录
如果希望在程序中操作文件和目录,都可以通过 File 类来完成,不管是文件还是目录都是使用 File 类操作,File 能新建、删除、重命名文件和目录,File 不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。
File 类可以使用文件路径字符串来创建File 实例,该文件路径字符串既可以是绝对路径,也可以是相对路径。默认情况下,系统总是依据用户的工作路径来解释相对路径,这个路径有系统属性“user.dir”指定,通常也是运算 Java 虚拟机时所在的路径。
File 类提供了很多方法来操作文件和目录。
访问文件名相关的方法:
- String getName():返回此 File 对象所表示的文件名或者路径名(如果是路径,则返回一级子路径名)。
- String getPath():返回此 File 对象所对应的路径名。
- File getAbsoluteFile():返回此 File 对象的绝对路径。
- String getAbsolutePath():返回此 File 对象的绝对路径名。
- String getParent():返回此 File 对象所对应目录(最后一级子目录)的父目录名。
- boolean renameTo(File newName):重命名此 File 对象所对应的文件或者目录,如果重命名成功,则返回 true,否则返回 false。
文件检测相关的方法
- boolean exists():判断 File 对象所对应的文件或目录是否存在。
- boolean canWrite():判断 File 对象所对应的文件和目录是否可写。
- boolean canRead():判断 File 对象所对应的文件和目录是否可读。
- boolean isFile():判断 File 对象所对应的是否是文件,而不是目录。
- boolean isDirectory():判断 File 对象所对应的是否是目录,而不是文件。
- boolean isAbsolute():判断 File 对象所对应的文件或目录是否是绝对路径。
获取常规文件信息:
- long lastModified():返回文件的最后修改时间。
- long length():返回文件内容的长度。
文件操作相关的方法:
- boolean createNewFile():当此 File 对象所对应的文件不存在时,该方法将新建一个该 File 对象所指定的新文件,如果创建成功则返回 true,否则返回 false。
- boolean delete():删除 File 对象所对应的文件或者路径。
- static File createTempFile(String prefix,String suffix):在默认的临时文件目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。这是一个静态方法,可以直接通过 File 类来调用。prefix 参数必须至少3字节长。
- static File createTempFile(String prefix,String suffix,File directory):在 directory 所指定的目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。
- void deleteOnExit():注册一个测试钩子,指定当 Java 虚拟机退出时,删除 File 对象所对应的文件和目录。
目录操作相关的方法:
- boolean mkdir():试图创建一个 File 对象所对应的目录,如果创建成功,则返回 true,否则返回 false。调用该方法时 File 对象必须对应一个路径,而不是一个文件。
- String[] list():列出 File 对象的所有子文件和路径,返回 String 数组。
- File[] listFiles():列出 File 对象的所有子文件和路径,返回 File 数组。
- static File[] listRoots():列出系统所有的根路径。
文件过滤器
File 类中的 list() 方法可以接收一个 FilenameFilter 参数,通过该参数可以只列出符合条件的文件。
理解 Java 的 IO 流
Java 的 IO 流是输入/输出的基础,它可以方便地实现数据的输入/输出操作,在 Java 中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“流”,通过流的方式允许 Java 程序使用相同的方式类访问不同的输入/输出源。
流的分类
输入流和输出流
- 输入流:只能从中读取数据,而不能向其写入数据。主要由 InputStream 和 Reader 作为基类。
- 输出流:只能向其写入数据,而不能从中读取数据。主要由 OutputStream 和 Writer 作为基类。
注意:
上面的基类都是抽象基类,无法直接创建实例。
字节流和字符流
字节流和字符流的用法几乎完全一样,区别在于操作的数据单元不同。
- 字节流:操作的数据单元是 8 位的字节,由 InputStream 和OutputStream 作为基类。
- 字符流:操作的数据单元是 816位的字符,由 Reader 和Writer 作为基类。
节点流和处理流
- 节点流:可以从/向一个特定的 IO 设备(如磁盘、网络)读/写数据的流,称为节点流,也被称为低级流。
- 处理流:对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能。处理流也被为高级流。
Java 使用处理流来包装节点流是一种典型的装饰器设计模式,通过使用处理流来包装不同的节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入/输出功能。因此,处理流也被称为包装流。
InputStream 和 Reader
InputStream 和 Reader 是所有输入的流的抽象基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板,所以它们的方法是所有输入流都可以使用的方法。
InputStream中的方法:
- int read():从输入流中读取单个字节,返回所读取的字节数据。
- int read(byte[] b):从输入流中最多读取 b.length 个字节的数据,并将其存储在字节数组 b 中,返回实际读取的字节数。
- int read(byet[] b,int off,int len):从输入流中最多读取 len 个字节的数据,并将其存储在数组 b中,从数组 b 中时,并不是从数组起点开始,而是从 off 位置开始,返回实际读取的字节数。
Reader中的方法:
- int read():从输入流中读取单个字符,返回所读取的字符数据。
- int read(char[] cbuf):从输入流中最多读取 cbuf.length 个字符的数据,并将其存储在字符数组 cbuf 中,返回实际读取的字符数。
- int read(char[] cbuf,int off,int len):从输入流中最多读取 len个字符的数据,并将其存储在字符数组 cbuf 中,放入数组 cbuf 中时,并不是从数组起点开始,而是从 off 位置开始,返回实际读取的字符数。
InputStream 和 Reader 都是抽象类,本身不能创建实例,但它们分别有一个用于读取文件的输入流 :FileInputStream 和 FileReader ,它们都是字节流,会直接和文件管理。
使用字节流读取文件,手动关闭资源:
public class test{
public static void main(String[] args) {
//创建字节输入流实例,构造器中传入文件绝对路径或者相对路径
FileInputStream fis = new FileInputStream("D:\john\study\java\study\HelloWorld.java");
//创建容器,装入读取的字节数据
byte[] bbuf = new byte[1024];
//用保存读取的字节数
int hasRead = 0;
//循环重复读取文件
while((hasRead = fis.read(bbuf)) > 0){
// 将字节转换为字符串输出
System.out.print(new String(bbuf,0,hasRead));
}
//关闭文件输入流,最后放在 finally 块中
fis.close();
}
}
使用字符流,自动关闭资源:
public class test{
public static void main(String[] args) {
//创建字符输入流实例,构造器中传入文件绝对路径或者相对路径,并使用try包裹
try(FileReader fis = new FileReader("D:\\john\\study\\java\\study\\HelloWorld.java");){
//创建容器,装入读取的字节数据
char[] bbuf = new char[32];
// 将字节转换为字符串输出
int hasRead = 0;
//循环重复读取文件
while((hasRead = fis.read(bbuf)) > 0){
System.out.print(new String(bbuf,0,hasRead));
}
}catch (IOException ex){
//打印异常
ex.printStackTrace();
}
}
}
字节流和字符流读取文件并没有太大的差别。只改变了容器和读取类而已。
除此之外,InputStream 和 Reader 还支持几个方法来移动指针。
- void mark(int readAheadLimit):在记录指针当前位置记录一个标记(mark)。
- booleam markSupported():判断此输入流是否支持 mark() 操作,即是否支持记录标记。
- void reset():将此流的记录针重新定位到上一次记录标记(mark)的位置。
- long skip(long n):记录指针向前移动 n 个字节/字符。
OutputStream 和 Writer
OutputStream 与 Writer 提供的三个方法:
- void write(int c):将指定的字节/字符输出到输出流中,其中 c 既可以代表字节,也可以代表字符。
- void write(byte[]