之前我们提到过字符IO流,想了解的可以去看一下这篇博客字符IO流与缓冲流。接下来我们来说说File类,字节流FileInputStream和FileOutputStream以及它们的缓冲流。
一、File类
File类是干什么的呢?File是文件或目录路径的抽象表示形式,它不表示文件,而是路径。File的实例一旦创建就不可改变其所指代的路径。首先,我们还是先从File的构造方法来开始学习,File常用的构造方法有三种:
File(String pathname) :通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(File parent, String child) :根据 路径为parent的File对象 和 child 路径名字符串创建一个新 File 实例。
File(String parent, String child) :根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
public static void main(String[] args) throws IOException {
// File(String pathname):将指定的路径名转换成一个File对象
File file = new File("F:\\a\\b.txt");
System.out.println(file);
// output:F:\a\b.txt
// File(String parent, String child):根据指定的父路径和文件路径创建File对象
File file2 = new File("F:\\a", "b.txt");
System.out.println(file2);
// output:F:\a\b.txt
// File(File parent, String child):根据父路径对象和文件路径创建File对象
File parent = new File("F:\\a");
File file3 = new File(parent, "b.txt");
System.out.println(file3);
// output:F:\a\b.txt
//使用匿名内部类创建File对象
File file4 = new File(new File("F:\\a"), "b.txt");
System.out.println(file4);
// output:F:\a\b.txt
}
然后,我们再来看看File类中有哪些常用方法,File的常用方法有很多,不过都是见名知意的方法,非常的简单。
- 创建功能/删除功能
boolean createNewFile()
boolean mkdir()
boolean mkdirs()
boolean delete()
接下来,我们在实例中学习它们的用法
private static void method1() throws IOException {
//创建File对象,指向的路径为相对当前项目的路径,即项目的根位置
File f1= new File("a.txt");
//boolean createNewFile() :当指定文件不存在时,创建文件并返回true;否则,返回false
System.out.println(f1.createNewFile());
//output:false(说明文件已经存在,创建失败)
//boolean mkdir() : 当指定文件夹不存在时,创建文件夹并返回true;否则,返回false
File f2 = new File("b");
System.out.println(f2.mkdir());
//output:true
//boolean mkdirs() : 创建多级目录
File f3 = new File("c\\d\\e");
System.out.println(f3.mkdirs());
//output:true
//boolean delete() : 删除存在的指定文件或文件夹,成功返回true,否则返回false
System.out.println(f1.delete());
//output:true
System.out.println(f2.delete());
//output:true
System.out.println(f3.delete());
//output:true(这里只删除了c/d/e文件目录中的e)
//删除文件夹时,文件夹下不能有文件夹或文件。同时,删除的文件不经过回收站。
File f4 = new File("c");
File f5 = new File("c\\d");
System.out.println(f4.delete());
//output:false(c文件夹下还有其他文件 因此不能删除,返回false)
System.out.println(f5.delete());
//output:true
System.out.println(f4.delete());
//output:true(c文件夹下没有文件时,才能删除c,返回true)
}
- 判断功能
boolean exists()
boolean isAbsolute()
boolean isDirectory()
boolean isFile()
boolean isHidden()
我们还是来看代码:
private static void method2() {
//创建File对象
File f1 = new File("a.txt");
File f3 = new File("b");
File f2 = new File("f:\\test.txt");
//boolean exists() : 判断文件或文件夹是否存在,存在返回true,否则返回false
System.out.println(f1.exists());
//output:false
//boolean isAbsolute() : 判断File对象指向是否是绝对路径,是返回true。
System.out.println(f1.isAbsolute());
//output:false f1对象存储的为相对地址
System.out.println(f2.isAbsolute());
//output:true f2对象存储的为绝对地址
//boolean isDirectory() : 判断File对象指向的路径是否为文件夹,是返回true。
//boolean isFile() : 判断File对象指向的路径是否为文件,是返回true。
System.out.println(f1.isDirectory());
//output:false a不是目录
System.out.println(f3.isDirectory());
//output:true b是目录
System.out.println(f1.isFile());
//output:true a是文件
System.out.println(f3.isFile());
//output:false b不是文件
//boolean isHidden() : 判断文件是否为隐藏文件,是返回false
System.out.println(f1.isHidden());
//output:false
}
- 获取功能/修改功能
File getAbsoluteFile() String getAbsolutePath()
String getParent() File getParentFile()
String getName() String getPath()
long lastModified() long length()
继续看代码:
private static void method3() {
//创建File对象
File f =new File("d:\\a\\b\\c");
File f2 = new File("a.txt");
// File getAbsoluteFile() :返回File对象指向的绝对路径,返回File对象
// String getAbsolutePath() :返回File对象指向的绝对路径,返回String对象
System.out.println(f.getAbsoluteFile());
System.out.println(f2.getAbsolutePath());
//output1:d:\a\b\c
//output2:d:D:\WorkSpaceEclipseMars\project\a.txt
// File getParentFile() :返回File指向对象的父路径,返回File对象
// String getParent() :返回File指向对象的父路径,返回String对象
System.out.println(f.getParent());
System.out.println(f2.getParentFile());
//output1:d:\a\b
//output2:null (没有指定父路径)
// String getName() : 获取文件或文件夹名称
System.out.println(f.getName());
//output:c
// String getPath() : 返回创建File对象时设置的路径
System.out.println(f.getPath());
System.out.println(f2.getPath());
//output1:d:\a\b\c
//output2:a.txt
File f3 = new File("f:\\test.jpg");
// long lastModified() : 最后的修改时间,返回毫秒值
System.out.println(f3.lastModified());
//output:1533022960822
Date date = new Date(1533022960822L);
System.out.println(date.toLocaleString());
//output:2018-7-31 15:42:40
// long length() : 返回文件的字节数,文件夹无法获取其字节数
System.out.println(f3.length());
//output:80479
}
boolean renameTo(File dest)
private static void method4() {
//原来File对象指向的路径
File f = new File("a.txt");
//要修改的使File指向的路径
File f2 = new File("d.txt");
//boolean renameTo(File dest): 将当前File对象的路径修改为dest指向的路径,返回true;如果dest已存在,则无法修改并返回false
System.out.println(f.renameTo(f2));
//output:true
}
File中其他的几个获取方法,返回值都是数组形式
String[] list()
File[] listFiles()
static File[] listRoots()
private static void method5() {
File f = new File("f:\\test");
// String[] list(): 返回当前路径下所有的文件和文件夹 名称 的数组
// 只有指向文件夹的File才能调用该方法
String[] str1 = f.list();
for (String s : str1) {
System.out.println(s);
}
// output:test.jpg
// test.txt
// File[] listFiles() : 返回当前路径下所有的文件和文件夹的数组
// 只有指向文件夹的File才能调用该方法
File[] file1 = f.listFiles();
for (File file : file1) {
System.out.println(file);
}
// output:f:\test\test.jpg
// f:\test\test.txt
// static File[] listRoots(): 静态方法,返回所有的盘符
File[] file2 = File.listRoots();
for (File file : file2) {
System.out.println(file);
}
// output: C:\
// D:\
// E:\
// F:\
// G:\
// I:\
}
二、IO流分类
流的分类:
按流的方向:输入流,输出流
按处理数据单位:字节流,字符流
按角色的不同:节点流(直接作用在文件),处理流
字节流/字符流 | 抽象类 | 节点流 | 缓冲流(处理流之一) | 传输内容 | |
---|---|---|---|---|---|
输入流 | 字符流 | Reader | FileReader | BufferedReader | 文本文件 |
字节流 | InputStream | FileInputStream | BufferedInputStream | 文本文件,图片,视频等 | |
输出流 | 字符流 | Writer | FileWriter | BufferedWriter | 文本文件 |
字节流 | OutputStream | FileOutputStream | BufferedOutputStream | 文本文件,图片,视频等 |
注:二进制文件必须用字节流,例如图片,音频,视频等(windows记事本打开乱码的文件)。
三、FileInputStream类,FileOutputStream类
这两个类读写数据的方式与FileReader,FileWriter基本一致,唯一的不同在于读取一个数组时,字符流我们用的是char类型的数组,而在字节流中我们使用byte类型的数组。可以参考字符IO流与缓冲流,了解字符流读写方式之后,这里我们看一下代码自然就清楚了。
创建FileInputStream或FileOutputStream对象时,可以传递一个路径的字符串,它们接受String类型的构造函数会自动为我们创建一个File对象。
private static void method2() throws IOException {
//创建字节输入输出流对象
FileInputStream fIStream = null;
FileOutputStream fOStream = null;
try {
//为字节流对象创建所指向的File对象的路径
fIStream = new FileInputStream(new File("f:\\test\\test.jpg"));
fOStream = new FileOutputStream(new File("f:\\test.jpg"));
int len;
//此时用于读写的数组为byte类型
byte[] chs = new byte[1024];
//一次读取一个字节数组的内容,当读取字节个数为0时,返回-1
while ((len = fIStream.read(chs)) != -1)
fOStream.write(chs, 0, len);
} catch (Exception e) {
e.printStackTrace();
} finally {
//无论读写是否成功,最后都要释放资源
fOStream.close();
fIStream.close();
}
}
四、BufferedInputStream类, BufferedOutputStream类
字节缓冲流与字符缓冲流的功能基本一直,它们都属于处理流的一种,都是为了加快读写速度和读写效率,如果我们把节点流当作是一根管道,那么缓冲流就相当于将这个管道加粗,使得在管道内通过相同大小的数据用时更少。
与字符缓冲流用法也是一样的,在创建字节缓冲流时,将字节流对象以参数的形式传递到缓冲流的对象中。
private static void method1() {
//声明字节流引用
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//将引用指向字节流对象,传递字节流对象
bis = new BufferedInputStream(new FileInputStream("f:\\test\\test.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("f:test.jpg"));
int len;
byte[] bys = new byte[1024];
//一次读取一个字节数组并写入
while((len = bis.read(bys))!=-1){
bos.write(bys, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}