2011-11-29 14 views
6

Sto cercando un modo per ottenere un ID unico file in un'applicazione Java, e sono imbattuto in questo:Ottieni un ID file univoco in Windows con Java?

Unique file identifier in windows

Ora, ho provato la risposta fornita da Ashley Henderson se stesso (quello che ha chiesto la domanda), e che ha funzionato bene in C#. Ma ho bisogno di farlo in Java, per far funzionare l'app su tutte le piattaforme.

Esiste un modo per eseguire il porting su Java o ottenere lo stesso ID in un altro modo?

EDIT:

ho quasi ottenuto lavorando ora, utilizzando la soluzione eee, solo ho bisogno di essere in una biblioteca, e quando compilo come una biblioteca ottengo un errore, anche se tutto è lavorando bene in un'applicazione di test con tutto incluso. Ma con una libreria separata che si tenta di importare (nessun errore del compilatore) ottengo questo errore di runtime:

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) 

Ho incluso il jna.jar e platform.jar nella libreria quando ho compilato esso ... Per favore ricorda che sono molto nuovo in Java, ma cosa sto sbagliando?

+1

Sospetto che tu avrebbe dovuto usare JNI per averlo. Perché vorresti comunque queste informazioni? – jontro

+0

qual è il caso d'uso? Perché hai bisogno dell'ID univoco? – aishwarya

+0

Il caso d'uso è quello di tenere traccia dei file quando vengono spostati o rinominati, per preservare i collegamenti da altri file. – Anders

risposta

4

Utilizzando JNA versione 3.3.0: caso

Kernel32.INSTANCE.GetFileInformationByHandle Test: uscita

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

    } 

} 

Esempio:

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 classe esempio:

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

Wow, grazie per la risposta dettagliata ...! Come ho detto, però, questo è un po 'sopra la mia testa, e sono completamente nuovo a Java per l'avvio, avendo programmato solo in C# prima. Ma devo fare una prova ora che hai fornito un esempio così dettagliato ... Ma non capisco dove si specifica il file da controllare? Probabilmente è lì, ma è difficile per me decodificarlo. Inoltre, qual è il FILE INDEX HIGH vs FILE INDEX LOW? Nell'esempio che ho usato (dal link) c'era solo un valore di indice, quindi quale dovrei usare qui per identificare il file? – Anders

+0

BTW, dal momento che JNA sembra essere in grado di accedere al codice nativo in DLL, non c'è un modo per farlo semplicemente compilando il codice nel link di esempio (che ho già in C# in lavorazione) in una DLL, e poi chiamarlo con JNA? Se lo è, apprezzerei davvero un semplice esempio ... speravo solo che potesse essere più semplice. – Anders

+0

@AndersSvensson sì, lo si può fare ma è un po 'difficile da quando si inizia con la DLL C# piuttosto che con la DLL C/C++ che quest'ultima è la convenzione di chiamata DLL preferita in JNA. È necessario avvolgere la DLL C# nella DLL C/C++ prima di poterla utilizzare con JNA. Questo è quello che posso capire con JNA. – ecle

0

Non è possibile utilizzare il percorso del file come ID univoco?!

percorso completo del file è abbastanza unico nel suo genere ...

+3

Sì, è univoco, ma non viene mantenuto quando si sposta un file in un'altra directory, che sembra essere l'intenzione dietro l'ID del file. –

+0

Esatto, il punto è essere in grado di spostare i file e rinominarli liberamente, quindi i percorsi dei file sono in realtà ciò che devo scoprire dopo tali spostamenti o ridenominazioni. – Anders

1

In Java si avrebbe bisogno JNI, compilazione nativa C, sia per Windows (utilizzando il codice C#), e per Unix/Linux (usando l'inode di un file). Onestamente non penso che questo sia molto sicuro.

+0

+1 Anche il filesystem in uso è importante, rendendo ancora più difficile la portabilità - buona fortuna su FAT, ad esempio :) –

+0

Sì, ho esaminato brevemente questo aspetto e speravo che ci fosse un modo più semplice. Ma speravo di non dover compilare questo e usarlo come è in Java, ma piuttosto se ci fosse un modo per riscriverlo in Java per ottenere lo stesso id ... Ottenere un id di file in * nix è molto più semplice, ma non riesco a trovare un modo per farlo per Windows tranne questo esempio in C#. A proposito, la FAT non è un problema. Sarà NTFS in Windows e Mac OS X è l'altro sistema operativo che devo prendere in considerazione. – Anders

+0

vedere la mia soluzione JNA – ecle