Java IO体系之File

简单介绍

Java.io.File类主要是完成了文件夹管理的命名、查询文件属性和处理目录等操作,它不进行文件夹内容的读取操作。

源码分析

继承关系

实现了java.io.Serializable接口,java.lang.Comparable接口【内比较器】

public class File
    implements Serializable, Comparable<File>

成员变量

/**
 * The FileSystem object representing the platform's local file system.
 * 表示平台本地文件系统的文件系统对象。
 */
private static final FileSystem fs = DefaultFileSystem.getFileSystem();

/**
* This abstract pathname's normalized pathname string. 
* 文件抽象路径
*/
private final String path;

/**
* Enum type that indicates the status of a file path.
* 表示地址是否合法的enum类
*/
private static enum PathStatus { INVALID, CHECKED };

/**
* The flag indicating whether the file path is invalid.
* 标记文件路径是否无效
*/
private transient PathStatus status = null;


/**
* The length of this abstract pathname's prefix, or zero if it has no
* prefix.
* 抽象路径名的前缀的长度,如果没有前缀,则为0。使用transient修饰符表示持久化时忽略该属性。
*/
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>.
 * 名称分隔符,在UNIX系统中此字段值是’/’,在WINDOWS系统中此字符的值是’\\’。
 */
public static final char separatorChar = fs.getSeparator();

/**
 * The system-dependent default name-separator character, represented as a
 * string for convenience.  This string contains a single character, namely
 * <code>{@link #separatorChar}</code>.
 */
public static final String separator = "" + separatorChar;

/**
 * The system-dependent path-separator character.  
 * 路径分割符,在UNIX系统中此字段值是':',在WINDOWS系统中此字符的值是';'。
 */
public static final char pathSeparatorChar = fs.getPathSeparator();

/**
 * The system-dependent path-separator character, represented as a string
 * for convenience.  This string contains a single character, namely
 * <code>{@link #pathSeparatorChar}</code>.
 */
public static final String pathSeparator = "" + pathSeparatorChar;

构造函数

/**
 * Internal constructor for already-normalized pathname strings.
 */
private File(String pathname, int prefixLength) {
    this.path = pathname;
    this.prefixLength = prefixLength;
}

/**
 * Internal constructor for already-normalized pathname strings.
 * The parameter order is used to disambiguate this method from the
 * public(File, String) constructor.
 */
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;
}

/**
 * Creates a new <code>File</code> instance by converting the given
 * pathname string into an abstract pathname.  If the given string is
 * the empty string, then the result is the empty abstract pathname.          
 */
public File(String pathname) {
    if (pathname == null) {
        throw new NullPointerException();
    }
    this.path = fs.normalize(pathname);
    this.prefixLength = fs.prefixLength(this.path);
}


/**
 * Creates a new <code>File</code> instance from a parent pathname string
 * and a child pathname string.
 */
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);
}

/**
 * Creates a new <code>File</code> instance from a parent abstract
 * pathname and a child pathname string.
 */
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);
}

/**
 * Creates a new <tt>File</tt> instance by converting the given
 * <tt>file:</tt> URI into an abstract pathname.
 */
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");

    // Okay, now initialize
    p = fs.fromURIPath(p);
    if (File.separatorChar != '/')
        p = p.replace('/', File.separatorChar);
    this.path = fs.normalize(p);
    this.prefixLength = fs.prefixLength(this.path);
}

常用方法

/**
 * Check if the file has an invalid path. 
 */
final boolean isInvalid() {
    if (status == null) {
        status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                   : PathStatus.INVALID;
    }
    return status == PathStatus.INVALID;
}

/**
 * Returns the length of this abstract pathname's prefix.
 * For use by FileSystem classes.
 */
int getPrefixLength() {
    return prefixLength;
}

/**
* Returns the name of the file or directory denoted by this abstract
* pathname.  
* 返回文件名称或者对象对应的最后一个路径字符串。
*/
public String getName() {
   int index = path.lastIndexOf(separatorChar);
   if (index < prefixLength) return path.substring(prefixLength);
   return path.substring(index + 1);
}

/**
 * Returns the pathname string of this abstract pathname's parent, or
 * <code>null</code> if this pathname does not name a parent directory.
 * 返回当前File对象的上级路径名称
 */
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);
}

/**
* Returns the abstract pathname of this abstract pathname's parent,
* or <code>null</code> if this pathname does not name a parent
* directory.
* 返回当前对象的上级目录的File对象
*/
public File getParentFile() {
   String p = this.getParent();
   if (p == null) return null;
   return new File(p, this.prefixLength);
}


/**
 * @return  The string form of this abstract pathname
 */
public String getPath() {
    return path;
}

/**
* Tests whether this abstract pathname is absolute.  The definition of
* absolute pathname is system dependent.  On UNIX systems, a pathname is
* absolute if its prefix is <code>"/"</code>.  On Microsoft Windows systems, a
* pathname is absolute if its prefix is a drive specifier followed by
* <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
* 判定当前File对象是否是绝对路径。
*/
public boolean isAbsolute() {
   return fs.isAbsolute(this);
}


/**
* Returns the absolute pathname string of this abstract pathname.
*/
public String getAbsolutePath() {
  return fs.resolve(this);
}

/**
* Returns the absolute form of this abstract pathname.  Equivalent to
* <code>new&nbsp;File(this.{@link #getAbsolutePath})</code>.
*/
public File getAbsoluteFile() {
  String absPath = getAbsolutePath();
  return new File(absPath, fs.prefixLength(absPath));
}



/**
 * Returns the canonical pathname string of this abstract pathname.
 */
public String getCanonicalPath() throws IOException {
    if (isInvalid()) {
        throw new IOException("Invalid file path");
    }
    return fs.canonicalize(fs.resolve(this));
}


/**
 * Returns the canonical form of this abstract pathname.  Equivalent to
 * <code>new&nbsp;File(this.{@link #getCanonicalPath})</code>.
 */
public File getCanonicalFile() throws IOException {
    String canonPath = getCanonicalPath();
    return new File(canonPath, fs.prefixLength(canonPath));
}

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;
}



/**
* Constructs a <tt>file:</tt> URI that represents this abstract pathname.
*/
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
  }
}


/**
* Tests whether the application can read the file denoted by this
* abstract pathname. 
*/
public boolean canRead() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkRead(path);
   }
   if (isInvalid()) {
       return false;
   }
   return fs.checkAccess(this, FileSystem.ACCESS_READ);
}




/**
* Tests whether the application can modify the file denoted by this
* abstract pathname. 
*/
public boolean canWrite() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkWrite(path);
   }
   if (isInvalid()) {
       return false;
   }
   return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
}



/**
* Tests whether the file or directory denoted by this abstract pathname
* exists.
* 判断抽象路径名称给定的文件或者路径是否存在
*/
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);
}

/**
* Tests whether the file denoted by this abstract pathname is a
* directory.
* 判断给定File对象是否是一个目录对象。
*/
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);
}

/**
* Tests whether the file denoted by this abstract pathname is a normal
* file.  
* 判断File对象给定的路径名称是否是一个规范的文件
*/
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);
}

/**
* Tests whether the file named by this abstract pathname is a hidden
* file. 
* 判断抽象路径名指定的文件是否是一个隐藏的文件
*/
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);
}

/**
* Returns the time that the file denoted by this abstract pathname was
* last modified.
*/
public long lastModified() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkRead(path);
   }
   if (isInvalid()) {
       return 0L;
   }
   return fs.getLastModifiedTime(this);
}

/**
* Returns the length of the file denoted by this abstract pathname.
* The return value is unspecified if this pathname denotes a directory.
* 返回给定的抽象路径名称的文件长度。
*/
public long length() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkRead(path);
   }
   if (isInvalid()) {
       return 0L;
   }
   return fs.getLength(this);
}


/**
* Atomically creates a new, empty file named by this abstract pathname if
* and only if a file with this name does not yet exist.  The check for the
* existence of the file and the creation of the file if it does not exist
* are a single operation that is atomic with respect to all other
* filesystem activities that might affect the file.
* 自动的创建一个新的空的文件,以给定的抽象路径名称为文件名
*/
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);
}


/**
 * Deletes the file or directory denoted by this abstract pathname.  If
 * this pathname denotes a directory, then the directory must be empty in
 * order to be deleted.
 */
public boolean delete() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkDelete(path);
    }
    if (isInvalid()) {
        return false;
    }
    return fs.delete(this);
}



/**
* Returns an array of strings naming the files and directories in the
* directory denoted by this abstract pathname.
* 返回此抽象路径名指定的文件或者目录的集合
*/
public String[] list() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkRead(path);
   }
   if (isInvalid()) {
       return null;
   }
   return fs.list(this);
}

/**
 * Returns an array of strings naming the files and directories in the
 * directory denoted by this abstract pathname that satisfy the specified
 * filter.  
 */
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()]);
}


/**
 * Returns an array of abstract pathnames denoting the files in the
 * directory denoted by this abstract pathname.
 * 返回此抽象路径名指定的文件或者目录下的所有文件的集合
 */
public File[] listFiles() {
    String[] ss = list();
    if (ss == null) return null;
    int n = ss.length;
    File[] fs = new File[n];
    for (int i = 0; i < n; i++) {
        fs[i] = new File(ss[i], this);
    }
    return fs;
}



/**
* Returns an array of abstract pathnames denoting the files and
* directories in the directory denoted by this abstract pathname that
* satisfy the specified filter.  
*/
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()]);
}

/**
* Creates the directory named by this abstract pathname.
* 创建此抽象路径名指定的目录
*/
public boolean mkdir() {
   SecurityManager security = System.getSecurityManager();
   if (security != null) {
       security.checkWrite(path);
   }
   if (isInvalid()) {
       return false;
   }
   return fs.createDirectory(this);
}

/**
* Creates the directory named by this abstract pathname, including any
* necessary but nonexistent parent directories.  Note that if this
* operation fails it may have succeeded in creating some of the necessary
* parent directories.
*/
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());
}

参考文档:
1. https://blog.csdn.net/yaomingyang/article/details/79360277

猜你喜欢

转载自blog.csdn.net/thebigdipperbdx/article/details/80545234
今日推荐