一、File
通过调用File类提供的各种方法,能够创建,删除或者重命名文件,判断硬盘上某个文件是否存在,查询文件最后修改时间等。
构造方法
File file = new File("D:\\file\\a.txt");//绝对路劲
File file1 = new File("src\\Hello.java");//相对路劲
System.out.println(file);//D:\file\a.txt
System.out.println(file1);//src\Hello.java
//在Java中,反斜杠“\” 表示转义符,Windows中的目录符号为反斜线“\”,因此用两个斜杆表示。也可以使用“/”表示
常用方法
操作
遍历目录下文件
File file = new File("E:\\Code\\example\\demo7_example\\src\\com\\wyy\\example");
if (file.isDirectory()){//判读是否存在该目录
String[] list = file.list();//将该目录下的文件存放在集合中
for (String name : list){
System.out.println(name);
}
遍历目录下指定类型的文件
File类中提供了一个重载的list(FilenameFilter filter)方法,该方法接收一个FilenameFilter类型的参数。而FilenameFilter是一个接口,被称作文件过滤器,当中定义了一个抽象方法accept(File dir,String name)。
要获取指定类型的文件,需要调用list()方法,实现文件过滤器FilenameFilter,并且在accept()中做出判断。
File file = new File("com/wyy/example");
//过滤器对象
FilenameFilter filter = new FilenameFilter() {
//在accpet方法中实现
@Override
public boolean accept(File dir, String name) {
//获取当前文件对象
File currFile = new File(dir, name);
// 如果文件名以.java结尾返回true,否则返回false
if (currFile.isFile() && name.endsWith(".java")) {
return true;
} else {
return false;
}
}
};
if (file.exists()) { // 判断File对象对应的目录是否存在
String[] lists = file.list(filter); // 获得过滤后的所有文件名数组
for (String name : lists) {
System.out.println(name);
}
整个过程中,file()文件对象调用list()方法传入上面设定好的FilenameFilter文件过滤器对象,接着取出当前Fiel对象所代表的目录下的所有的子目录和文件,而对于每一个子目录和文件,都会调用文件过滤器对象中我们重写的accept(File dir,String name)方法,并且把代表当前目录的File对象以及这个子目录或文件的名字作为参数dir和name传递给方法。最后,如果accept()方法返回true,就将当前遍历的这个子目录或文件添加到数组中,如果返回false,则不添加。
遍历目录下每一层文件包括子目录中的所有内容
如果想得到所有子目录下的File类型对象,list()方法显然不能满足要求,这时需要使用File类提供的另一个方法listFiles()。
public static void main(String[] args) {
File file = new File("D:\\Computer\\tools");
fileDir(file);
}
public static void fileDir(File dir){
File[] files = dir.listFiles();//获取该目录下所有文件的额属数组
for (File file: files){ // 遍历所有的子目录和文件
if (file.isDirectory()){
fileDir(file); // 如果是目录,递归调用fileDir()
}
System.out.println(file.getAbsolutePath());// 输出文件的绝对路径
}
}
删除文件及目录
File file = new File("D:\\hello");
if (file.exists()){
System.out.println(file.delete());
}
上面的代码运行结果为 false,因为delete()方法只能删除一个指定的文件,对于一个目录下存在多个文件,无法将其和删除,只能在当前目录为空的情况下,才能删除成功。若想要一次性完全删除,则需要利用递归一层层的删除。
public static void main(String[] args) {
File file = new File("D:\\hello\\test");
deleteDir(file);
}
public static void deleteDir(File Dir) {
if (Dir.exists()) {
File[] files = Dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
deleteDir(file);
} else {
file.delete();
}
Dir.delete();
}
}
}
二、字节流
概述
在计算机中,所有的文件都是以二进制形式存在的,而对于字节的输入输出IO流提供了一系列的流,称为字节流。根据输入方向可以将其分为字节输入流和字节输出流。
字节流的父类——两个抽象类InputStream和OutputStream,io流中的输入输出都是相对与程序而言的。InputStream是输入,从源输入到程序,OutputStream是输出,从程序输出到目标设备。
读写数据相关方法
InputStream读数据
OutputStream写数据
子类实例
对于Inputsteam和OutStream两个抽象父类而言,并不能被实例化,因此,这两个类提供了不同的子类。
InputStream体系
OutputStream体系
FileIntputStream和FileOutputStream
将文件的内容输入到程序上 ——FileInputstream
public static void main(String[] args) throws Exception {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("E:\\Code\\example\\demo7_example\\src\\com\\wyy\\example\\test.txt");
//在根目录下创建一个test.txt文件,在文件中写入 “abcd”。这里的路劲最好填写绝对路劲,相对路劲容易报找不到该文件的异常错误。
int b = 0;
while (true){
b = inputStream.read();
if (b == -1){
break;
}
System.out.println(b);
}
} finally {
if (inputStream != null){
inputStream.close();
}
}//97 98 99 100
}
将程序上的内容输入到文件中—— FileOutputStream
public static void main(String[] args) throws Exception {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream("E:\\Code\\example\\demo7_example\\src\\com\\wyy\\example\\test2.txt");
String str = "芒果披萨";
byte[] bytes = str.getBytes();
for (int i = 0; i < bytes.length; i++) {
outputStream.write(bytes[i]);
}
} finally {
outputStream.close();
}
}
结果
在这个过程中,FileOUtStrem会创建会直接创建一个文件,在文件中输入对应的字符,若是已经存在文件,会将该文件中的内容先清空,再写入相对应的字符。
如果想要在文件后面追加,则可以使用FileOutputStream(String fileName, boolean append)来创建文件输出流对象,并把append 参数的值设置为true。
将上述代码中这两行进行修改
outputStream = new FileOutputStream("E:\\Code\\example\\demo7_example\\src\\com\\wyy\\example\\test2.txt",true);
String str = "你好";
结果
文件复制
public static void main(String[] args) throws Exception {
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new FileInputStream("source/test.docx");
outputStream = new FileOutputStream("target/test.docx");
int len;
long start = System.currentTimeMillis();
while ((len = inputStream.read()) != -1) {//判断是否读到文件末尾
outputStream.write(len);
}
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start) + "毫秒");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}//消耗时间:2039毫秒
}
实际上以上方式拷贝效率十分低下,相当于外卖员送两份餐到同一单主手上,但他却跑了两次,每一次只拿一份。因此,为了提高效率,引入了缓冲区。
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new FileInputStream("E:\\Code\\example\\demo7_example\\source\\test.docx");
outputStream = new FileOutputStream("E:\\Code\\example\\demo7_example\\src\\com\\wyy\\example\\test.docx");
byte[] buff = new byte[1024];
int len;
long start = System.currentTimeMillis();
while ((len = inputStream.read(buff)) != -1) {//判断是否读到文件末尾
outputStream.write(buff,0,len);
//每循环一次,就从文件读取若干字节填充字节数组,并通过变量len记住读入数组的字节数,
// 然后从数组的第一个字节开始,将len个字节依次写入文件。
}
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start));
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}// 消耗时间:39毫秒
}
}
缓冲区
IO提供两个带缓冲的字节流,分别是BufferedInputStream和BufferedOutputStream,它们的构造方法中分别接收InputStream和OutputStream类型的参数作为对象,在读写数据时提供缓冲功能。
这两个流内部都定义了一个大小为8192的字节数组,调用read()或者write()方法读写数据时,首先将读写的数据存入定义好的字节数组,然后将字节数组的数据一次性读写到文件中。
public static void main(String[] args) throws Exception {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//带缓冲区的输入流
bis = new BufferedInputStream(new FileInputStream("src.txt"));
//带缓冲区的输出流
bos = new BufferedOutputStream(new FileOutputStream("des.txt"));
int len;
while((len = bis.read()) != -1){
bos.write(len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (bis != null){
bis.close();
}
if (bos != null){
bos.close();
}
}
}
三、字符流
概述
字符流父类——两个抽象类Reader和Writer,其中Reader是字符输入流,用于从某个源设备读取字符。Writer是字符输出流,用于向某个目标设备写入字符。
体系
字符流与字节流类似,很多方法都相同。不同的是字符流是char类型,而字节流是String类型。在缓冲区中还有一点不同的是,BufferReader中有readLine方法,BufferWriter中有newLine()方法, 写入一个换行符,该方法会根据不同的操作系统生成相应的换行符。
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader("source.txt"));
bufferedWriter = new BufferedWriter(new FileWriter("target.txt"));
String str;
while(( str = bufferedReader.readLine()) != null){//读一行
bufferedWriter.write(str);//输入一行
bufferedWriter.newLine();//换行
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
bufferedReader.close();
bufferedWriter.close();
}
}
四、转换流
InputStreamReader是Reader的子类,它可以将一个字节输入流转换成字符输入流,方便直接读取字符。OutputStreamWriter是Writer的子类,它可以将一个字节输出流转换成字符输出流,方便直接写入字符。
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
FileInputStream fileInputStream = new FileInputStream("start.txt");//字节输入流
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);//字节流转哈为字符流
bufferedReader = new BufferedReader(inputStreamReader);//创建字符流缓冲区
FileOutputStream outputStream = new FileOutputStream("end.txt");//字节输出流
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);//字节流转换为字符流
bufferedWriter = new BufferedWriter(outputStreamWriter);//创建字符流缓冲区
String line;
while ((line = bufferedReader.readLine()) != null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (bufferedReader != null){
bufferedReader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (bufferedWriter != null){
bufferedWriter.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
针对操作文本文件的字节流进行转换,如果字节流操作的是一张图片,此时转换为字符流就会造成数据丢失。