java、android 對比兩個目錄或文件是否是同一個目錄或文件的方法


由於軟鏈接及android的外部卡mount方式存在,導致一個文件夾可能同時有兩個路徑,如: /mnt/sdcard1      /storage/ext_sdcard ,如果通過某種方式(如mount命令)得到了這兩個路徑,但是現在要給路徑去重,可以采用如下方法:

一、首先,要判斷目錄是否是同一個目錄,可能會用到判斷一個文件是否是同一個文件的方法,如果已經得到文件的路徑 filePath1 和 filePath2,則可以這樣來對比是否是同一個物理文件:

1、先檢查這兩個文件是否是符號鏈接,若是符號鏈接,通過采用File.getCanonicalPath() 的方法得到文件的正規路徑(Canonical是規范的、正規的、正則的意思):

檢查文件是否是符號鏈接:

// 自己補上: 先檢查文件是否存在,不存在則直接返回 false
public
static boolean isSymlink(File file) throws IOException { if (file == null) throw new NullPointerException("File must not be null"); File canon; if (file.getParent() == null) { canon = file; } else { File canonDir = file.getParentFile().getCanonicalFile(); canon = new File(canonDir, file.getName()); } return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); }

如果是符號鏈接,采用File.getCanonicalPath()的方法得到文件的規范路徑:

// 自己加上:先檢查文件是否存在,不存在則直接返回 file.getAbsolutePath() 或者 a.getPath()
if (isSymlink(file)) {
  return file.getCanonicalFile();
}

關於canonical pathname的解釋:

A canonical pathname is both absolute and unique. The precise definition of canonical form is system-dependent. This method first converts this pathname to absolute form if necessary, as if by invoking the getAbsolutePath() method, and then maps it to its unique form in a system-dependent way. This typically involves removing redundant names such as "." and ".." from the pathname, resolving symbolic links (on UNIX platforms), and converting drive letters to a standard case (on Microsoft Windows platforms).

2、得到文件的canonical path之后,對比文件的inode是否相等:

Runtime.getRuntime().exec("ls -i" + " " + file_canonical_path);

然后得到輸出后先trim,再split(" "),再判斷獲得的第一個元素是否全是數字,如果全是數字則是其inode。

 

 

二、判斷兩個目錄(A和B)是否是同一個目錄:

 1、先通過查找某個文件夾目錄(如A)里的第一個文件,找到其相對路徑:

public void listFilesForFolder(final File folder) {
if (!folder.exists()) return;

for (final File fileEntry : folder.listFiles()) { if (fileEntry.isDirectory()) { listFilesForFolder(fileEntry); } else { System.out.println(fileEntry.getName()); } } }

上面的程序可以找到某文件夾里的所有文件,自己取某些文件即可。

得到該文件夾(A)的某些文件之后,通過獲得這些文件的 AbsolutePath 字符串,然后再從 這些 AbsolutePath 字符串里去掉 文件夾A的 AbsolutePath 字符串,就得到了這些文件的相對路徑。注意,建議別用網上找到的方法來獲取相對路徑(因為有些時候 toURI() 會改變文件的路徑,由於某些符號映射機制,如我的 android手機(華為榮耀7) 里的 /storage/sdcard1 就被映射成了 /storage/0123-4567,所有/storage/sdcard1目錄下的文件,調用 toURI()之后都被改變了根目錄為 /storage/0123-4567 ):

ring path = "/var/data/stuff/xyz.dat";
String base = "/var/data";
String relative = new File(base).toURI().relativize(new File(path).toURI()).getPath();     # 不要用這種方法獲取相對路徑

 

除了上面得到相對路徑的方法外,還有一種更好的方法得到第一個文件的相對路徑,建議用下面這種方法得到相對路徑:

public void listFilesForFolder(final File folder) {
    if (!folder.exists()) return;

    String relativePath = "";
String fileName = "";
for (final File fileEntry : folder.listFiles()) { if (fileEntry.isDirectory()) {
relativePath += fileEntry.getName() + "/"; listFilesForFolder(fileEntry); }
else {
fileNmae = fileEntry.getName(); System.out.println(fileEntry.getName());
break; } } }

 

2、得到文件夾A里某些文件的相對路徑之后,在B文件夾里創建這些文件,即new File(B, fileRelativePath), 將這些文件與文件夾A的相應的文件進行對比,看看他們的inode是否相同。相同則表明A和B是同一個文件夾,如果不同,則不是同一個文件夾。方法如下:

假如從文件夾A得到里一個文件 dir/file1.txt,通過字串方式去掉前面A的路徑,自然語言描述如下:

File file1A = new File("A", "dir/file1.txt");

File file1B = new File("B", file1RelativePath);

if (!file1B.exists()) 則A和B不是同一個目錄;

if (file1B的inode等於file1A的inode)則是同一個目錄,否則不是。獲取inode的時候不用將符號鏈接變成Canonical Path,即不推薦將兩個文件都調用 getCanonicalFile(),因為如果A和B是同一個文件夾,則它里面的文件(哪怕是符號鏈接文件)也應該是同一個文件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM