JDK源码(九):File

Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。File对象代表磁盘中实际存在的文件和目录,File类实现了Serializable,表示可以被序列化。File类内部依赖于FileSystem,FileSystem为本地文件系统抽象打包私有抽象类。抽象出了一个 FileSystem 来表示文件系统,不同的操作系统通过继承该类实现各自的文件系统,比如 Windows操作系统则为WinNTFileSystem,而 unix操作系统为 UnixFileStream.需要注意的一点是,WinNTFileSystem类和 UnixFileSystem类并不是在同一个 JDK 里面,也就是说它们是分开的,你只能在 Windows 版本的 JDK 中找到 WinNTFileSystem,而在 unix 版本的 JDK 中找到 UnixFileSystem,同样地,其他操作系统也有自己的文件系统实现类,由于此类方法较多,不一一列举,请看下面的代码注释。

public class DirList {
    public static void main(String args[]) {
        String dirname = "/java";
        File f1 = new File(dirname);
        if (f1.isDirectory()) {
            System.out.println("Directory of " + dirname);
            String s[] = f1.list();
            for (int i = 0; i < s.length; i++) {
                File f = new File(dirname + "/" + s[i]);
                if (f.isDirectory()) {
                    System.out.println(s[i] + " is a directory");
                } else {
                    System.out.println(s[i] + " is a file");
                }
            }
        } else {
            System.out.println(dirname + " is not a directory");
        }
    }
}

源码(1.8)

public class File implements Serializable, Comparable<File>
{
    /**
     * 表示平台本地文件系统的file system对象.
     */
    private static final FileSystem fs = 
                       DefaultFileSystem.getFileSystem();
    /**
     * 此抽象路径名的规范化路径名字符串。
   * 规范化路径名字符串使用默认名称分隔符,
   * 不包含任何重复或冗余的分隔符.
     */
    private final String path;
    /**
     * 指示文件路径状态的枚举类型
     */
    private static enum PathStatus { INVALID, CHECKED };
    /**
     * 指示文件路径是否无效的标志
     */
    private transient PathStatus status = null;
    /**
     * 检查文件的路径是否无效。
   * 目前,对文件路径的检查是非常有限的,
   * 它只包括Nul字符检查。
   * 返回true意味着路径绝对无效/垃圾。
   * 但返回false并不保证路径有效
     */
    final boolean isInvalid() {
        if (status == null) {
            status = 
      (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                       : PathStatus.INVALID;
        }
        return status == PathStatus.INVALID;
    }
    /**
     * 此抽象路径名前缀的长度,如果没有前缀,则为零
     */
    private final transient int prefixLength;
  /**
     * 依赖于系统的默认分隔符字符
   * 在linux下为 "/" ,windows为 "\\"
     */
    public static final char separatorChar = fs.getSeparator();

    /**
     * 默认分隔符,用字符串表示已方便使用
     */
    public static final String separator = "" + separatorChar;

    /**
     * 分割连续路径的分隔符.  This field is
     * linux中为 ":" windows中为 ";"
     */
    public static final char pathSeparatorChar = fs.getPathSeparator();

    /**
     * 分割连续路径的分隔符,用字符串表示已方便使用
     */
    public static final String pathSeparator = "" + pathSeparatorChar;

    /**
     * 返回此路径名前缀的长度.
     */
    int getPrefixLength() {
        return prefixLength;
    }
    /* -- Constructors -- */

    /**
     * 指定路径和前缀长度创建File.
     */
    private File(String pathname, int prefixLength) {
        this.path = pathname;
        this.prefixLength = prefixLength;
    }

    /**
     * 内部构造函数,
   * 参数顺序是为了区分public File(File parent, String child)方法
     */
    private File(String child, File parent) {
        assert parent.path != null;
        assert (!parent.path.equals(""));
        this.path = fs.resolve(parent.path, child);
        this.prefixLength = parent.prefixLength;
    }

    /**
     * 指定路径创建File
     */
    public File(String pathname) {
        if (pathname == null) {
            throw new NullPointerException();
        }
        this.path = fs.normalize(pathname);
        this.prefixLength = fs.prefixLength(this.path);
    }

    /**
     * 以父路径名字符串和子路径名字符串创建File对象
     * 如果父路径为null,则以子路径创建File对象
     * 如果子路径是绝对路径,
   * 则会以系统相关的方式将其转换为相对路径名
     */
    public File(String parent, String child) {
        if (child == null) {
            throw new NullPointerException();
        }
        if (parent != null) {
            if (parent.equals("")) {
        //根据父路径解析子路径名字符串
                this.path = fs.resolve(fs.getDefaultParent(),
                                       fs.normalize(child));
            } else {
                this.path = fs.resolve(fs.normalize(parent),
                                       fs.normalize(child));
            }
        } else {
      //将给定的路径名字符串转换为普通形式。
      //如果字符串已经是正常形式,那么只需返回它
            this.path = fs.normalize(child);
        }
        this.prefixLength = fs.prefixLength(this.path);
    }

    /**
     * 用父路径名和子路径名创建File实例.
     */
    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);
    }

    /**
     * 通过给定的file:uri转换为抽象路径名创建File.
     *
     * file:URI的确切形式依赖于系统,因此此构造函数执行的转换也依赖于系统
     * 如:new File(new URI("file:///c:/a.bat"))
     * @since 1.4
     */
    public File(URI uri) {

        // Check our many preconditions
        if (!uri.isAbsolute())
            throw new IllegalArgumentException("URI is not absolute");
        if (uri.isOpaque())
            throw new IllegalArgumentException("URI is not hierarchical");
        String scheme = uri.getScheme();
        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
            throw new IllegalArgumentException("URI scheme is not \"file\"");
        if (uri.getAuthority() != null)
            throw new IllegalArgumentException("URI has an authority component");
        if (uri.getFragment() != null)
            throw new IllegalArgumentException("URI has a fragment component");
        if (uri.getQuery() != null)
            throw new IllegalArgumentException("URI has a query component");
        String p = uri.getPath();
        if (p.equals(""))
            throw new IllegalArgumentException("URI path component is empty");

        // 如有必要,处理给定的URI路径字符串
        p = fs.fromURIPath(p);
    //替换成系统的分隔符
        if (File.separatorChar != '/')
            p = p.replace('/', File.separatorChar);
    //将给定的路径名字符串转换为普通形式。
    //如果字符串已经是正常形式,那么只需返回它
        this.path = fs.normalize(p);
        this.prefixLength = fs.prefixLength(this.path);
    }

    /**
     * 返回文件或目录的名称
     */
    public String getName() {
        int index = path.lastIndexOf(separatorChar);
        if (index < prefixLength) return path.substring(prefixLength);
        return path.substring(index + 1);
    }

    /**
     *返回父目录的路径名字符串.
     *如果没有就返回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对象
     * @since 1.2
     */
    public File getParentFile() {
        String p = this.getParent();
        if (p == null) return null;
        return new File(p, this.prefixLength);
    }

    /**
     * 返回目录或文件的路径
     */
    public String getPath() {
        return path;
    }

    /**
     * 测试路径名是否为绝对路径名. 
     */
    public boolean isAbsolute() {
        return fs.isAbsolute(this);
    }

    /**
     * 返回绝对路径名字符串.
     *
     * 如果这个抽象路径名已经是绝对路径名,
   * 那么路径名字符串将被简单地返回,就像由getPath方法返回一样。
   * 如果此抽象路径名是空的抽象路径名,
   * 则返回由系统属性user.dir命名的当前用户目录的路径名字符串。
   * 否则,将以系统相关的方式解析此路径名。
   * 在UNIX系统上,相对路径名通过对当前用户目录进行解析而成为绝对路径名。
   * 在Microsoft Windows系统上,相对路径名是绝对的,
   * 方法是根据路径名命名的驱动器的当前目录(如果有)进行解析;
   * 如果没有,则根据当前用户目录进行解析
     */
    public String getAbsolutePath() {
        return fs.resolve(this);
    }

    /**
     * 返回绝对路径的File对象. 
     * @since 1.2
     */
    public File getAbsoluteFile() {
    //获取绝对路径
        String absPath = getAbsolutePath();
        return new File(absPath, fs.prefixLength(absPath));
    }

    /**
     * 返回规范的路径名.
     *
     * 规范路径名既绝对又唯一。
   * 规范形式的精确定义依赖于系统
     * 如果需要,此方法首先将此路径名转换为绝对形式
   * 然后以系统相关的方式将其映射到其唯一形式
   * 并修改驱动器大小写(Windows下)
   * File file = new File("d:");
     * File file1 = new File(file, "jdk_s_d");
     * System.out.println(file1.getCanonicalPath());
   * 输出:D:\jdk_s_d
     * @since   JDK1.1
     */
    public String getCanonicalPath() throws IOException {
        if (isInvalid()) {
            throw new IOException("Invalid file path");
        }
        return fs.canonicalize(fs.resolve(this));
    }

    /**
     * 返回规范的路径File对象
     * @since 1.2
     */
    public File getCanonicalFile() throws IOException {
        String canonPath = getCanonicalPath();
        return new File(canonPath, fs.prefixLength(canonPath));
    }
    //转换路径为URI格式时调用,添加斜线
    private static String slashify(String path, boolean isDirectory) {
        String p = path;
        if (File.separatorChar != '/')
            p = p.replace(File.separatorChar, '/');
        if (!p.startsWith("/"))
            p = "/" + p;
        if (!p.endsWith("/") && isDirectory)
            p = p + "/";
        return p;
    }

    /**
     * 已弃用
     */
    @Deprecated
    public URL toURL() throws MalformedURLException {
        if (isInvalid()) {
            throw new MalformedURLException("Invalid file path");
        }
        return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
    }

    /**
     * 获取文件的URI.
     * URI的确切形式取决于系统。
   * 如果可以确定这个路径名所表示的文件是一个目录,
   * 那么生成的URI将以斜线结尾
   * File file = new File("d:");
     * File file1 = new File(file, "jdk_s_d");
     * System.out.println(file1.toURI());
   * 输出:file:/d:/jdk_s_d/
     * @since 1.4
     */
    public URI toURI() {
        try {
            File f = getAbsoluteFile();
            String sp = slashify(f.getPath(), f.isDirectory());
            if (sp.startsWith("//"))
                sp = "//" + sp;
            return new URI("file", null, sp, null);
        } catch (URISyntaxException x) {
            throw new Error(x);         // Can't happen
        }
    }


    /* -- Attribute accessors -- */

    /**
     * 文件是否可读
     */
    public boolean canRead() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_READ);
    }

    /**
     * 文件是否可写
     */
    public boolean canWrite() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
    }

    /**
     * 文件是否存在
     */
    public boolean exists() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
    }

    /**
     * 文件是否是目录
     */
    public boolean isDirectory() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
                != 0);
    }

    /**
     * 是否是文件
     */
    public boolean isFile() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
    }

    /**
     * 是否是隐藏文件
     * @since 1.2
     */
    public boolean isHidden() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
    }

    /**
     * 返回文件上次修改的时间
   * File file = new File("d:");
     * File file1 = new File(file, "jdk_s_d");
     * System.out.println(file1.lastModified());
   * 输出:1577975690211
     */
    public long lastModified() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getLastModifiedTime(this);
    }

    /**
     * 返回此抽象路径名表示的文件长度。
   * 如果此路径名表示目录,则返回值不定
     * File file1 = new File("d:\\jdk_s_d\\out.txt");
     * System.out.println(file1.length());
   * 输出:134     //测试的out.txt文件大小为134字节
     */
    public long length() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getLength(this);
    }

    /**
     * 创建一个新的空文件,该文件由这个指定的路径名命名,
   * 当且仅当这个名称的文件不存在时。
   * 如果文件不存在,则检查文件的存在和文件的创建,
   * 这是对可能影响文件的所有其他文件系统活动的原子操作.
     * @since 1.2
     */
    public boolean createNewFile() throws IOException {
        SecurityManager security = System.getSecurityManager();
        if (security != null) security.checkWrite(path);
        if (isInvalid()) {
            throw new IOException("Invalid file path");
        }
        return fs.createFileExclusively(path);
    }

    /**
     * 删除此路径名表示的文件或目录。
   * 如果此路径名表示目录,则目录必须为空才能删除.
     */
    public boolean delete() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.delete(this);
    }

    /**
     * 请求在虚拟机终止时删除此抽象路径名表示的文件或目录。
   * 文件(或目录)按注册的相反顺序删除。
   * 调用此方法删除已注册删除的文件或目录无效。
   * 只有在Java语言规范定义的虚拟机正常终止时才会尝试删除
     * @since 1.2
     */
    public void deleteOnExit() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return;
        }
        DeleteOnExitHook.add(path);
    }

    /**
     * 返回一个字符串数组,用于路径名所表示的目录中的文件和目录.
   * File file1 = new File("d:\\jdk_s_d");
     * String[] list = file1.list();
     * for (String f : list) {
     *     System.out.println(f);
     * }
   * 输出jdk_s_d下所有文件和目录
     */
    public String[] list() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return null;
        }
        return fs.list(this);
    }

    /**
     * 返回一个字符串数组,
   * 用于命名此路径名所表示的目录中满足指定筛选器的文件和目录
   * File file1 = new File("d:\\jdk_s_d");
     * String[] list = file1.list(new FilenameFilter() {
     *      @Override
     *       public boolean accept(File dir, String name) {
   *         //列出文件名包含"InputStream"字符串的文件名
     *         return name.contains("InputStream");
     *     }
     *  });
     *  for (String f : list) {
     *      System.out.println(f);
     *  }
     */
    public String[] list(FilenameFilter filter) {
        String names[] = list();
        if ((names == null) || (filter == null)) {
            return names;
        }
        List<String> v = new ArrayList<>();
        for (int i = 0 ; i < names.length ; i++) {
            if (filter.accept(this, names[i])) {
                v.add(names[i]);
            }
        }
        return v.toArray(new String[v.size()]);
    }

    /**
     * 返回一个File数组,表示路径名所表示的目录中的文件.
     *
     * 如果此抽象路径名不表示目录,则此方法返回null。
   * 否则将返回一个File对象数组,
   * 该数组中每个文件或目录对应一个对象。
   * 结果中不包括表示目录本身和目录父目录的路径名。
     * @since  1.2
     */
    public File[] listFiles() {
    //路径下所有文件名
        String[] ss = list();
        if (ss == null) return null;
        int n = ss.length;
    //创建File对象数组
        File[] fs = new File[n];
        for (int i = 0; i < n; i++) {
            fs[i] = new File(ss[i], this);
        }
        return fs;
    }

    /**返回过滤后的File数组
     */
    public File[] listFiles(FilenameFilter filter) {
        String ss[] = list();
        if (ss == null) return null;
        ArrayList<File> files = new ArrayList<>();
        for (String s : ss)
            if ((filter == null) || filter.accept(this, s))
                files.add(new File(s, this));
        return files.toArray(new File[files.size()]);
    }

    /**
     * 返回过滤后的File数组
   * File file1 = new File("d:\\jdk_s_d");
     * File[] list = file1.listFiles(new FileFilter() {
     *    @Override
     *    public boolean accept(File pathname) {
     *        return false;
     *    }
     *});
     */
    public File[] listFiles(FileFilter filter) {
        String ss[] = list();
        if (ss == null) return null;
        ArrayList<File> files = new ArrayList<>();
        for (String s : ss) {
            File f = new File(s, this);
            if ((filter == null) || filter.accept(f))
                files.add(f);
        }
        return files.toArray(new File[files.size()]);
    }

    /**
     * 创建一个目录.
     */
    public boolean mkdir() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.createDirectory(this);
    }

    /**
     * 创建由这个路径名命名的目录,
   * 包括任何必要但不存在的父目录。
   * 注意,如果这个操作失败,
   * 它可能已经成功地创建了一些必要的父目录.
     */
    public boolean mkdirs() {
        if (exists()) {
            return false;
        }
        if (mkdir()) {
            return true;
        }
        File canonFile = null;
        try {
            canonFile = getCanonicalFile();
        } catch (IOException e) {
            return false;
        }

        File parent = canonFile.getParentFile();
        return (parent != null && (parent.mkdirs() || parent.exists()) &&
                canonFile.mkdir());
    }

    /**
     *重命名此路径名表示的文件
   *File file1 = new File("d:\\jdk_a_d");
     *file1.renameTo(new File("d:\\jdk_s_d"));
   *将文件名jdk_a_d重命名为jdk_s_d
     */
    public boolean renameTo(File dest) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
            security.checkWrite(dest.path);
        }
        if (dest == null) {
            throw new NullPointerException();
        }
        if (this.isInvalid() || dest.isInvalid()) {
            return false;
        }
        return fs.rename(this, dest);
    }

    /**
     * 设置此文件或目录的上次修改时间.
     * @since 1.2
     */
    public boolean setLastModified(long time) {
        if (time < 0) throw new IllegalArgumentException("Negative time");
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.setLastModifiedTime(this, time);
    }

    /**
     * 设置文件只读
     * @since 1.2
     */
    public boolean setReadOnly() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.setReadOnly(this);
    }

    /**
     * 设置文件可写
   * @param 如果true,则写入权限仅适用于所有者的写入权限;
   * 否则,它适用于所有人。
   * 如果底层文件系统无法区分所有者的写权限和其他人的写权限,
   * 那么该权限将应用于所有人,而不考虑此值
     * @since 1.6
     */
    public boolean setWritable(boolean writable, boolean ownerOnly) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
    }

    /**
     * 设置文件可写
     *
     * @since 1.6
     */
    public boolean setWritable(boolean writable) {
        return setWritable(writable, true);
    }

    /**
     * 设置文件可读
     * @since 1.6
     */
    public boolean setReadable(boolean readable, boolean ownerOnly) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
    }

    /**
     * 设置文件可读
     * @since 1.6
     */
    public boolean setReadable(boolean readable) {
        return setReadable(readable, true);
    }

    /**
     * 设置文件可执行
     * @since 1.6
     */
    public boolean setExecutable(boolean executable, boolean ownerOnly) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
    }

    /**
     * 设置文件可执行
     * @since 1.6
     */
    public boolean setExecutable(boolean executable) {
        return setExecutable(executable, true);
    }

    /**
     * 文件是否可执行
     * @since 1.6
     */
    public boolean canExecute() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExec(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
    }


    /* -- Filesystem interface -- */

    /**
     * 列出可用的文件系统根目录.
     */
    public static File[] listRoots() {
        return fs.listRoots();
    }
    /**
     * 返回按此路径名命名的分区的大小.
     * @since  1.6
     */
    public long getTotalSpace() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
            sm.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getSpace(this, FileSystem.SPACE_TOTAL);
    }

    /**
     * 返回分区中未分配的字节数
     *
     * @since  1.6
     */
    public long getFreeSpace() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
            sm.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getSpace(this, FileSystem.SPACE_FREE);
    }

    /**
     * 返回分区上此虚拟机可用的字节数
     * @since  1.6
     */
    public long getUsableSpace() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
            sm.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getSpace(this, FileSystem.SPACE_USABLE);
    }

    /* -- Temporary files -- */

    private static class TempDirectory {
        private TempDirectory() { }

        // temporary directory location
        private static final File tmpdir = new File(AccessController
            .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
        static File location() {
            return tmpdir;
        }

        // file name generation
        private static final SecureRandom random = new SecureRandom();
        static File generateFile(String prefix, String suffix, File dir)
            throws IOException
{
            long n = random.nextLong();
            if (n == Long.MIN_VALUE) {
                n = 0;      // corner case
            } else {
                n = Math.abs(n);
            }

            // Use only the file name from the supplied prefix
            prefix = (new File(prefix)).getName();

            String name = prefix + Long.toString(n) + suffix;
            File f = new File(dir, name);
            if (!name.equals(f.getName()) || f.isInvalid()) {
                if (System.getSecurityManager() != null)
                    throw new IOException("Unable to create temporary file");
                else
                    throw new IOException("Unable to create temporary file, " + f);
            }
            return f;
        }
    }

    /**
     * <p> 在指定目录中创建新的空文件,使用给定的前缀和后缀字符串生成其名称:
     *此方法仅提供临时文件工具的一部分。
   *若要安排由此方法创建的文件自动删除,请使用deleteOnExit方法
     * @since 1.2
     */
    public static File createTempFile(String prefix, String suffix,
                                      File directory)
        throws IOException
{
        if (prefix.length() < 3)
            throw new IllegalArgumentException("Prefix string too short");
        if (suffix == null)
            suffix = ".tmp";

        File tmpdir = (directory != null) ? directory
                                          : TempDirectory.location();
        SecurityManager sm = System.getSecurityManager();
        File f;
        do {
            f = TempDirectory.generateFile(prefix, suffix, tmpdir);

            if (sm != null) {
                try {
                    sm.checkWrite(f.getPath());
                } catch (SecurityException se) {
                    // don't reveal temporary directory location
                    if (directory == null)
                        throw new SecurityException("Unable to create temporary file");
                    throw se;
                }
            }
        } while ((fs.getBooleanAttributes(f) & FileSystem.BA_EXISTS) != 0);

        if (!fs.createFileExclusively(f.getPath()))
            throw new IOException("Unable to create temporary file");

        return f;
    }

    /**
     * 创建临时文件
     */
    public static File createTempFile(String prefix, String suffix)
        throws IOException
{
        return createTempFile(prefix, suffix, null);
    }

    /* -- Basic infrastructure -- */

    /**
     * 比较两个File路径名,此方法定义的顺序取决于底层系统
     * 在UNIX系统中,字母大小写在比较路径名时非常重要;
   * 而在Microsoft Windows系统中则不是。
     * @since   1.2
     */
    public int compareTo(File pathname) {
        return fs.compare(this, pathname);
    }

    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof File)) {
            return compareTo((File)obj) == 0;
        }
        return false;
    }

    public int hashCode() {
        return fs.hashCode(this);
    }

    /**
     * 返回路径名
     */
    public String toString() {
        return getPath();
    }

    /**
     * 调用WriteObject以保存此文件名。
   * 分隔符也将被保存,
   * 以便在路径在其他主机类型上重新组合时可以替换它.
     */
    private synchronized void writeObject(java.io.ObjectOutputStream s)
        throws IOException
{
        s.defaultWriteObject();
        s.writeChar(separatorChar); // Add the separator character
    }

    /**
     * 调用readObject以还原此文件名。
   * 读取原始分隔符字符。
     */
    private synchronized void readObject(java.io.ObjectInputStream s)
         throws IOException, ClassNotFoundException
{
        ObjectInputStream.GetField fields = s.readFields();
        String pathField = (String)fields.get("path", null);
        char sep = s.readChar(); // read the previous separator char
        if (sep != separatorChar)
            pathField = pathField.replace(sep, separatorChar);
        String path = fs.normalize(pathField);
        UNSAFE.putObject(this, PATH_OFFSET, path);
        UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));
    }

    private static final long PATH_OFFSET;
    private static final long PREFIX_LENGTH_OFFSET;
    private static final sun.misc.Unsafe UNSAFE;
    static {
        try {
            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
            PATH_OFFSET = unsafe.objectFieldOffset(
                    File.class.getDeclaredField("path"));
            PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
                    File.class.getDeclaredField("prefixLength"));
            UNSAFE = unsafe;
        } catch (ReflectiveOperationException e) {
            throw new Error(e);
        }
    }


    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 301077366599181567L;

    // -- Integration with java.nio.file --

    private volatile transient Path filePath;

    public Path toPath() {
        Path result = filePath;
        if (result == null) {
            synchronized (this) {
                result = filePath;
                if (result == null) {
                    result = FileSystems.getDefault().getPath(path);
                    filePath = result;
                }
            }
        }
        return result;
    }
}

更多精彩内容,请关注微信公众号:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐楠_01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值