Java编程的逻辑 (59) - 文件和目录操作

前面两节我们介绍了如何通过流的方式读写文件内容,本节我们介绍文件元数据和目录的一些操作。

文件和目录操作最终是与操作系统和文件系统相关的,不同系统的实现是不一样的,但Java中的java.io.File类提供了统一的接口,底层它会通过本地方法调用操作系统和文件系统的具体实现,本节,我们就来介绍File类。

File类中的操作大概可以分为三类:

  • 文件元数据
  • 文件操作
  • 目录操作

在介绍这些操作之前,我们先来看下File的构造方法。

构造方法

File既可以表示文件,也可以表示目录,它的主要构造方法有:

public File(String pathname)
public File(String parent, String child)
public File(File parent, String child) 

可以是一个参数pathname,表示完整路径,该路径可以是相对路径,也可以是绝对路径。还可以是两个参数,表示父目录的parent和表示孩子的child。

File中的路径可以是已经存在的,也可以是不存在的。

通过new新建一个File对象,不会实际创建一个文件,只是创建一个表示文件或目录的对象,new之后,File对象中的路径是不可变的。

文件元数据

文件名与文件路径

有了File对象后,就可以获取它的文件名和路径信息,相关方法有:

public String getName()
public boolean isAbsolute()
public String getPath()
public String getAbsolutePath()
public String getCanonicalPath() throws IOException
public String getParent()
public File getParentFile()
public File getAbsoluteFile()
public File getCanonicalFile() throws IOException

getName()返回的就是文件或目录名称,不含路径名。isAbsolute()判断File中的路径是否是绝对路径。

getPath()返回构造File对象时的完整路径名,包括路径和文件名称。getAbsolutePath()返回完整的绝对路径名。getCanonicalPath()返回标准的完整路径名,它会去掉路径中的冗余名称如".","..",跟踪软连接(Unix系统概念)等。这三个路径容易混淆,我们看一个例子来说明:

File f = new File("../io/test/students.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println("path: " + f.getPath());
System.out.println("absolutePath: " + f.getAbsolutePath());
System.out.println("canonicalPath: " + f.getCanonicalPath());

这里,使用相对路径来构造File对象,..表示上一级目录,输出为:

/Users/majunchang/io
path: ../io/test/students.txt
absolutePath: /Users/majunchang/io/../io/test/students.txt
canonicalPath: /Users/majunchang/io/test/students.txt

当前目录为/Users/majunchang/io,getPath()返回的就是构造File对象时使用的相对路径,而getAbsolutePath()返回的是完整路径,但是包含冗余路径"../io/",而getCanonicalPath()则去除了该冗余路径。

getParent()返回父目录路径,getParentFile()返回父目录的File对象,需要注意的是,如果File对象是相对路径,则这些方法可能得不到父目录,比如:

File f = new File("students.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println("parent: " + f.getParent());
System.out.println("parentFile: " + f.getParentFile());

输出为:

/Users/majunchang/io
parent: null
parentFile: null

即使是有父目录的,getParent()的返回值也是null。那如何解决这个问题呢?可以先使用getAbsoluteFile()或getCanonicalFile()方法,它们都返回一个新的File对象,新的File对象分别使用getAbsolutePath()和getCanonicalPath()的返回值作为参数构造。比如,修改上面的代码为:

File f = new File("students.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println("parent: " + f.getCanonicalFile().getParent());
System.out.println("parentFile: " + f.getCanonicalFile().getParentFile());

这次,就能得到父目录了,输出为:

/Users/majunchang/io
parent: /Users/majunchang/io
parentFile: /Users/majunchang/io

File类中有四个静态变量,表示路径分隔符,它们是:

public static final String separator
public static final char separatorChar
public static final String pathSeparator
public static final char pathSeparatorChar

separator和separatorChar表示文件路径分隔符,在Windows系统中,一般为"\",Linux系统中一般为"/"。

pathSeparator和pathSeparatorChar表示多个文件路径中的分隔符,比如环境变量PATH中的分隔符,Java类路径变量classpath中的分隔符,在执行命令时,操作系统会从PATH指定的目录中寻找命令,Java运行时加载class文件时,会从classpath指定的路径中寻找类文件。在Windows系统中,这个分隔符一般为‘;‘,在Linux系统中,这个分隔符一般为‘:‘。

文件基本信息

除了文件名和路径,File对象还有如下方法,以获取文件或目录的基本信息:

//文件或目录是否存在
public boolean exists()
//是否为目录
public boolean isDirectory()
//是否为文件
public boolean isFile()
//文件长度,字节数
public long length()
//最后修改时间,从纪元时开始的毫秒数
public long lastModified()
//设置最后修改时间,设置成功返回true,否则返回false
public boolean setLastModified(long time)

对于目录,length()方法的返回值是没有意义的。

需要说明的是,File对象没有返回创建时间的方法,因为创建时间不是一个公共概念,Linux/Unix就没有创建时间的概念。

安全和权限信息

File类中与安全和权限相关的方法有:

//是否为隐藏文件
public boolean isHidden()
//是否可执行
public boolean canExecute()
//是否可读
public boolean canRead()
//是否可写
public boolean canWrite()
//设置文件为只读文件
public boolean setReadOnly()
//修改文件读权限
public boolean setReadable(boolean readable, boolean ownerOnly)
public boolean setReadable(boolean readable)
//修改文件写权限
public boolean setWritable(boolean writable, boolean ownerOnly)
public boolean setWritable(boolean writable)
//修改文件可执行权限
public boolean setExecutable(boolean executable, boolean ownerOnly)
public boolean setExecutable(boolean executable)

在修改方法中,如果修改成功,返回true,否则返回false。在设置权限方法中,ownerOnly为true表示只针对owner,为false表示针对所有用户,没有指定ownerOnly的方法中,ownerOnly相当于是true。

文件操作

文件操作主要有创建、删除、重命名。

创建

新建一个File对象不会实际创建文件,但如下方法可以:

public boolean createNewFile() throws IOException 

创建成功返回true,否则返回false,新创建的文件内容为空。如果文件已存在,不会创建。

File对象还有两个静态方法,可以创建临时文件:

public static File createTempFile(String prefix, String suffix) throws IOException
public static File createTempFile(String prefix, String suffix, File directory) throws IOException

临时文件的完整路径名是系统指定的、唯一的,但可以通过参数指定前缀(prefix)、后缀(suffix)和目录(directory),prefix是必须的,且至少要三个字符,suffix如果为null,则默认为".tmp", directory如果不指定或指定为null,则使用系统默认目录。我们看个例子:

File file = File.createTempFile("upload_", ".jpg");
System.out.println(file.getAbsolutePath());

在我的电脑上的一些运行的输出为:

/var/folders/fs/8s4jdbj51jvcm7vc6lm_144r0000gn/T/upload_8850973909847443784.jpg

删除

File类如下删除方法:

public boolean delete()
public void deleteOnExit()

delete删除文件或目录,删除成功返回true,否则返回false。如果File是目录且不为空,则delete不会成功,返回false,换句话说,要删除目录,先要删除目录下的所有子目录和文件。

deleteOnExit将File对象加入到待删列表,在Java虚拟机正常退出的时候进行实际删除。

重命名

方法为:

public boolean renameTo(File dest) 

参数dest代表重命名后的文件,重命名能否成功与系统有关,如果成功返回true,否则返回false。

目录操作

当File对象代表目录时,可以执行目录相关的操作,如创建、遍历。

创建

有两个方法用于创建目录:

public boolean mkdir()
public boolean mkdirs()

它们都是创建目录,创建成功返回true,失败返回false。需要注意的是,如果目录已存在,返回值是false。这两个方法的区别在于,如果某一个中间父目录不存在,则mkdir会失败,返回false,而mkdirs则会创建必需的中间父目录。

遍历

有如下方法访问一个目录下的子目录和文件:

public String[] list()
public String[] list(FilenameFilter filter)
public File[] listFiles()
public File[] listFiles(FileFilter filter)
public File[] listFiles(FilenameFilter filter)

它们返回的都是直接子目录或文件,不会返回子目录下的文件。list返回的是文件名数组,而listFiles返回的是File对象数组。FilenameFilter和FileFilter都是接口,用于过滤,FileFilter的定义为:

public interface FileFilter {
    boolean accept(File pathname);
}

FilenameFilter的定义为:

public interface FilenameFilter {
    boolean accept(File dir, String name);
}

在遍历子目录和文件时,针对每个文件,会调用FilenameFilter或FileFilter的accept方法,只有accept方法返回true时,才将该子目录或文件包含到返回结果中。

FilenameFilter和FileFilter的区别在于,FileFilter的accept方法参数只有一个File对象,而FilenameFilter的accept方法参数有两个,dir表示父目录,name表示子目录或文件名。

我们来看个例子,列出当前目录下的所有后缀为.txt的文件,代码可以为:

File f = new File(".");
File[] files = f.listFiles(new FilenameFilter(){
    @Override
    public boolean accept(File dir, String name) {
        if(name.endsWith(".txt")){
            return true;
        }
        return false;
    }
});
for(File file : files){
    System.out.println(file.getCanonicalPath());
}

我们创建了个FilenameFilter的匿名内部类对象并传递给了listFiles。

使用遍历方法,我们可以方便的进行递归遍历,完成一些更为高级的功能。

比如,计算一个目录下的所有文件的大小(包括子目录),代码可以为:

public static long sizeOfDirectory(final File directory) {
    long size = 0;
    if (directory.isFile()) {
        return directory.length();
    } else {
        for (File file : directory.listFiles()) {
            if (file.isFile()) {
                size += file.length();
            } else {
                size += sizeOfDirectory(file);
            }
        }
    }
    return size;
}

再比如,在一个目录下,查找所有给定文件名的文件,代码可以为:

public static Collection<File> findFile(final File directory,
        final String fileName) {
    List<File> files = new ArrayList<>();
    for (File f : directory.listFiles()) {
        if (f.isFile() && f.getName().equals(fileName)) {
            files.add(f);
        } else if (f.isDirectory()) {
            files.addAll(findFile(f, fileName));
        }
    }
    return files;
}

前面介绍了File类的delete方法,我们提到,如果要删除目录而目录不为空,需要先清空目录,利用遍历方法,我们可以写一个删除非空目录的方法,代码可以为:

public static void deleteRecursively(final File file) throws IOException {
    if (file.isFile()) {
        if (!file.delete()) {
            throw new IOException("Failed to delete "
                    + file.getCanonicalPath());
        }
    } else if (file.isDirectory()) {
        for (File child : file.listFiles()) {
            deleteRecursively(child);
        }
        if (!file.delete()) {
            throw new IOException("Failed to delete "
                    + file.getCanonicalPath());
        }
    }
}

小结

本节介绍了如何在Java中利用File类进行文件和目录操作,File类封装了操作系统和文件系统的差异,提供了统一的API。

理解了这些操作,我们回过头来,再看下文件内容的操作,前面我们介绍的都是流,除了流,还有其他操作方式,如随机访问和内存映射文件,为什么还需要这些方式?它们有什么特点?适用于什么场合?让我们接下来继续探索。

原文地址:https://www.cnblogs.com/ivy-xu/p/12369470.html

时间: 2024-10-13 14:47:42

Java编程的逻辑 (59) - 文件和目录操作的相关文章

计算机程序的思维逻辑 (59) - 文件和目录操作

前面两节我们介绍了如何通过流的方式读写文件内容,本节我们介绍文件元数据和目录的一些操作. 文件和目录操作最终是与操作系统和文件系统相关的,不同系统的实现是不一样的,但Java中的java.io.File类提供了统一的接口,底层它会通过本地方法调用操作系统和文件系统的具体实现,本节,我们就来介绍File类. File类中的操作大概可以分为三类: 文件元数据 文件操作 目录操作 在介绍这些操作之前,我们先来看下File的构造方法. 构造方法 File既可以表示文件,也可以表示目录,它的主要构造方法有

python之OS模块(对文件or目录操作)

OS模块 os,语义为操作系统,包含普遍的操作系统功能,与具体的平台无关.python编程时,处理文件和目录这些操作,就比如说:显示当前目录下所有文件/删除某个文件/获取文件大小-- os模块不受平台限制,也就是说:当我们要在linux中显示当前命令时就要用到pwd命令,而Windows中cmd命令行下就要用到这个,例如:这时候我们使用python中os模块的os.path.abspath(name)功能,甭管是linux或者Windows都可以获取当前的绝对路径. 常见函数列表 os.name

c++Builder 下的文件及目录操作

转自 http://blog.csdn.net/ktcserver/article/details/936329 一.判断目录是否存在:           C++   Builder中提供了检查文件是否存在的函数FileExists,indows   程序实现如下:           设char   *Dir为带判断的目录       bool   Exist;   //   最后结果,表示目录是否存在       if(Dir[strlen(Dir)]=='//')Dir[strlen(D

第四天 文件和目录操作

7.1 linux 文件系统 linux文件不靠后缀名 内置标识 1.普通文件 - 开头代表 普通文件 文本文件 二进制程序 音频 视频 2.目录文件 d 开头代表 目录文件 3.设备文件 特殊类型文件 /dev (device) ll /dev/rc.d ll /dev/sd* [[email protected] ~]# ll /dev|grep s brw-rw----. 1 root disk 8, 0 Jul 17 20:33 sda brw-rw----. 1 root disk 8

Python文件和目录操作实例代码

对于文件和目录的处理,虽然可以通过操作系统命令来完成,但是Python语言为了便于开发人员以编程的方式处理相关工作,提供了许多处理文件和目录的内置函数.重要的是,这些函数无论是在Unix.Windows还是Macintosh平台上,它们的使用方式是完全一致的. 本文将详细解释这些函数的使用方法.首先,介绍Python语言中类似于Windows系统的dir命令的列出文件功能,然后描述如何测试一个文件名对应的是一个标准文件.目录还是链接,以及提取文件大小和日期的方法.之后,还将介绍如何删除文件和目录

【Linux命令详解】2、文件和目录操作管理

2.文件和目录操作管理 本节主要学习在Linux下如何使用命令对文件和目录进行操作,这些命令pwd.cd.ls等. 2.1 pwd:显示工作目录路径 使用pwd命令可以显示当前用户所处的工作目录的绝对路径. 2.1.1命令语法: pwd[选项] 2.1.2参数选项: 选项 选项含义 -L 目录链接时,输出链接路径 -P 输出物理路径 2.1.3实例: 例1:显示用户当前工作目录路径. [[email protected] ~]# pwd /root //用户当前的工作路径是root 例2:显示用

关于文件、目录操作的函数

删除目录及目录下的文件(user ShellApi单元) function SHMyDelDirectory(const Source: string): boolean;  var fo: TSHFILEOPSTRUCT;  begin  FillChar(fo, SizeOf(fo), 0);  with fo do  begin  Wnd:= 0;   wFunc := FO_Delete;   pFrom := PChar(Source + #0);    pTo    := #0#0;

MFC常用的字符串、文件、目录操作(双11版本)

修改日志: 1.增加了list容器存储: 2.修改了IsFile 和 IsDir的实现,使区别于IfExistFile和IfExistDir; 3.修改了部分函数的名称: 4.其他细节修改: 首先是头文件: /* ******* StrDirFile.h ********** ********* 字符串.文件.目录操作函数声明 ********** */ /* author: autumoon */ #ifndef _STR_DIR_FILE_ #define _STR_DIR_FILE_ #p

python文件和目录操作函数小结

本文主要介绍python文件和目录操作函数小结,主要涉及到os模块和shutil模块的一些方法. python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()返回指定目录下的所有文件和目录名:os.listdir()函数用来删除一个文件:os.remove()删除多个目录:os.removedirs(r"c:\python")检验给出的路径是否是一个文件:os.path.isf