2011-11-29 107 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