jdk1.8 java.io.File類源碼閱讀

public class File
    implements Serializable, Comparable<File>

實現了序列化和內部比較器Comparable.
內部比較方法

 public int compareTo(File pathname) {
        return fs.compare(this, pathname);
    }
 private static final FileSystem fs = DefaultFileSystem.getFileSystem();

fs屬性是DefaultFileSystem.getFileSystem();返回的

class DefaultFileSystem {

    /**
     * Return the FileSystem object for Windows platform.
     */
    public static FileSystem getFileSystem() {
        return new WinNTFileSystem();
    }
}

默認是WinNTFileSystem

class WinNTFileSystem extends FileSystem 

WinNTFileSystem 繼承的FileSystem,並且該類是修飾符是默認的,只能同一個包下才能訪問.
ps:對比分析https://cloud.tencent.com/developer/article/1333744

abstract class FileSystem

FileSystem類簡介https://blog.csdn.net/yaomingyang/article/details/79347284
FileSystem類方法詳解:https://blog.csdn.net/yaomingyang/article/details/79351330(該類主要是對文件和路徑的一些操作,該類是抽象的,需要不同系統下的類實現該方法,例如wind系統下的類爲WinNTFileSystem )
compareTo(File pathname)方法爲WinNTFileSystem 下的:

  @Override
    public int compare(File f1, File f2) {
        return f1.getPath().compareToIgnoreCase(f2.getPath());
    }

@Test

    @Test
    public void testFileCompare(){
        File file1 =new File("F:\\FileStudy\\test1.text");
        File file2 =new File("F:\\FileStudy\\test2.text");
        System.out.println(file1.compareTo(file2));
        File file3 =new File("F:\\FileStudy\\test2.text");
        File file4 =new File("F:\\FileStudy\\test1.text");
        System.out.println(file3.compareTo(file4));
        File file5 =new File("F:\\FileStudy\\test1.text");
        File file6 =new File("F:\\FileStudy\\test1.text");
        System.out.println(file5.compareTo(file6));
        File file7 =new File("F:\\FileStudy\\test1.text");
        File file8 =new File("F:\\FileStUdy\\TEST1.text");
        System.out.println(file7.compareTo(file8));
    }

輸出結果:在這裏插入圖片描述
由上可以看出compareTo不區分大小寫的比較,同一個文件返回0,不同文件返回<0,或者>0;

屬性

/**
   * This abstract pathname's normalized pathname string. A normalized
   * pathname string uses the default name-separator character and does not
   * contain any duplicate or redundant separators.
   *
   * @serial
   */
  private final String path;

  /**
   * Enum type that indicates the status of a file path.
   */
  private static enum PathStatus { INVALID, CHECKED };

  /**
   * The flag indicating whether the file path is invalid.
   */
  private transient PathStatus status = null;

  /**
   * Check if the file has an invalid path. Currently, the inspection of
   * a file path is very limited, and it only covers Nul character check.
   * Returning true means the path is definitely invalid/garbage. But
   * returning false does not guarantee that the path is valid.
   *
   * @return true if the file path is invalid.
   */
  final boolean isInvalid() {
      if (status == null) {
          status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                     : PathStatus.INVALID;
      }
      return status == PathStatus.INVALID;
  }

  /**
   * The length of this abstract pathname's prefix, or zero if it has no
   * prefix.
   */
  private final transient int prefixLength;

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

(1)
private final String path:注意用final修飾,當用final作用於類的成員變量時,成員變量(注意是類的成員變量,局部變量只需要保證在使用之前被初始化賦值即可)必須在定義時或者構造器中進行初始化賦值,而且final變量一旦被初始化賦值之後,就不能再被賦值了。
final關鍵字詳解:https://www.cnblogs.com/dolphin0520/p/3736238.html

(2)
private static enum PathStatus { INVALID, CHECKED };
private transient PathStatus status = null;
定義了一個靜態枚舉類用於區分該文件的狀態 INVALID:無效的 CHECKED:檢查的

(3)
final boolean isInvalid():用於判讀該文件是否非法類型
ps:注意成員變量和方法的修飾詞


/**
     * 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>.
     *
     * @see     java.lang.System#getProperty(java.lang.String)
     */
    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;

separatorChar :fs.getSeparator();(fs屬性上面已經解釋)
依賴於系統的默認名稱分隔符。此字段初始化爲包含系統屬性file.separator的值的第一個字符。在UNIX系統中,這個字段的值是’/’;在Microsoft Windows系統中,它是’\’。
getSeparator()是WinNTFileSystem類裏面的方法

private final char slash;//斜槓符號
private final char altSlash;//與slash相反的斜槓
private final char semicolon;//分號
@Override
 public char getSeparator() {
     return slash;
 }

separator :把 char separatorChar 轉換成字符串


    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;

pathSeparatorChar:系統相關的路徑分隔符。該字段初始化爲包含系統屬性path.separator的第一個字符。此字符用於分隔以路徑列表形式給出的文件序列中的文件名。在UNIX系統中,這個字符是’:’;在Microsoft Windows系統中,它是“;”。
跟上面一樣也是調用fs.getPathSeparator();

    @Override
    public char getPathSeparator() {
        return semicolon;
    }

構造方法

jdk1.8 文檔:
在這裏插入圖片描述
源碼的構造方法:
源碼
volatile關鍵字解析:https://www.cnblogs.com/dolphin0520/p/3920373.html

方法

(1)public String getName();

   public String getName() {
       int index = path.lastIndexOf(separatorChar);
       if (index < prefixLength) return path.substring(prefixLength);
       return path.substring(index + 1);
   }

該方法返回由這個抽象路徑名錶示的文件或目錄的名稱。這只是路徑名的名稱序列中的最後一個名稱。如果路徑名的名稱序列爲空,則返回空字符串。
值得注意的是prefixLength的值只有0,1,2,3;對應的是pathname給定的文件路徑是什麼樣子的,比如當pathname="" 時prefixLength=0,等等

(2)public String getParent();

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

返回這個抽象路徑名的父路徑名字符串,如果這個路徑名沒有指定父目錄,則返回null。
抽象路徑名的父路徑名由路徑名前綴(如果有的話)和路徑名名稱序列中的每個名稱(最後一個除外)組成。如果名稱序列爲空,則路徑名不命名父目錄。
@Test

    @Test
    public void getParent(){
        File file =new File("F:\\FileStudy\\test1.text");
        File file1 =new File("F:\\FileStudy");
        File file2 =new File("");
        System.out.println(file.getParent());
        System.out.println(file1.getParent());
        System.out.println(file2.getParent());

    }
    輸出結果:F:\FileStudy;F:\;null

該方法的實現也是根據檢索""出現的位置在與prefixLength 比較,得出父路勁的目錄

(3) public File getParentFile();

    public File getParentFile() {
        String p = this.getParent();
        if (p == null) return null;
        return new File(p, this.prefixLength);
    }

返回這個抽象路徑名的父路徑名的抽象路徑名,如果這個路徑名沒有指定父目錄的名稱,則返回null。
抽象路徑名的父路徑名由路徑名前綴(如果有的話)和路徑名名稱序列中的每個名稱(最後一個除外)組成。如果名稱序列爲空,則路徑名不命名父目錄。

該方法是調用上面的方法返回父路徑的字符串,然後再利用構造函數構造File類型的值

(4)public boolean isAbsolute();

    public boolean isAbsolute() {
        return fs.isAbsolute(this);
    }

WinNTFileSystem 類中的isAbsolute方法

    @Override
    public boolean isAbsolute(File f) {
        int pl = f.getPrefixLength();
        return (((pl == 2) && (f.getPath().charAt(0) == slash))
                || (pl == 3));
    }

測試這個抽象路徑名是否絕對。絕對路徑名的定義依賴於系統。在UNIX系統中,如果路徑名的前綴是“/”,那麼它就是絕對路徑名。在microsoftwindows系統中,如果路徑名的前綴是驅動器說明符,後跟“\”,或者前綴是“\\”,則路徑名是絕對的。
@Test

   @Test
    public void isAbsolute(){
        File file =new File("F:\\FileStudy\\test1.text");
        File file1 =new File("test1.text");
        File file2 =new File("");
        System.out.println(file.isAbsolute());
        System.out.println(file1.isAbsolute());
        System.out.println(file2.isAbsolute());

    }
輸出結果:true;false;false

該方法也是跟prefixLength比較,得出是不是絕對路徑

(5)
public String getAbsolutePath()

    public String getAbsolutePath() {
        return fs.resolve(this);
    }
WinNTFileSystem 類中的resolve方法:
  @Override
    public String resolve(File f) {
        String path = f.getPath();
        int pl = f.getPrefixLength();
        if ((pl == 2) && (path.charAt(0) == slash))
            return path;                        /* UNC */
        if (pl == 3)
            return path;                        /* Absolute local */
        if (pl == 0)
            return getUserPath() + slashify(path); /* Completely relative */
        if (pl == 1) {                          /* Drive-relative */
            String up = getUserPath();
            String ud = getDrive(up);
            if (ud != null) return ud + path;
            return up + path;                   /* User dir is a UNC path */
        }
        if (pl == 2) {                          /* Directory-relative */
            String up = getUserPath();
            String ud = getDrive(up);
            if ((ud != null) && path.startsWith(ud))
                return up + slashify(path.substring(2));
            char drive = path.charAt(0);
            String dir = getDriveDirectory(drive);
            String np;
            if (dir != null) {
                /* When resolving a directory-relative path that refers to a
                   drive other than the current drive, insist that the caller
                   have read permission on the result */
                String p = drive + (':' + dir + slashify(path.substring(2)));
                SecurityManager security = System.getSecurityManager();
                try {
                    if (security != null) security.checkRead(p);
                } catch (SecurityException x) {
                    /* Don't disclose the drive's directory in the exception */
                    throw new SecurityException("Cannot resolve path " + path);
                }
                return p;
            }
            return drive + ":" + slashify(path.substring(2)); /* fake it */
        }
        throw new InternalError("Unresolvable path: " + path);
    }

返回這個抽象路徑名的絕對路徑名字符串。
如果這個抽象路徑名已經是絕對的,那麼路徑名字符串就會像getPath方法那樣簡單地返回。如果這個抽象路徑名是空的抽象路徑名,那麼當前用戶目錄的路徑名字符串將由系統屬性user命名。dir,返回。否則,此路徑名將以與系統相關的方式解析。在UNIX系統中,通過根據當前用戶目錄解析相對路徑名,可以使其變爲絕對路徑名。在microsoftwindows系統中,相對路徑名是絕對的,方法是根據路徑名(如果有的話)命名的驅動器的當前目錄解析它;如果不是,則根據當前用戶目錄解析。
@Test

    @Test
    public void getAbsolutePath(){
        File file =new File("F:\\FileStudy\\test1.text");
        File file1 =new File("test1.text");
        File file2 =new File("");
        System.out.println(file.getAbsolutePath());
        System.out.println(file1.getAbsolutePath());
        System.out.println(file2.getAbsolutePath());

    }
    輸出結果:F:\FileStudy\test1.text;E:\java1.8Study\test1.text;E:\java1.8Study

該方法也是跟prefixLength比較,返回絕對路徑的字符串,當該路徑爲相對路勁是返回的是:當前項目路徑+pathname

(6)public File getAbsoluteFile();

    public File getAbsoluteFile() {
        String absPath = getAbsolutePath();
        return new File(absPath, fs.prefixLength(absPath));
    }

返回此抽象路徑名的絕對形式。相當於新文件(this.getAbsolutePath)。
該方法跟上面的調用上面的方法,然後在調用構造函數,返回File類型

(7) public String getCanonicalPath() throws IOException;

  public String getCanonicalPath() throws IOException {
        if (isInvalid()) {
            throw new IOException("Invalid file path");
        }
        return fs.canonicalize(fs.resolve(this));
    }
  public File getCanonicalFile() throws IOException {
        String canonPath = getCanonicalPath();
        return new File(canonPath, fs.prefixLength(canonPath));
    }

返回這個抽象路徑名的規範路徑名字符串。

規範路徑名是絕對的,也是唯一的。規範形式的精確定義依賴於系統。該方法首先在必要時將這個路徑名轉換爲絕對形式,就像調用getAbsolutePath方法一樣,然後以系統相關的方式將其映射到其惟一的形式。這通常涉及從路徑名中刪除“.”和“…”等冗餘名稱,解析符號鏈接(在UNIX平臺上),並將驅動器字母轉換爲標準大小寫(在Microsoft Windows平臺上)。

表示現有文件或目錄的每個路徑名都有惟一的規範形式。表示不存在的文件或目錄的每個路徑名都有唯一的規範形式。不存在的文件或目錄的路徑名的規範形式可能與創建文件或目錄後相同路徑名的規範形式不同。類似地,現有文件或目錄的路徑名的規範形式可能與刪除文件或目錄後相同路徑名的規範形式不同。

java中File類的getPath(),getAbsolutePath(),getCanonicalPath()區別:https://blog.51cto.com/handd/1173823
getCanonicalPath() 就是處理成規範模式:
比如.\test.txt 會轉換成E:\java1.8Study\test1.text
getAbsolutePath():比如.\test.txt 會轉換成E:\java1.8Study.\test1.text
@Test

   @Test
    public void getCanonicalPath() throws IOException {

        File file =new File(".\\test1.text");
        File file1 =new File(".\\test1.text");
        System.out.println(file.getAbsolutePath());
        System.out.println(file1.getCanonicalPath());
    }
輸出結果:
E:\java1.8Study\.\test1.text
E:\java1.8Study\test1.text

(8) public URI toURI();

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

構造一個表示此抽象路徑名的file: URI。
URI的確切形式是依賴於系統的。 如果可以確定由此抽象路徑名錶示的文件是目錄,則生成的URI將以斜槓結尾。

對於給定的抽象路徑名f ,它是有保證的

new File( f .toURI()).equals( f .getAbsoluteFile())
只要原始的抽象路徑名,URI和新的抽象路徑名都在同一個Java虛擬機(可能不同的調用)中創建。 然而,由於抽象路徑名的系統依賴性質,當將一個操作系統上的虛擬機中創建的8839929495048 URI轉換爲不同操作系統上的虛擬機中的抽象路徑名時,此關係通常不成立。
請注意,當此抽象路徑名錶示UNC路徑名時,UNC的所有組件(包括服務器名稱組件)都將在URI路徑中進行編碼。 權限組件未定義,表示爲null 。 所述Path類定義了toUri方法在所得的授權組成編碼的服務器名稱URI 。 toPath方法可用於獲取表示此抽象路徑名的Path 。
@Test

    @Test
    public void toURI() throws IOException {
        File file =new File("F:\\FileStudy\\test1.text");
        File file1 =new File("F:\\FileStudy");
        File file2 =new File("");
        System.out.println(file.toURI());
        System.out.println(file1.toURI());
        System.out.println(file2.toURI());
    }
 輸出結果:
file:/F:/FileStudy/test1.text
file:/F:/FileStudy/
file:/E:/java1.8Study/

該方法主要把File轉換成URL類型,然後對路徑進行了加"/"處理

(9)public boolean canRead();

 public boolean canRead() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_READ);
    }

WinNTFileSystem 類中的checkAccess方法,這是一個本地方法:檢查由給定的抽象路徑名錶示的文件或目錄是否可由該進程訪問。第二個參數指定要檢查的訪問權限ACCESS_READ、ACCESS_WRITE或ACCESS_EXECUTE。如果訪問被拒絕或出現I/O錯誤,則返回false

@Override
public native boolean checkAccess(File f, int access);

測試應用程序是否可以讀取由這個抽象路徑名錶示的文件。在某些平臺上,可以使用特權啓動Java虛擬機,允許它讀取標記爲不可讀的文件。因此,即使文件沒有讀權限,此方法也可能返回true。
@Test

    @Test
    public void canRead() {
        File file =new File("F:\\FileStudy\\test1.txt");//有該文件
        File file1 =new File("F:\\FileStudy\\test1.text");//沒有該文件
        File file2 =new File("");
        System.out.println(file.canRead());
        System.out.println(file1.canRead());
        System.out.println(file2.canRead());
    }
    輸出結果:
    true
	false
	false

由上可以看出錯誤文件和""都返回false,其餘有可讀屬性返回true

(10)public boolean canWrite();

  public boolean canWrite() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
    }

測試應用程序是否可以修改這個抽象路徑名錶示的文件。在某些平臺上,可以使用特權啓動Java虛擬機,允許它修改標記爲只讀的文件。因此,即使文件被標記爲只讀,此方法也可能返回true。
@Test

    @Test
  public void canWrite() {
      File file =new File("F:\\FileStudy\\test1.txt");//設置成可讀
      File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
      File file2 =new File("");
      File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
      System.out.println(file.canWrite());
      System.out.println(file1.canWrite());
      System.out.println(file2.canWrite());
      System.out.println(file3.canWrite());
  }
  輸出結果:
  false
  false
  false
  true

由上可以看出,文件設置成可讀,錯誤文件和""都返回false,沒有設置的返回true

(11)public boolean 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);
    } 

WinNTFileSystem 類中的getBooleanAttributes方法:爲指定的抽象路徑名錶示的文件或目錄返回簡單的布爾屬性,如果不存在或出現其他I/O錯誤,則返回0。

    @Override
   public native int getBooleanAttributes(File f);

測試由這個抽象路徑名錶示的文件或目錄是否存在。
@Test

    @Test
   public void exists() {
       File file =new File("F:\\FileStudy\\test1.txt");//設置成可讀
       File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
       File file2 =new File("");
       File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
       File file4 =new File("F:\\FileStudy");//目錄
       System.out.println(file.exists());
       System.out.println(file1.exists());
       System.out.println(file2.exists());
       System.out.println(file3.exists());
       System.out.println(file4.exists());
   }
   輸出結果:
true
false
false
true
true    

由上可以看出,也是調用WinNTFileSystem 類中的本地方法進行判斷是否存在該文件或者目錄,存在返回true,不存在返回false

(12)public boolean isDirectory();

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

測試由這個抽象路徑名錶示的文件是否是一個目錄。
如果需要將I/O異常與文件不是目錄的情況區分開,或者同時需要同一文件的多個屬性,則需要文件。可以使用readAttributes方法。
@Test

    @Test
    public void isDirectory() {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成可讀
        File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
        File file2 =new File("");
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄

        System.out.println(file.isDirectory());
        System.out.println(file1.isDirectory());
        System.out.println(file2.isDirectory());
        System.out.println(file3.isDirectory());
        System.out.println(file4.isDirectory());
    }
    輸出結果:
false
false
false
false
true

判斷文件是不是目錄,由上可以看出也是調用WinNTFileSystem 類中的getBooleanAttributes方法,最後 & FileSystem.BA_DIRECTORY常量進行判斷是否是目錄.文件或者錯誤文件都返回false,只有存在目錄的返回false

(13)public boolean isFile();

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

測試由這個抽象路徑名錶示的文件是否是一個普通文件。如果文件不是目錄,並且滿足其他與系統相關的條件,那麼它就是正常的。Java應用程序創建的任何非目錄文件都保證是正常的文件。
如果需要將I/O異常與文件不是普通文件的情況區分開來,或者同時需要同一文件的多個屬性,則使用文件。可以使用readAttributes方法。
@Test

    @Test
    public void isFile() {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成可讀
        File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
        File file2 =new File("");
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄

        System.out.println(file.isFile());
        System.out.println(file1.isFile());
        System.out.println(file2.isFile());
        System.out.println(file3.isFile());
        System.out.println(file4.isFile());
    }
    輸出結果:
true
false
false
true
false

跟isDirectory()方法一樣也是& FileSystem.BA_REGULAR常量去判斷是否爲文件.
只有該文件是一個文件而不是目錄和假文件才返回true,其餘返回false

(14)public boolean isHidden();

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

測試由這個抽象路徑名命名的文件是否爲隱藏文件。隱藏的確切定義依賴於系統。在UNIX系統中,如果文件的名稱以句點字符(’.’)開頭,則認爲該文件是隱藏的。在microsoftwindows系統中,如果文件系統中已將其標記爲隱藏文件,則認爲該文件已被隱藏。
@Test

    @Test
    public void isHidden() {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
        File file2 =new File("");
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄

        System.out.println(file.isHidden());
        System.out.println(file1.isHidden());
        System.out.println(file2.isHidden());
        System.out.println(file3.isHidden());
        System.out.println(file4.isHidden());
    }
   輸出結果:
true
false
false
false
false

跟上面的幾個方法實現的原理一樣.

(15)public long lastModified();

    public long lastModified() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getLastModifiedTime(this);
    }

返回由這個抽象路徑名錶示的文件最後修改的時間。

如果需要將I/O異常與返回0L的情況區分開,或者在同一時間需要同一文件的多個屬性,或者需要最後一次訪問的時間或創建時間,則需要文件。可以使用readAttributes方法。
@Test

    @Test
    public void lastModified() {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
        File file2 =new File("");
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄

        System.out.println(file.lastModified());
        System.out.println(file1.lastModified());
        System.out.println(file2.lastModified());
        System.out.println(file3.lastModified());
        System.out.println(file4.lastModified());
    }
    輸出結果:
1581419351429
0
0
1581419351429
1581419386036

該方法也是調用WinNTFileSystem 類本地方法getLastModifiedTime(File f),注意返回的是long的類型,錯誤文件直接返回0.

(16) public long length();

    public long length() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return 0L;
        }
        return fs.getLength(this);
    }

返回由這個抽象路徑名錶示的文件長度。如果此路徑名錶示目錄,則返回值未指定。
如果需要將I/O異常與返回0L的情況區分開,或者同時需要相同文件的多個屬性,則需要文件。可以使用readAttributes方法。
@Test

    @Test
    public void length() {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\test1.text");//錯誤文件
        File file2 =new File("");
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄

        System.out.println(file.length());
        System.out.println(file1.length());
        System.out.println(file2.length());
        System.out.println(file3.length());
        System.out.println(file4.length());
    }
    輸出結果:
0
0
0
14
0

由上可以看出,如果是空文件,假文件和目錄都返回0,有內容的文件返回文件大小,大小用字節表示.也是調用WinNTFileSystem 類本地方法public native long getLength(File f);

(17)public boolean createNewFile() throws IOException;

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

當且僅當具有此名稱的文件尚不存在時,原子地創建一個由此抽象路徑名命名的新空文件。對於可能影響文件的所有其他文件系統活動來說,檢查文件是否存在以及如果文件不存在則創建文件是一個單獨的原子操作。
注意:這個方法不能用於文件鎖定,因爲產生的協議不能可靠地工作。應該使用FileLock工具。
@Test

    @Test
    public void createNewFile() throws IOException {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\te1.text");//錯誤文件
        File file3 =new File("F:\\FileStudy\\test2.txt");//沒有設置成可讀
        File file4 =new File("F:\\FileStudy");//目錄
        File file5 =new File("F:\\FilStudy");//不存在該目錄

        File file2 =new File("");

        System.out.println(file.createNewFile());
        System.out.println(file1.createNewFile());
        System.out.println(file3.createNewFile());
        System.out.println(file4.createNewFile());
        System.out.println(file5.createNewFile());
        System.out.println(file2.createNewFile());
    }
輸出結果:
false
true
false
false
true
java.io.IOException: 系統找不到指定的路徑。

該方法也是調用WinNTFileSystem 類本地方法public native boolean createFileExclusively(String path) throws IOException;當存在該文件時,直接返回false;不存在該文件並且路徑正確則會創建該文件的空文件;當不存在該目錄時創建沒有後綴的文件,比如file5如下圖;
在這裏插入圖片描述
不存在該路徑時拋出IOException異常.

(18)public boolean delete();

  public boolean delete() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.delete(this);
    }

WinNTFileSystem 類public boolean delete(File f);

  @Override
    public boolean delete(File f) {
        // Keep canonicalization caches in sync after file deletion
        // and renaming operations. Could be more clever than this
        // (i.e., only remove/update affected entries) but probably
        // not worth it since these entries expire after 30 seconds
        // anyway.
        cache.clear();
        prefixCache.clear();
        return delete0(f);
    }

    private native boolean delete0(File f);

刪除由這個抽象路徑名錶示的文件或目錄。如果這個路徑名錶示一個目錄,那麼該目錄必須爲空才能刪除。

請注意java.nio.文件。Files類定義刪除方法,以便在無法刪除文件時拋出IOException。這對於錯誤報告和診斷爲什麼文件不能刪除非常有用。
@Test

    @Test
    public void delete() throws IOException {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\te1.text");//錯誤文件
        File file5 =new File("F:\\FilStudy");//不存在該目錄
        File file2 =new File("");

        System.out.println(file.delete());
        System.out.println(file1.delete());

        System.out.println(file5.delete());
        System.out.println(file2.delete());
    }
輸出結果:
true
true
true
false

由上可以看出,刪除該文件也是掉WinNTFileSystem類的本地方法,但是調用之前先清除緩存裏面的緩存值,然後在調用本地方法. 當存在該文件或者目錄直接刪除返回true,不存在或者爲""返回false.

(19)public void deleteOnExit();

   public void deleteOnExit() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return;
        }
        DeleteOnExitHook.add(path);
    }

請求在虛擬機終止時刪除由此抽象路徑名錶示的文件或目錄。 文件(或目錄)按註冊的相反順序進行刪除。 調用此方法刪除已註冊刪除的文件或目錄無效。 將僅針對Java語言規範定義的虛擬機的正常終止而嘗試刪除。
一旦請求刪除,就無法取消請求。 因此,該方法應謹慎使用。
注意:此方法不應用於文件鎖定,因爲生成的協議不能使其可靠地工作。 應該使用FileLock設施。
該方法和DeleteOnExitHook類詳解:https://blog.csdn.net/10km/article/details/51822560
file.delete()與file.deleteOnExit()的區別:https://blog.csdn.net/asty9000/article/details/80488350

(20) public String[] list();
函數式編程可以學習.

  public String[] list() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return null;
        }
        return fs.list(this);
    }
 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()]);
    }

WinNTFileSystem 類本地方法public native String[] list(File f):文件系統列出用給定的抽象路徑名錶示的目錄的元素。如果成功,返回命名目錄元素的字符串數組;否則,返回null。

    @Override
    public native String[] list(File f);

public String[] list():
返回一個字符串數組,命名由此抽象路徑名錶示的目錄中的文件和目錄。
如果此抽象路徑名不表示目錄,則此方法返回null 。 否則返回一個字符串數組,一個用於目錄中的每個文件或目錄。 表示目錄本身和目錄的父目錄的名稱不包括在結果中。 每個字符串都是一個文件名,而不是完整的路徑。

不保證結果數組中的名稱字符串將以任何特定的順序出現; 他們不是特別保證按字母順序出現。

請注意, Files類定義了newDirectoryStream方法來打開目錄並遍歷目錄中文件的名稱。 在使用非常大的目錄時,這可能會減少資源,並且在使用遠程目錄時可能會更加靈活。

結果
一組字符串,命名由此抽象路徑名錶示的目錄中的文件和目錄。 如果目錄爲空,則該數組將爲空。 如果此抽象路徑名不表示目錄,或返回I / O錯誤,則返回null 。
異常
SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkRead(String)方法拒絕對目錄的讀取訪問

public String[] list(FilenameFilter filter):
返回一個字符串數組,命名由此抽象路徑名錶示的目錄中滿足指定過濾器的文件和目錄。 該方法的行爲與list()方法的行爲相同,只是返回的數組中的字符串必須滿足過濾器。 如果給定的filter是null那麼所有的名字都被接受。 否則,一個名稱滿足過濾器,當且僅當值true當結果FilenameFilter.accept(File, String)濾波器的方法是在此抽象路徑名和在於其表示目錄中的文件或目錄的名稱調用。
參數
filter - 文件名過濾器
結果
一組字符串,命名由該抽象路徑名錶示的目錄中由指定的filter接受的文件和filter 。 如果目錄爲空,或者過濾器沒有接受名稱,則該數組將爲空。 如果此抽象路徑名不表示目錄,或返回I / O錯誤,則返回null 。
異常
SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkRead(String)方法拒絕對目錄的讀取訪問
@Test

    @Test
    public void list() throws IOException {
        File file =new File("F:\\FileStudy\\test1.txt");//設置成隱藏
        File file1 =new File("F:\\FileStudy\\te1.text");//錯誤文件
        File file5 =new File("F:\\FileStudy");//目錄
        File file6 =new File("F:\\FilStudy");//不存在該目錄

        File file2 =new File("");

        System.out.println(Arrays.toString(file.list()));
        System.out.println(Arrays.toString(file1.list()));
        System.out.println(Arrays.toString(file5.list()));
        System.out.println(Arrays.toString(file6.list()));
        System.out.println(Arrays.toString(file2.list()));
    }
輸出結果:
null
null
[test1.text, test2.txt, tet1.text]
null
null

由上可以看出,如果當前的文件不是目錄或者是不存在的目錄和文件則返回null,如果存在則輸出該目錄下的文件名.
@Test

    @Test
    public void listFilenameFilter() throws IOException {

        File file5 = new File("F:\\FileStudy");//目錄
        File file6 = new File("F:\\FilStudy");//不存在該目錄
        System.out.println(Arrays.toString(file5.list((v, t) -> {
            if (v.equals(new File("F:\\FileStudy"))) return true;
            return false;
        })));
        System.out.println(Arrays.toString(file5.list((v, t) -> {
            if (v.equals(new File("F:\\FileStudy"))&& !t.equals("test1.text")) return true;
            return false;
        })));
        System.out.println(Arrays.toString(file6.list((v, t) -> {
            if (v.equals(new File("F:\\FileStudy"))) return true;
            return false;
        })));
    }
輸出結果:
[test1.text, test2.txt, tet1.text]
[test2.txt, tet1.text]
null

跟上面的方法一樣,只是添加了一個參數FilenameFilter filter用於過濾,該參數可以使用lambada表達式寫,函數式編程.

(21) public File[] listFiles();

    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;
    }
   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類型.

    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()]);
    }

該方法跟上面的方法一樣,只是參數變成FileFilter filter,查看該源碼可以看出

@FunctionalInterface
public interface FileFilter {

    /**
     * Tests whether or not the specified abstract pathname should be
     * included in a pathname list.
     *
     * @param  pathname  The abstract pathname to be tested
     * @return  <code>true</code> if and only if <code>pathname</code>
     *          should be included
     */
    boolean accept(File pathname);
}

該過濾器中的方法只有一個參數File pathname
@Test

    @Test
    public void listFiles() throws IOException {
        File file5 = new File("F:\\FileStudy");//目錄
        File[] files = file5.listFiles(
                v -> {
                    if (v.equals(new File("F:\\FileStudy\\test1.text"))) return true;
                    return false;
                }
        );
        System.out.println(Arrays.toString(files));
    }
    輸出結果:
    [F:\FileStudy\test1.text]

跟上面的方法一樣,只是一個是兩個參數的過濾器,一個一個參數的過濾器,參數類型也不同,一個參數的類型File類型.

(22)
public boolean mkdir():創建由此抽象路徑名命名的目錄。
public boolean mkdirs():創建由此抽象路徑名命名的目錄,包括任何必需但不存在的父目錄。 請注意,如果此操作失敗,它可能已成功創建一些必需的父目錄

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

WinNTFileSystem 類本地方法public native boolean createDirectory(File f);

   @Override
   public native boolean createDirectory(File f);

值得注意的是mkdirs()方法裏面採用了遞歸,先是判斷該目錄是否存在,不存在創建該目錄,可能出現失敗,失敗後獲取該規範形式的File,然後在執行這個條件
(parent != null && (parent.mkdirs() || parent.exists()) && canonFile.mkdir())
返回true表示成功

(23)public boolean renameTo(File dest);

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

WinNTFileSystem 類的rename(File f1, File f2):

    @Override
    public boolean rename(File f1, File f2) {
        // Keep canonicalization caches in sync after file deletion
        // and renaming operations. Could be more clever than this
        // (i.e., only remove/update affected entries) but probably
        // not worth it since these entries expire after 30 seconds
        // anyway.
        cache.clear();
        prefixCache.clear();
        return rename0(f1, f2);
    }

    private native boolean rename0(File f1, File f2);

public boolean renameTo(File dest)
重命名由此抽象路徑名錶示的文件。
該方法的行爲的許多方面固有地依賴於平臺:重命名操作可能無法將文件從一個文件系統移動到另一個文件系統,它可能不是原子的,如果具有目標抽象路徑名的文件可能無法成功已經存在。 應始終檢查返回值,以確保重命名操作成功。
請注意, Files類定義了以獨立於平臺的方式移動或重命名文件的move方法。
參數
dest - 命名文件的新抽象路徑名
結果
true當且僅當重命名成功; false否則
異常
SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對舊的或新的路徑名的寫入訪問
NullPointerException - 如果參數 dest是 null
@Test

    @Test
    public void renameTo() {
        File file = new File("F:\\FileStudy\\test1.text");//存在的文件
        File file1 = new File("F:\\FileStudy\\test1.ext");//不存的文件
        File file2 = new File("");//爲空
        System.out.println(file.renameTo(new File("F:\\FileStudy\\test1.txt")));
        System.out.println(file1.renameTo(new File("F:\\FileStudy\\test1.xt")));
        System.out.println(file2.renameTo(new File("F:\\FileStudy\\test1.t")));
        System.out.println(file.renameTo(null));
    }
輸出結果:
true
false
false
java.lang.NullPointerException

第一個修改成功:
在這裏插入圖片描述
由上可知,該方法也是調用WinNTFileSystem類中的本地方法,只是在調用之前,清楚了緩存表中的數據,然後在調用本地方法.而File類中做了一些參數校驗,是否可寫,是否有效,dest是否爲null.
看@Test可以看出,當存在該文件則會重命名成功返回true,不存在返回false修改不成功.當dest爲null,拋出控制針異常.

(24)Set*類方法:該類方法主要設置可讀可寫和一些權限,都是調用WinNTFileSystem類中的本地方法,jdk1.8文檔解釋:

  1. public boolean setExecutable(boolean executable)
    爲此抽象路徑名設置所有者的執行權限的便利方法。 在某些平臺上,可能會啓動具有特殊權限的Java虛擬機,以允許其執行未標記爲可執行文件。
    調用此方法的形式爲file.setExcutable(arg)的行爲方式與調用完全相同
    file.setExecutable(arg, true)
    參數
    executable - 如果true ,設置訪問權限允許執行操作; 如果false不允許執行操作
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。 如果executable是false並且底層文件系統沒有實現執行權限,那麼操作將失敗。
    異常
    SecurityException - 如果存在安全管理員,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對文件的寫入訪問

  1. public boolean setExecutable(boolean executable,boolean ownerOnly)
    設置該抽象路徑名的所有者或每個人的執行權限。 在某些平臺上,可能會啓動具有特殊權限的Java虛擬機,以允許其執行未標記爲可執行文件。
    Files類定義了對文件屬性(包括文件權限)進行操作的方法。 當需要更精細的文件權限操作時,可以使用這種方法。
    參數
    executable - 如果true ,設置訪問權限允許執行操作; 如果false不允許執行操作
    ownerOnly - 如果true ,則執行權限僅適用於所有者的執行權限; 否則適用於所有人。 如果底層文件系統無法區分所有者的執行權限與其他人的執行權限,則該權限將適用於所有人,不管該值。
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。 如果executable是false並且底層文件系統沒有實現執行權限,那麼操作將失敗。
    異常
    SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對該文件的寫訪問
    ps:個人理解可以執行的文件爲每個人設置執行權限,列如wind下.exe後綴文件

  1. public boolean setLastModified(long time)
    設置由此抽象路徑名命名的文件或目錄的最後修改時間。
    所有平臺都支持文件修改時間到最近的秒數,但有些則提供更高的精度。 參數將被截斷以適應支持的精度。 如果操作成功,並且不會對文件進行干預操作,則下一次調用lastModified()方法將返回傳遞給此方法的(可能截斷的) time參數。
    參數
    time - 自上個世紀(1970年1月1日00:00:00 GMT)以來,以毫秒計
    結果
    true當且僅當操作成功; false否則
    異常
    IllegalArgumentException - 如果參數爲負數
    SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對命名文件的寫入訪問

  1. public boolean setReadable(boolean readable)
    一種方便的方法來設置所有者對此抽象路徑名的讀取權限。 在某些平臺上,可以使用特殊權限啓動Java虛擬機,以允許它讀取標記爲不可讀的文件。
    調用此方法的形式爲file.setReadable(arg)的行爲方式與調用完全相同
    file.setReadable(arg, true)
    參數
    readable - 如果true ,設置訪問權限允許讀操作; 如果false不允許讀操作
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。 如果readable是false ,並且底層文件系統沒有實現讀取權限,則操作將失敗。
    異常
    SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對該文件的寫入訪問

  1. public boolean setReadable(boolean readable,
    boolean ownerOnly)
    設置此抽象路徑名的所有者或每個人的讀取權限。 在某些平臺上,可以使用特殊權限啓動Java虛擬機,以允許它讀取標記爲不可讀的文件。
    Files類定義了對文件屬性(包括文件權限)進行操作的方法。 當需要更精細的文件權限操作時,可以使用這種方法。
    參數
    readable - 如果true ,設置訪問權限允許讀操作; 如果false不允許讀操作
    ownerOnly - 如果true ,讀權限僅適用於所有者的讀權限; 否則適用於所有人。 如果底層文件系統無法區分所有者的讀取權限與其他用戶的讀取權限,則該權限將適用於所有人,不管該值如何。
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。 如果readable是false並且底層文件系統沒有實現讀取權限,則操作將失敗。
    異常
    SecurityException - 如果存在安全管理員,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對文件的寫入訪問

  1. public boolean setWritable(boolean writable)
    一種方便的方法來設置所有者對此抽象路徑名的寫入權限。 在某些平臺上,可能會啓動具有特殊權限的Java虛擬機,允許它修改不允許寫入操作的文件。
    調用此方法的形式爲file.setWritable(arg)的行爲方式與調用完全相同
    file.setWritable(arg, true)
    參數
    writable - 如果true ,設置訪問權限允許寫操作; 如果false不允許寫操作
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。
    異常
    SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對文件的寫入訪問

  1. public boolean setReadable(boolean readable,
    boolean ownerOnly)
    設置此抽象路徑名的所有者或每個人的讀取權限。 在某些平臺上,可以使用特殊權限啓動Java虛擬機,以允許它讀取標記爲不可讀的文件。
    Files類定義了對文件屬性(包括文件權限)進行操作的方法。 當需要更精細的文件權限操作時,可以使用這種方法。
    參數
    readable - 如果true ,設置訪問權限允許讀操作; 如果false不允許讀操作
    ownerOnly - 如果true ,讀權限僅適用於所有者的讀權限; 否則適用於所有人。 如果底層文件系統無法區分所有者的讀取權限與其他用戶的讀取權限,則該權限將適用於所有人,不管該值如何。
    結果
    true當且僅當操作成功。 如果用戶沒有權限更改此抽象路徑名的訪問權限,操作將失敗。 如果readable是false並且底層文件系統沒有實現讀取權限,則操作將失敗。
    異常
    SecurityException - 如果存在安全管理員,並且其 SecurityManager.checkWrite(java.lang.String)方法拒絕對文件的寫入訪問

(25) public static File[] listRoots():

public static File[] listRoots() {
        return fs.listRoots();
    }

WinNTFileSystem類中的listRoots()

    @Override
    public File[] listRoots() {
        int ds = listRoots0();
        int n = 0;
        for (int i = 0; i < 26; i++) {
            if (((ds >> i) & 1) != 0) {
                if (!access((char)('A' + i) + ":" + slash))
                    ds &= ~(1 << i);
                else
                    n++;
            }
        }
        File[] fs = new File[n];
        int j = 0;
        char slash = this.slash;
        for (int i = 0; i < 26; i++) {
            if (((ds >> i) & 1) != 0)
                fs[j++] = new File((char)('A' + i) + ":" + slash);
        }
        return fs;
    }

    private static native int listRoots0();

public static File[] listRoots()
列出可用的文件系統根。
一個特定的Java平臺可以支持零個或多個分層組織的文件系統。 每個文件系統都有一個root目錄,從該目錄可以訪問該文件系統中的所有其他文件。 例如,Windows平臺具有每個活動驅動器的根目錄; UNIX平臺有一個根目錄,即"/" 。 可用文件系統根的集合受到各種系統級操作的影響,例如插入或彈出可移動介質以及斷開或卸載物理或虛擬磁盤驅動器。

此方法返回一個File對象的數組,它們表示可用文件系統根的根目錄。 確保本地機器上物理存在的任何文件的規範路徑名將以此方法返回的其中一個根源開始。

駐留在某個其他機器上並通過遠程文件系統協議(如SMB或NFS)訪問的文件的規範路徑名可能或可能不以此方法返回的根目錄之一開始。 如果遠程文件的路徑名在語法上與本地文件的路徑名無法區分,那麼它將以此方法返回的其中一個根開始。 因此,例如, File對象表示在Windows平臺的映射的網絡驅動器的根目錄下將通過該方法返回,而File含有UNC路徑名的對象將不通過該方法來返回。

與此類中的大多數方法不同,此方法不會拋出安全異常。 如果安全管理器存在,並且其SecurityManager.checkRead(String)方法拒絕對特定根目錄的讀取訪問,則該目錄將不會顯示在結果中。

結果
一組File對象表示可用的文件系統根,或null如果無法確定根組。 如果沒有文件系統根,數組將爲空。
@Test

 @Test
    public void listRoots() {
        System.out.println(Arrays.toString(File.listRoots()));
    }
    輸出結果:
    [C:\, D:\, E:\, F:\]

該方法是一個靜態方法,返回該系統所有的根路徑,如上.注意返回類型爲File

(26) public long getTotalSpace();

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

WinNTFileSystem類中的getSpace(File f, int t)

  @Override
    public long getSpace(File f, int t) {
        if (f.exists()) {
            return getSpace0(f, t);
        }
        return 0;
    }

    private native long getSpace0(File f, int t);

public long getTotalSpace()
通過此抽象路徑名返回分區 named的大小。
結果
分區的大小(以字節爲單位)或 0L(如果此抽象路徑名未命名分區)
異常
SecurityException - 如果安全管理器已經安裝,否認RuntimePermission (“getFileSystemAttributes”)或其SecurityManager.checkRead(String)方法拒絕對此抽象路徑名命名的文件的讀訪問權限
@Test

    @Test
    public void getTotalSpace() {
        File file = new File("F:\\FileStudy\\test1.txt");//存在的文件
        File file1 = new File("F:\\FileStudy\\test1.t1xt");//不存在該文件
        File file2 = new File("F:\\FileStudy");//目錄
        File file3 = new File("F:");//根目錄

        System.out.println(file.getTotalSpace());
        System.out.println(file1.getTotalSpace());
        System.out.println(file2.getTotalSpace());
        System.out.println(file3.getTotalSpace());
    }
輸出結果:
63607664640
0
63607664640
63607664640

在這裏插入圖片描述
由上可以不管該文件在哪,返回該盤的容量大小,不存在的文件返回0.

(27)
public long getFreeSpace();
public long getUsableSpace();

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

跟上面實現額方法一樣,只是傳入的常量不同而已.

public long getFreeSpace()
返回分區未分配的字節數named此抽象路徑名。
返回的未分配字節數是一個提示,但不是保證,可以使用大多數或任何這些字節。 在此呼叫之後,未分配字節的數量很可能是準確的。 任何外部I / O操作(包括在該虛擬機之外的系統上進行的操作)都可能導致不準確。 此方法不保證對該文件系統的寫入操作將成功。
結果
分區上的未分配字節數或0L(如果抽象路徑名未命名分區)。 該值將小於或等於由getTotalSpace()返回的總文件系統大小。
異常
SecurityException - 如果已安裝安全管理器,並且拒絕RuntimePermission (“getFileSystemAttributes”)或其SecurityManager.checkRead(String)方法拒絕對此抽象路徑名命名的文件的讀取訪問權限

public long getUsableSpace()
返回上的分區提供給該虛擬機的字節數named此抽象路徑名。 如果可能,此方法將檢查寫入權限和其他操作系統限制,因此通常會提供比getFreeSpace()實際寫入多少新數據的更準確的估計。
返回的可用字節數是一個提示,但不是保證,可以使用大多數或任何這些字節。 在此呼叫之後,未分配字節的數量很可能是準確的。 任何外部I / O操作(包括在該虛擬機之外的系統上進行的操作)都可能導致不準確。 此方法不保證對該文件系統的寫入操作將成功。
結果
分區上的可用字節數或0L,如果抽象路徑名不命名分區。 在此信息不可用的系統上,此方法將等同於調用getFreeSpace() 。
異常
SecurityException - 如果安全管理器已安裝,並且拒絕RuntimePermission (“getFileSystemAttributes”)或其SecurityManager.checkRead(String)方法拒絕對此抽象路徑名命名的文件的讀訪問權限
@Test

    @Test
    public void getFreeSpace() {
        File file = new File("F:\\FileStudy\\test1.txt");//存在的文件
        File file1 = new File("F:\\FileStudy\\test1.t1xt");//不存在該文件
        File file2 = new File("F:\\FileStudy");//目錄
        File file3 = new File("F:");//根目錄

        System.out.println(file.getFreeSpace());
        System.out.println(file1.getFreeSpace());
        System.out.println(file2.getFreeSpace());
        System.out.println(file3.getFreeSpace());
    }

    @Test
    public void getUsableSpace() {
        File file = new File("F:\\FileStudy\\test1.txt");//存在的文件
        File file1 = new File("F:\\FileStudy\\test1.t1xt");//不存在該文件
        File file2 = new File("F:\\FileStudy");//目錄
        File file3 = new File("F:");//根目錄

        System.out.println(file.getUsableSpace());
        System.out.println(file1.getUsableSpace());
        System.out.println(file2.getUsableSpace());
        System.out.println(file3.getUsableSpace());
    }
輸出結果都是:
57936908288
0
57936908288
57936908288
上面文檔有解釋

在這裏插入圖片描述
(28)
public static File createTempFile(String prefix, String suffix,File directory);
public static File createTempFile(String prefix, String suffix) throws IOException;

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

public static File createTempFile(String prefix,
String suffix,
File directory)
throws IOException
在指定的目錄中創建一個新的空文件,使用給定的前綴和後綴字符串生成其名稱。 如果此方法成功返回,則可以保證:

在調用此方法之前,由返回的抽象路徑名錶示的文件不存在
該方法和其任何變體都不會在當前虛擬機的調用中再次返回相同的抽象路徑名。
此方法僅提供臨時文件設施的一部分。 要安排通過此方法創建的文件被自動刪除,請使用deleteOnExit()方法。
prefix參數必須至少有三個字符長。 建議前綴爲短的有意義的字符串,如"hjb"或"mail" 。 suffix參數可以是null ,在這種情況下將使用後綴".tmp" 。

要創建新文件,可以首先調整前綴和後綴以適應底層平臺的限制。 如果前綴太長,那麼它將被截斷,但它的前三個字符將始終保留。 如果後綴太長,那麼它也將被截斷,但是如果以句點字符( ‘.’ )開頭,那麼它的週期和前三個字符將始終保留。 一旦進行了這些調整,將通過連接前綴,五個或更多內部生成的字符和後綴來生成新文件的名稱。

如果directory參數是null那麼將使用系統相關的默認臨時文件目錄。 默認臨時文件目錄由系統屬性java.io.tmpdir 。 在UNIX系統上,此屬性的默認值通常爲"/tmp"或"/var/tmp" ; 在Microsoft Windows系統上,通常是"C:\WINNT\TEMP" 。 當Java虛擬機被調用時,可以向該系統屬性賦予不同的值,但不能保證對此屬性的編程更改對此方法使用的臨時目錄有任何影響。

參數
prefix - 用於生成文件名的前綴字符串; 長度必須至少爲3個字符
suffix - 用於生成文件名的後綴字符串; 可能是null ,在這種情況下將使用後綴".tmp"
directory -其中文件是要創建的目錄,或 null如果默認臨時文件目錄將被使用
結果
表示新創建的空文件的抽象路徑名
異常
IllegalArgumentException - 如果 prefix參數包含少於三個字符
IOException - 如果無法創建文件
SecurityException - 如果安全管理器存在,並且其 SecurityManager.checkWrite(java.lang.String)方法不允許創建文件

該方法設計很巧妙,利用一個靜態內部類完成一些基本操作,最後在外部調用完成操作.

createNewFile()與createTempFile()的區別:https://blog.csdn.net/Double2hao/article/details/50363532

(29)public Path toPath();

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

public Path toPath()
返回從該抽象路徑構造的java.nio.file.Path對象。 Path的Path與default-filesystem有關 。
該方法的第一次調用的工作原理就像調用它相當於評估表達式:

FileSystems.getDefault().getPath(this.getPath());

此方法的Path調用返回相同的Path 。
如果此抽象路徑Path空抽象路徑名,則此方法返回可用於訪問當前用戶目錄的Path。

結果
一個從這個抽象路徑 Path Path
異常
InvalidPathException - 如果無法從抽象路徑 Path對象(參見 FileSystem.getPath )

總結:未完待續

發佈了17 篇原創文章 · 獲贊 0 · 訪問量 7221
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章