熟悉Linux操作系統的同學應該知道Linux文件系統采用了inode - block的結構來表示和存儲文件,inode包含了文件的元數據信息,block存儲實際的文件內容。Linux把一切的IO都抽象成文件,那么目錄和普通文件一樣,也都是文件。每個文件都有一個唯一的inode號。
可以用stat命令來查看一個文件的inode信息,比如下面這個文件 stat log.txt
可以看到Device是16777219d, inode號是1821216。這個文件內容是空的,所以Blocks為0
把這個log.txt 重命名為log2.txt,再執行stat log2.txt,可以看到只有文件名變了,其他的inode號這些元數據都沒有變。
實際上普通文件的inode數據結構只存儲一些元數據,不存儲文件名的信息。那么文件名是存在哪里的呢,我們知道目錄也是一種文件,那么它也有inode和block。普通文件的block塊存儲的是文件內容,目錄的block塊則存儲了該目錄下所有文件的inode號及對應的文件名等信息。
所以重命名一個文件,只是修改了它所在目錄的目錄block中的文件名信息,不會對文件的inode結構做任何修改。
既然inode這么有用,可以標識唯一的一個文件,那么Java如何獲取這個inode信息呢。因為經常會遇到判斷兩個文件是否是同一個文件的場景。
Java NIO提供了一個BasicFileAttributes接口來獲得文件的Inode信息。它提供了一個 fileKey()方法,返回一個Object,這個Object包含了文件的deviceid和 inode號,可以唯一的標識一個文件。
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
public class INodeAttributes {
public static void main(String[] args) throws Exception {
Path path = Paths.get("/xxxxx/log.txt2");
BasicFileAttributes bfa = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("Creation Time : " + bfa.creationTime());
System.out.println("Last Access Time : " + bfa.lastAccessTime());
System.out.println("Last Modified Time : " + bfa.lastModifiedTime());
System.out.println("Is Directory : " + bfa.isDirectory());
System.out.println("Is Other : " + bfa.isOther());
System.out.println("Is Regular File : " + bfa.isRegularFile());
System.out.println("Is Symbolic Link : " + bfa.isSymbolicLink());
System.out.println("Size : " + bfa.size());
Object objectKey = bfa.fileKey();
System.out.println("Object Key : " + bfa.fileKey());
}
}
看到結果輸出的deviceid和inode號和用Linux stat命令返回的結果是一致的
Creation Time : 2015-01-21T03:20:41Z
Last Access Time : 2015-01-21T03:38:01Z
Last Modified Time : 2015-01-21T03:20:41Z
Is Directory : false
Is Other : false
Is Regular File : true
Is Symbolic Link : false
Size : 0
Object Key : (dev=1000003,ino=1821216)