一、简介

File类是“文件”和“目录名”的抽象表示形式。因此在java语言中,File类既可以表示文件也可以表示目录。

尽管java.io定义的大多数类是实行流式操作的,而File类则不是,它没有指定信息怎样从文件读取或向文件存储。File描述了文件本身的属性,直接处理文件和文件系统,是唯一一个与文件本身有关的操作。

1.1 File的继承与实现接口

File 直接继承于Object,实现了Serializable接口和Comparable接口。

public class File implements Serializable, Comparable<File>
  • File类实现Serializable接口,意味着File对象支持序列化操作。
  • File类实现Comparable接口,意味着File对象之间可以比较大小,此外File能直接被存储在有序集合(如TreeSet、TreeMap中)。
结构图如下:

1.2 File使用注意事项

1、创建File类对象时要注意的地方

    首先我们要区分两个名词:“绝对路径”和“相对路径”。
    绝对路径:即完整的路径,比如:D:\MyCode\Java\FileDemo
    相对路径:会在代码所在的地方生成,比如:res/jay.txt  就会在你代码的目录下成jay.txt文件
   另外,由于路径名字符或者是抽象路径名的转换与生俱来就是依赖于系统的。比如在Unix系统中,绝对路径名的前缀总是“/”,然而在Windows系统中,绝对路径名的前缀总是”\”。
关于前缀的解决办法:
例1:在Windows中,路劲名为D:\Program Files
在java程序中,必须将”\”转换为”/”或者”\\”,比如:D:/Program Files或者D:\\Program Files
 
如果想让程序跨平台的话,由于Linux中是”/”,而Windows中是”\”,我们可以使用File提供的常量字符串File.separator,它能根据系统平台的不同,自动转换成”/”还是”\\”。

1.3 File的常见方法

1)判断文件或者目录是否存在:  exists()

2)判断是否为目录:   isDirectory()

3)判断是否为文件:   isFile()

4)判断文件是否可读:    canRead()

5)判断文件是否可写:    canWrite()

6)判断文件是否隐藏:    isHidden()

7)判断文件路径是否为绝对路径:  isAbsolute()

8)判断文件路径是否相同:  equals():返回true,false       

                                        compareTo():是否相等,相等返回0,小于返回负数,大于返回正数

9)获取文件的绝对路径:   getAbsolutePath()

10)获取文件名称:  getName()

11)获取文件大小:  length()

12)获取文件最后被修改的时间 :  lastModified()

13)获取文件的路径:   getPath()

14)获取文件的上层文件的目录:   getParent()

15)创建一个新文件:    createNewFile()

16)创建一个新目录:    mkdir()

17)删除文件或目录:  delete()

18)修改文件的名称:   renameTo(str)

19)修改文件为只读:  setReadOnly()

20)修改最后的修改时间:   setLastModified(long time)

二、源码分析

2.1 成员变量

所有成员变量如下:
下面列举一些比较关键的成员变量
// The FileSystem object representing the platform's local file system.
// 获取本地文件系统
private static final FileSystem fs = DefaultFileSystem.getFileSystem(); // 文件路径名
private final String path; // 标记文件路径是否无效
private transient PathStatus status = null; // The length of this abstract pathname's prefix, or zero if it has no prefix.
private final transient int prefixLength; /**
     * The system-dependent default name-separator character.  This field is
     * initialized to contain the first character of the value of the system
     * property <code>file.separator</code>.  On UNIX systems the value of this
     * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
     *
*/
public static final char separatorChar = fs.getSeparator(); // The system-dependent path-separator character, represented as a string for convenience.
public static final String pathSeparator = "" + pathSeparatorChar;
1、成员变量 fs 是如何获取到本地文件系统的呢?
Windows平台下,所下载的JDK中,我们找到了WinNTFileSystem文件系统

Linux呢?因此,下了个Linux版本的JDK,解压,找到rt.jar。然后java/io目录中,找到了UnixFileSystem类。真相大白了!

其实是根据不同的平台,安装不同版本的JDK,根据平台下对应版本的JDK,加载本地文件系统。

解决了fs这个成员变量,那么separatorChar 这个成员变量就迎刃而解了。

2.2 构造函数

1、首先看看整体如下:

2、挑选比较有代表性的方法进行讲解
1) File(String pathname)
public File(String pathname) {
    if (pathname == null) {
        throw new NullPointerException();
    }
    this.path = fs.normalize(pathname);
    this.prefixLength = fs.prefixLength(this.path);
}

该构造方法主要是初始化了path、prefixLength两个成员变量,其中path通过WinNTFileSystem中normalize 公开方法将其规范化。

规范化后的好处,比如

public static void main(String[] args)
{
    File file = new File("d:/test.txt");
    System.out.println(file.getPath());   
}

File:

public String getPath() {
    return path;
}
输出结果:d:\test.txt
主要我们输入的是pathname = "d:/test.txt"  然而path得到的是"d:\test.txt” 。
2)File(File parent, String child)
public File(File parent, String child) {
    if (child == null) {
        throw new NullPointerException();
    }
    if (parent != null) {
        if (parent.path.equals("")) {
            this.path = fs.resolve(fs.getDefaultParent(),
                                   fs.normalize(child));
        } else {
            this.path = fs.resolve(parent.path,
                                   fs.normalize(child));
        }
    } else {
        this.path = fs.normalize(child);
    }
    this.prefixLength = fs.prefixLength(this.path);
}
其目的还是为path、prefixLength两个成员变量赋值。
其中,fs.resolve(parent.path,fs.normalize(child));目的就是在合理范围内拼接父与子路径

2.3 创建操作

  • createNewFile
  • createTempFile
  • mkdir

1)createNewFile()

public boolean createNewFile() throws IOException {
    // 1、检查是否有权限对该文件进行操作
    SecurityManager security = System.getSecurityManager();
    if (security != null) security.checkWrite(path);

// 2、检查文件路径是否有效
    if (isInvalid()) {
        throw new IOException("Invalid file path");
    }

// 3、在Windows中,调用WinNTFileSystem中createFileExclusively方法,该方法是调用系统底层方法。
    return fs.createFileExclusively(path);
}

 
2)mkdir()
// 此方法创建此抽象路径名的目录。
public boolean mkdir() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(path);
    }
    if (isInvalid()) {
        return false;
    }
    return fs.createDirectory(this);
}

2.4 删除操作

  • delete
  • deleteOnExit
1)delete()

public boolean delete() {
    // 1、权限检查
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkDelete(path);
    }

// 2、检查文件路径是否有效
    if (isInvalid()) {
        return false;
    }
   
    // 3、调用系统本地底层删除方法,
    // 不过在删除之前做了一些清理,cache.clear();prefixCache.clear();
    return fs.delete(this);
}

而deleteOnExit 一般用在删除临时文件。
注意:file.delete()或file.deleteOnExit()方法只能删除文件或空文件夹
2.5 获取文件操作
1)getAbsoluteFile()
// Returns the absolute form of this abstract pathname. Equivalent to new File(this.getAbsolutePath()). 
public File getAbsoluteFile() {
    String absPath = getAbsolutePath();
    return new File(absPath, fs.prefixLength(absPath));
}
2)getCanonicalFile()
// Returns the canonical form of this abstract pathname. Equivalent to new File(this.getCanonicalPath()). 
public File getCanonicalFile() throws IOException {
    String canonPath = getCanonicalPath();
    return new File(canonPath, fs.prefixLength(canonPath));
}
2.6 获取路径操作
1)getAbsolutePath()
// 此方法返回此抽象路径名的绝对路径名字符串。
public String getAbsolutePath() {
    return fs.resolve(this);
}
2)getCanonicalPath()
// 此方法返回此抽象路径名的规范路径名字符串。
public String getCanonicalPath() throws IOException {
    if (isInvalid()) {
        throw new IOException("Invalid file path");
    }
    return fs.canonicalize(fs.resolve(this));
}
3)getPath()
// 此方法此抽象路径名转换为一个路径名字符串。
// Converts this abstract pathname into a pathname string
// 此处pathname与File(String pathname)中pathname一致
public String getPath() {
    return path;
}

4)getParent()

// 此方法返回此抽象路径名的父路径名的字符串,或者null,如果此路径名没有指定父目录。
public String getParent() {
    // 查找最后分隔符的位置
     int index = path.lastIndexOf(separatorChar);
     if (index < prefixLength) {
         if ((prefixLength > 0) && (path.length() > prefixLength))
             return path.substring(0, prefixLength);
         return null;
     }
    // 获取最后分隔符之前的所有字符
     return path.substring(0, index);
}
 
由于File中的源码基本上调用系统底层的API,故不再介绍。
 
 
 
 
 
 
 
参考:

3、图解 Java IO : 一、File源码

java File详解的更多相关文章

  1. Java Annotation详解 理解和使用Annotation

    系统中用到了java注解: 查了一下如何使用注解,到底注解是什么: (1)创建方法:MsgTrace Java Class==> 在Create New Class中: name:输入MsgTr ...

  2. Java ClassLoad详解

    Java ClassLoad详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1. ...

  3. Java NIO 详解(一)

    一.基本概念描述 1.1 I/O简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通 ...

  4. Java IO 详解

    Java IO 详解 初学java,一直搞不懂java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂.而且没有结合到java7 的最新技术,所以自己来整理一下,有错的话请指正, ...

  5. Java集合详解3:Iterator,fail-fast机制与比较器

    Java集合详解3:Iterator,fail-fast机制与比较器 今天我们来探索一下LIterator,fail-fast机制与比较器的源码. 具体代码在我的GitHub中可以找到 https:/ ...

  6. Java ClassLoader详解(转载)

    Java ClassLoader详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK ...

  7. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  8. 黑马----JAVA迭代器详解

    JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...

  9. C++调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

随机推荐

  1. Design Pattern Explained 读书笔记二——设计模式序言

    设计模式的由来: 20 世纪 90 年代初,一些聪明的开发者偶然接触到 Alexander(Christopher Alexander 的建筑师) 有关模式的工作.他们非常想知道,在建筑学成立的理论, ...

  2. Centos中安装vim

    Centos, 默认没有安装VIM, 所以要当然要安装了, 直接yum install vim是不行的, 首先: yum install vim* 会看到vim-enhanced这个包,没错, 我们要 ...

  3. 大作业 XXX大学 课程管理系统

    #include<stdio.h> #include<iostream> #include<string.h> #include <fstream> # ...

  4. android的ListView做表格添加圆角边框

    边框,圆角,都可以实现的 在drawable目录下添加view_yuan_morelist.xml,设置控件的边框代码.如下: <?xml version="1.0" enc ...

  5. ASC(1)G(上升时间最长的序列)

    G - Beautiful People Time Limit: 10000/5000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Other ...

  6. 已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)

    操作SQLServer数据库时.遇到这种问题:已超过了锁请求超时时段. (Microsoft SQL Server,错误: 1222) 经过查找材料了解为资源抢占,照成死锁,杀死进程就OK了.详细操作 ...

  7. select poll使用

    select poll使用     2.1. 怎样管理多个连接?“我想同一时候监控一个以上的文件描写叙述符(fd)/连接(connection)/流(stream),应该怎么办?” 使用 select ...

  8. Unity手游之路&lt;七&gt;角色控制器

    我们要控制角色的移动,能够所有细节都由自己来实现.控制角色模型的移动,同一时候移动摄影机,改变视角.当然Unity也提供了一些组件,能够让我们做更少的工作,实现我们所期望的功能.今天我们就一起系统来学 ...

  9. devenv.exe - Assert Failure visual studio 2010

    安装完成devexpress后启动vs提示 devenv.exe - assert failure  第一种在博客园找到的解决方案: 原因是机器上安装了framework 4.5 和4.5中文包,卸载 ...

  10. Objective-C /iphone开发基础:分类(category,又称类别)

    在c++中我们可以多继承来实现代码复用和封装使程序更加简练.在objective-c中只能单继承,不能多继承,那么除了协议protocol之外,我们可以实现类似多继承的一个方法就是,分类(catego ...