简单介绍
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 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 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