如果要学好IO,那么必须清楚抽象类,IO的操作部分重点掌握两个代码模型。整个IO的核心组成:五个类(File,OutputStream,InputStream,Wtiter,Reader)一个接口(Serializable)
在java.io包之中File类是唯一一个与文件本身操作(文件的创建,删除,取得文件信息等等)有关的程序类,
File类的基本使用
java.io.File类是一个普通的类,所以这个类使用字节产生实例化对象即可,如果要实例化对象有两种方法
构造方法一:public File(String pathname)
构造方法二:public File(String parent,String child) 设置父路径和子文件夹
如果要想进行文件的基本操作,可以使用File类的基本方法:
创建一个新文件:public boolean createNewFile()throws IOException
删除文件:public boolean delete()
判断文件是否存在:public boolean exists()
范例:创建新文件
1 package cn.Tony.demo; 2 3 import java.io.File; 4 5 public class TestDemo{ 6 public static void main(String[] args) throws Exception { 7 File file=new File("D:\IO\Hello.txt");//定义要操作的文件路径 8 file.createNewFile();//创建新文件 9 } 10 }
File类只是创建文件的本身
范例:编写一个文件的基本操作
如果文件不存在则进行一个创建,如果文件存在则进行删除
1 package cn.Tony.demo; 2 3 import java.io.File; 4 5 public class TestDemo{ 6 public static void main(String[] args) throws Exception { 7 File file=new File("D:\IO\Hello.txt");//定义要操作的文件路径 8 if(file.exists()) { 9 file.delete(); 10 }else { 11 file.createNewFile();//创建新文件 12 } 13 } 14 }
以实现了最简化的文件处理操作,但是此时有两个问题
1.对于项目的开发只有Windows(MacBook)最好用,但是在实际的项目部署环境都要求在UNIX Linux之中;那么这个时候路径的问题就很麻烦了,windows使用的是“”,而UNIX下使用的都是“/”。所以一般在使用路径分隔符的时候都会采用File类的一个常量来描述:public static final String separator;
1 //由不同的操作系统的JVM来决定最终的separator是什么内容 2 File file=new File("D:"+File.separator+"IO"+File.separator+"Hello.txt");//定义要操作的文件路径
2.因为java里面如果要进行文件的处理操作是要通过本地操作系统支持的,如果有同名文件就出现有延迟的问题
目录操作
在之前创建的文件在根目录下直接进行的控制,那么如果说现在有目录出现,则以上的代码将无法执行。
范例:错误的代码
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 //由不同的操作系统的JVM来决定最终的separator是什么内容 6 File file=new File("D:"+File.separator+"Hello"+File.separator+"IO"+File.separator+"Hello.txt");//定义要操作的文件路径 7 if(file.exists()) { 8 file.delete(); 9 }else { 10 file.createNewFile();//创建新文件 11 } 12 } 13 }
Exception in thread "main" java.io.IOException: 系统找不到指定的路径。
因为现在没有父路径所以无法找到。那么该如果取得父路径呢?在File类中有如下的方法:
取得父路径:public File getParentFile()
因为我们是要进行父目录的创建,所以此处最好取得父路径的File类对象;
创建父目录:public boolean mkdir()
创建多级父目录:public boolean mkdirs()
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 //由不同的操作系统的JVM来决定最终的separator是什么内容 6 File file=new File("D:"+File.separator+"Hello"+File.separator+"IO"+File.separator+"Hello.txt");//定义要操作的文件路径 7 if(!file.getParentFile().exists()) {//如果父目录不存在 8 file.getParentFile().mkdirs();//File父目录创建 9 } 10 if(file.exists()) { 11 file.delete(); 12 }else { 13 file.createNewFile();//创建新文件 14 } 15 } 16 }
在以后的开发之中此父目录的判断有可能会经常出现
取得文件信息
在File类里面有很多取得文件信息的操作方法
判断路径是否是文件:public boolean isFile()
判断路径是否是目录:public boolean isDirectory()
取得文件大小(字节):public long length()
最后一次修改日期:public long lastModified()
范例:取得文件信息
package cn.Tony.demo; import java.io.File; import java.text.SimpleDateFormat; class MyMath{ public static double round(double num,int scale) { return Math.round(num*Math.pow(10, scale))/Math.pow(10, scale); } } public class TestDemo{ public static void main(String[] args) throws Exception { File file=new File("D:"+File.separator+"IO"+File.separator+"llh.png");//要操作的文件 if(file.exists()&&file.isFile()) {//必须保证文件存在才可以取得相应的信息 System.out.println("文件大小:"+MyMath.round(file.length()/(double)1024/1024,2)); System.out.println("文件最后修改日期:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(file.lastModified())); } } }
以上操作都行针对文件进行的信息取得,而通过目录进行相应的信息取得目录中的全部组成:public File[] listFiles()
范例:列出目录中的全部组成
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 File file=new File("D:"+File.separator);//要操作的文件 6 if(file.exists()&&file.isDirectory()) { 7 File data[]=file.listFiles(); 8 for(int x=0;x<data.length;x++) { 9 System.out.println(data[x]); 10 } 11 12 } 13 } 14 }
以上的这些操作可以取得本地的文件的相关信息
File类综合操作:列出子目录内容
虽然File类本身提供有listFile()方法,这个方法本身只能列出本目录的第一级信息,如果要求列出目录中所有级的信息,则就必须自己来实现处理。这种操作就必须通过递归的模式完成了。
范例:实现该操作
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 File file=new File("D:"+File.separator);//要操作的文件 6 listDir(file);//必须执行开始 7 } 8 /** 9 * 列出指定目录的全部子目录信息 10 * @param file 11 */ 12 public static void listDir(File file){ 13 if(file.isDirectory()) {//判断file是否为目录 14 File data[]=file.listFiles(); 15 if(data!=null) { 16 for(int x=0;x<data.length;x++) { 17 listDir(data[x]); 18 } 19 } 20 } 21 System.out.println(file); 22 } 23 }
线程阻塞问题:
现在所有的代码都是在main线程下完成的,如果列出的操作不完成,后续操作不完成,这种耗时的操作,给主线程带来了阻塞,而导致后续代码无法正常执行完毕,不想让阻塞产生,那么产生一个新的线程处理。
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 new Thread(() ->{ 6 File file=new File("D:"+File.separator);//要操作的文件 7 listDir(file);//必须执行开始 8 },"线程开始") .start(); 9 System.out.println("开始"); 10 } 11 /** 12 * 列出指定目录的全部子目录信息 13 * @param file 14 */ 15 public static void listDir(File file){ 16 if(file.isDirectory()) {//判断file是否为目录 17 File data[]=file.listFiles(); 18 if(data!=null) { 19 for(int x=0;x<data.length;x++) { 20 listDir(data[x]); 21 } 22 } 23 } 24 System.out.println(file); 25 } 26 }
1 package cn.Tony.demo; 2 import java.io.File; 3 public class TestDemo{ 4 public static void main(String[] args) throws Exception { 5 new Thread(() ->{ 6 File file=new File("D:"+File.separator);//要操作的文件 7 listDir(file);//必须执行开始 8 },"线程开始") .start(); 9 System.out.println("开始"); 10 } 11 /** 12 * 列出指定目录的全部子目录信息 13 * @param file 14 */ 15 public static void listDir(File file){ 16 if(file.isDirectory()) {//判断file是否为目录 17 File data[]=file.listFiles(); 18 if(data!=null) { 19 for(int x=0;x<data.length;x++) { 20 listDir(data[x]); 21 } 22 } 23 } 24 file.delete(); 25 } 26 }