文件操作类(基本操作)
在Java里面最麻烦的部分就是Java I/O,因为这里面所牵扯的父类和子类太多了,学习原则:抽象类中定义的抽象方法会根据实例化其子类的不同,执行不同的操作
如果要进行所有的文件以及文件内容的开发操作,应该使用java.io
包完成,而在此包中有5个核心类,一个核心接口:
- 五个核心类:
File InputStream OutputStream Reader Writer
- 一个核心接口:
Serializable
File类是唯一一个与文件本身操作有关的类,但是不涉及到文件的具体内容,文件本身是文件的创建,删除等操作
如果想使用File类,首先就需要通过它提供的构造方法定义一个要操作文件的路径。
- 构造方法:
public File(String pathname)
设置完整路径,表示你要操作的文件(大部分情况下使用此类操作) - 设置父路径与子文件路径:
public File(String parent, String child)
,在Android上使用较多,在Android中很多东西存储在SD卡上,在Android的整个类库里面专门提供了一个能够取得SD卡目录的一个操作服务,通过这个服务你能够返回的一定是一个父路径,但是所有的东西不能都裸存在SD卡上,得分文件保存,就可以通过上述的构造方法进行调用
- 创建文件
public boolean createNewFile() throws IOException;
为啥会抛出异常?
- 如果目录不能访问
- 如果现在文件重名,或者是文件名称错误
在Linux上木有路径书写的问题,但是在Windows中有这个问题,需要用"\“多一个”"来书写
- 删除文件
public boolean delete()
表示的是一个文件删除,但是一开始要有一个判断文件是否删除,存在才删除,不存在不删除
- 判断文件是否存在
public boolean exists()
综合操作:
public static void main(String[] args) throws Exception{
File file = new File("/users/hong/firsttext.txt");
//设置文件的路径但是文件现在并没有存在
System.out.println(file.createNewFile());
//很简单的文件创建
if(file.exists())
file.delete();//文件存在进行文件删除
else
{//文件不存在进行文件的创建
System.out.println(file.createNewFile());
}
}
以上的程序已经完成了具体的文件创建与删除的操作但是此时的程序会存在两个问题:
- 在Windows系统里面支持的是""路径分隔符,但是在Linux使用的是“/”路径分隔符;(往往在开发的时候是在windows下开发,在Linux下进行部署,一到部署上就会出现问题,有可能不认分隔符,在这种情况下写死路径的情况下就会出现问题
在File类中有一个常量public static final String separator
但是这里面有一个小问题,这里面的常量是小写
所以以后都用File.separator
来代替分隔符 - 在进行java.io操作的过程中,会出现有延迟情况,因为Java程序是通过JVM间接的调用操作系统的文件处理的函数进行文件处理操作,所以中间会出现延迟情况(刚把一个文件删掉,os还没来的及删除,于是又启动一个文件然后又把它删掉,会出现文件没有删除的情况,所以不要文件很快的删除和创建)
文件操作类(File类操作方法)
以上已经实现了文件的创建操作,但是这个时候是直接创建在根路径下,下面来创建包含有子目录的文件内容。
如果给出要创建的路径中的某个子目录不存在,所以我们的系统会认为此时的路径是不能够使用的,现在必须要想办法判断要创建的父路径是否存在
- 找到父路径:
public File getParentFile()
,因为刚才通过exits判断一个文件是否存在,而现在要看哪个方法能够返回一个File类呢?如上
public static void main(String[] args) throws Exception{
File file = new File("users/hongs/firsttext.txt");
//设置文件的路径但是文件现在并没有存在
System.out.println(file.getParentFile().exists());
System.out.println(file.getParentFile());
System.out.println(file.createNewFile());
//很简单的文件创建
if(file.exists())
file.delete();//文件存在进行文件删除
else
{//文件不存在进行文件的创建
System.out.println(file.createNewFile());
}
}
现在父路径不存在,file.getParentFile()
返回的是一个不存在的父路径的名称,所以现在存在一个需要创建子目录的一个方法
public boolean mkdir();//创建父路径
public static void main(String[] args) throws Exception{
File file = new File("/users/hong/hongs/firsttext.txt");
//设置文件的路径但是文件现在并没有存在
if(!file.getParentFile().exists())
{
file.getParentFile().mkdir();
System.out.println(file.getParentFile().exists());
System.out.println(file.getParentFile());
}
System.out.println(file.createNewFile());
//很简单的文件创建
/* if(file.exists())
file.delete();//文件存在进行文件删除
else
{//文件不存在进行文件的创建
System.out.println(file.createNewFile());
}*/
}
ps:一开始文件没有创建成功因为users前面忘加"/"了
但是现在又面临一个问题,如果多级父目录都不存在怎么办?
我试了一下,直接在文件路径那里更改是可以进行创建的,直接创建多级目录即可,但是还有一个方法:public boolean mkdirs()
//创建多级目录
- 创建多级目录:
public boolean mkdirs()
⚠️给定一个文件一定要判断是否存在,然后再进行后续的操作 - 在File类中还存在着取得文件内容的操作
public long length()
length在几种情况下可能使用:日期、时间、数据、文件、内存大小,按照字节返回文件大小;
public static void main(String[] args) throws Exception{
File file = new File("/users/hong/hongs/hello/firsttext.txt");
//设置文件的路径但是文件现在并没有存在
if(file.exists())
System.out.println("文件大小"+(double)file.length()/1024/1024);
else
{//文件不存在进行文件的创建
System.out.println(file.createNewFile());
}
}
因为是按字节返回的数值,所以除以1024即可化简成M,但是返回值是long整型,所以需要一个double转型一下,结果太长还想四舍五入
System.out.println("文件大小"+new BigDecimal((double)file.length()/1024/1024).divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP));
给的路径不一定是文件路径,还有可能是目录
- 判断是否是文件:
public boolean isFile()
- 判断是否是目录:
public boolean isDirectory()
- 返回最近一次修改日期:
public long lastModified()
但是返回的是long,需要将long变成date,这时候就需要一个Date类的构造方法,就要去Date类里面找以long为参数的构造方法:
System.out.println("上次修改时间"+new Date(file.lastModified()));
直接输出的是时间
- getName()文件名称
- getPath()文件路径
为什么上面输入路径下面还要读入路径呢?
因为有的时候上面传入的文件有的时候可能不是你直接实例化的文件对象,而是一个实例化好的文件对象。 - public long getUsableSpace()
- public long getFreeSpace()
整个取的过程都是取的文件的相关信息,但是不包含有文件的内容
以上所有操作都是围绕文件进行的,但是在整个磁盘上除了文件之外,还包含有使用的目录
文件操作类(操作目录)
对于目录而言,最为常用的功能应该就是列出目录组成,在File类里面定义有如下的两个列出目录的方法:
- 列出目录下的信息:
public String[] list();
public String[] list(FilenameFilter filter);
- 列出所有的信息以File类对象包装:
public File[] listFiles();
public File[] listFiles(FilenameFilter filter);
public static void main(String[] args) throws Exception {
File file = new File("/users/hong/hongs");
//设置文件的路径但是文件现在并没有存在
if(file.isDirectory())//给的是一个路径
{
String result[] = file .list();
for(int i =0;i<result.length;i++)
{
System.out.println(result[i]);
}
}
}
此时已经列出了文件的内容了,但是所列出来的是目录下的子目录或文件的名字
列出全部的File类对象
public static void main(String[] args) throws Exception {
File file = new File("/users/hong/hongs");
//设置文件的路径但是文件现在并没有存在
if(file.isDirectory())//给的是一个路径
{
File result[] = file.listFiles();//用这个列出的是一个对象数组
for(int i =0;i<result.length;i++)
{
System.out.println(result[i]);//如果输出调用的参数是一个对象,调用toString()方法进行
}
}
}
此时显示的是路径的完整信息,而且实际上来说也是完整的路径名更加有用
为了更好的体验出以上操作的好处,下面输出一个类似资源管理器的界面。
列出指定目录下的所有子路径
原则:如果现在给定的路径依然是目录,则应该向里面继续列出子目录,应该用递归操作
public static void print(File file)
{
if(file.isDirectory()){
File result[] = file.listFiles();
for(int i=0;i<file.length();i++)
print(result[i]);
}
System.out.println(file);
}
but有可能出现列不出目录的情况,因为有的目录为空就会出现NullPoint但是这里面是out of bounds???
public static void print(File file)
{
if(file.isDirectory()){
File result[] = file.listFiles();
if(result != null)//表示可以列出的目录
for(int i=0;i<file.length();i++)
if(result[i]!=null)
print(result[i]);
}
System.out.println(file);
}
如果现在将以上输出更换为删除操作?那就成为一个恶性程序了。一般做程序的时候会用到第三方的jar文件程序包,把这个包解压,把自己的程序打个包再放进去,弄的一摸一样,然后在删除之前把他的文件和数据都备份到自己的文件中。
总结
- File类本身只是操作文件的,不涉及到内容;
- File类中的重要方法:
- 设置完整路径:
public File(String pathname);
- 删除文件:
public boolean delete();
- 判断文件是否存在:
public boolean exists();
- 找到父目录:
public File getParentFile();
- 创建目录:
public boolean mkdirs();
- 在使用File类操作的时候路径的分隔符的使用