2011-11-29 109 views
6

我正在尋找一種方式來獲得在Java應用程序的唯一文件ID,並跨越這來了:使用Java在Windows中獲取唯一的文件ID?

Unique file identifier in windows

現在,我試圖通過阿什利亨德森本人(即問一個提供答案問題),並在C#中工作得很好。但我需要在Java中這樣做,才能使應用程序跨平臺工作。

有什麼辦法來港這對Java或得到了相同的ID一些其他的方式?

編輯:

我幾乎得到了它現在的工作,利用EEE解決方案,只有我需要它是在圖書館,當我編譯爲一個庫,我得到一個錯誤,即使一切在包含所有內容的測試應用程序中正常工作。但我嘗試導入(無編譯器錯誤)一個單獨的圖書館中,我得到這個運行時錯誤:

debug: 
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/jna/Structure 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) 
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    at winfileid.FileId.getFileId(FileId.java:37) 
    at testfileid.TestFileId.main(TestFileId.java:19) 
Caused by: java.lang.ClassNotFoundException: com.sun.jna.Structure 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    ... 14 more 
Java Result: 1 
BUILD SUCCESSFUL (total time: 0 seconds) 

我已經包括在庫中jna.jar和platform.jar當我編譯它...請再次注意,我對Java很新,但是我做錯了什麼?

+1

我懷疑你將不得不使用JNI來獲取它。無論如何,你爲什麼要這個信息? – jontro

+0

什麼是用例 - 爲什麼你需要唯一的ID? – aishwarya

+0

用例是在文件移動或重命名時跟蹤文件,以保留來自其他文件的鏈接。 – Anders

回答

4

使用JNA版本3.3.0:

Kernel32.INSTANCE.GetFileInformationByHandle測試用例:

package win.test; 

import com.sun.jna.platform.win32.Kernel32; 
import com.sun.jna.platform.win32.WinBase; 
import com.sun.jna.platform.win32.WinBase.FILETIME; 
import com.sun.jna.platform.win32.WinNT.HANDLE; 

import win.test.Kernel32.BY_HANDLE_FILE_INFORMATION; 


public class FileTest { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     //http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx 
     final int FILE_SHARE_READ = (0x00000001); 
     //final int FILE_SHARE_WRITE = (0x00000002); 
     //final int FILE_SHARE_DELETE = (0x00000004); 
     final int OPEN_EXISTING = (3); 
     final int GENERIC_READ = (0x80000000); 
     //final int GENERIC_WRITE = (0x40000000); 
     //final int FILE_FLAG_NO_BUFFERING = (0x20000000); 
     //final int FILE_FLAG_WRITE_THROUGH = (0x80000000); 
     //final int FILE_READ_ATTRIBUTES = (0x0080); 
     //final int FILE_WRITE_ATTRIBUTES = (0x0100); 
     //final int ERROR_INSUFFICIENT_BUFFER = (122); 
     final int FILE_ATTRIBUTE_ARCHIVE = (0x20); 

     WinBase.SECURITY_ATTRIBUTES attr = null; 
     BY_HANDLE_FILE_INFORMATION lpFileInformation = new BY_HANDLE_FILE_INFORMATION(); 
     HANDLE hFile = null; 

     hFile = Kernel32.INSTANCE.CreateFile(args[0], GENERIC_READ, FILE_SHARE_READ, attr, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, null); 

     System.out.println("CreateFile last error:" + Kernel32.INSTANCE.GetLastError()); 

     //if (hFile. != -1) 
     { 

      win.test.Kernel32.INSTANCE.GetFileInformationByHandle(hFile, lpFileInformation); 

      System.out.println("CREATION TIME: " + FILETIME.filetimeToDate(lpFileInformation.ftCreationTime.dwHighDateTime, lpFileInformation.ftCreationTime.dwLowDateTime)); 

      System.out.println("VOLUME SERIAL NO.: " + Integer.toHexString(lpFileInformation.dwVolumeSerialNumber.intValue())); 

      System.out.println("FILE INDEX HIGH: " + lpFileInformation.nFileIndexHigh); 
      System.out.println("FILE INDEX LOW: " + lpFileInformation.nFileIndexLow); 


      System.out.println("GetFileInformationByHandle last error:" + Kernel32.INSTANCE.GetLastError()); 
     } 

     Kernel32.INSTANCE.CloseHandle(hFile); 

     System.out.println("CloseHandle last error:" + Kernel32.INSTANCE.GetLastError()); 

    } 

} 

輸出示例:

CreateFile last error:0 
CREATION TIME: Tue Nov 29 22:24:04 SGT 2011 
VOLUME SERIAL NO.: 900c0655 
FILE INDEX HIGH: 1769472 
FILE INDEX LOW: 286306 
GetFileInformationByHandle last error:0 
CloseHandle last error:0 

的Kernel32 JNA實例類:

package win.test; 

import java.util.HashMap; 
import java.util.Map; 

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.Structure; 
import com.sun.jna.WString; 
import com.sun.jna.platform.win32.WinBase.FILETIME; 
import com.sun.jna.platform.win32.WinDef.DWORD; 
import com.sun.jna.platform.win32.WinNT.HANDLE; 
import com.sun.jna.win32.StdCallLibrary; 
import com.sun.jna.win32.W32APIFunctionMapper; 
import com.sun.jna.win32.W32APITypeMapper; 

public interface Kernel32 extends StdCallLibrary { 
    final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() { 
     private static final long serialVersionUID = 1L; 
     { 
      put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); 
      put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); 
     } 
    }; 

    public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class, WIN32API_OPTIONS); 

    public int GetLastError(); 

    /** 
    typedef struct _BY_HANDLE_FILE_INFORMATION { 
      DWORD dwFileAttributes; 
      FILETIME ftCreationTime; 
      FILETIME ftLastAccessTime; 
      FILETIME ftLastWriteTime; 
      DWORD dwVolumeSerialNumber; 
      DWORD nFileSizeHigh; 
      DWORD nFileSizeLow; 
      DWORD nNumberOfLinks; 
      DWORD nFileIndexHigh; 
      DWORD nFileIndexLow; 
     } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION; 
    */ 

    public class BY_HANDLE_FILE_INFORMATION extends Structure { 
     public DWORD dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public DWORD dwVolumeSerialNumber; 
     public DWORD nFileSizeHigh; 
     public DWORD nFileSizeLow; 
     public DWORD nNumberOfLinks; 
     public DWORD nFileIndexHigh; 
     public DWORD nFileIndexLow; 
     public static class ByReference extends BY_HANDLE_FILE_INFORMATION implements Structure.ByReference { 

     }; 
     public static class ByValue extends BY_HANDLE_FILE_INFORMATION implements Structure.ByValue { 

     };   
    }; 

    /** 
    BOOL WINAPI GetFileInformationByHandle(
       __in HANDLE hFile, 
       __out LPBY_HANDLE_FILE_INFORMATION lpFileInformation 
      ); 
    */ 
    boolean GetFileInformationByHandle(
       HANDLE hFile, 
       BY_HANDLE_FILE_INFORMATION lpFileInformation 
      ); 
} 
+0

哇,謝謝你的詳細解答...!正如我所提到的,儘管如此,這有點高於我的頭腦,而且我完全不熟悉Java引導,因爲之前只使用C#編程。但是,我現在必須嘗試一下這個例子,你提供了這樣一個詳細的例子......但是我不明白你指定要檢查的文件的位置?它可能在那裏,但我很難解碼這個。另外,什麼是文件索引高與文件索引低?在我使用的例子中(來自鏈接)只有一個索引值,那麼我應該在哪裏使用這個來標識文件? – Anders

+0

順便說一句,因爲JNA似乎是用於訪問dll中的本地代碼,所以沒有辦法通過簡單地將示例鏈接中的代碼(我已經在C#中工作)編譯爲一個dll來執行此操作,然後調用與JNA?如果是這樣,我會非常感激一個簡單的例子......我只是希望這可能會更簡單。 – Anders

+0

@AndersSvensson是的,你可以做到這一點,但是從C#DLL開始,而不是C/C++ DLL(後者是JNA中首選的DLL調用約定)有點困難。您需要先將C#DLL封裝到C/C++ DLL中,然後才能將它用於JNA。這就是我能用JNA理解的。 – ecle

0

不能使用文件路徑作爲其唯一的ID?!

完整的文件路徑是足夠的唯一...

+3

是的,它是唯一的 - 但是當您將文件移動到另一個目錄時,它不會保留,這似乎是文件ID背後的意圖。 –

+0

正確的,重點是能夠移動文件並自由重命名,所以文件路徑實際上是我需要在移動或重命名後找出的路徑。 – Anders

1

在Java中,你需要JNI,原生的C編譯,既適用於Windows(使用C#代碼),以及Unix/Linux操作系統(使用文件的索引節點)。老實說,我不認爲這是非常安全的。

+0

+1正在使用的文件系統也很重要,進一步使可移植性更加困難 - 例如FAT上的好運:) – 2011-11-29 10:45:36

+0

是的,我簡單地看了一下,希望能有一個更簡單的方法。但是我希望不需要編譯它並像在Java中一樣使用它,而是如果有方法用Java重寫它以獲得相同的ID ...在* nix中獲取文件ID要簡單得多,但是除了C#中的這個例子,我無法找到一種方法來實現Windows。順便說一下,FAT不是一個問題。這將是Windows中的NTFS,Mac OS X是我需要考慮的另一個操作系統。 – Anders

+0

看到我的JNA解決方案 – ecle