2011-11-29 11 views
6

Busco una forma de obtener un identificador de archivo único en una aplicación Java, y me encontré con esto:¿Obtiene ID de archivo único en Windows con Java?

Unique file identifier in windows

Ahora, he intentado la respuesta suministrada por el propio Ashley Henderson (la que pidió la pregunta), y eso funcionó bien en C#. Pero necesito hacer esto en Java, para que la aplicación funcione en todas las plataformas.

¿Hay alguna forma de llevar esto a Java, o obtener la misma identificación de otra manera?

EDIT:

Casi tengo trabajo ahora, el uso de la solución mediante eee, solamente lo necesito estar en una biblioteca, y cuando compilo como una biblioteca consigo un error, a pesar de que todo está funciona bien en una aplicación de prueba con todo incluido. Pero con una biblioteca independiente que intento importar (no hay errores de compilación) me sale este error de ejecución:

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) 

He incluido el jna.jar y platform.jar en la biblioteca cuando compilé que ... Tenga en cuenta una vez más que soy muy nuevo en Java, pero ¿qué estoy haciendo mal?

+1

sospecho que tu Tendría que usar JNI para obtenerlo. ¿Por qué querrías esta información de todos modos? – jontro

+0

cuál es el caso de uso, ¿por qué necesita la identificación única? – aishwarya

+0

El caso de uso es realizar un seguimiento de los archivos cuando se mueven o cambian de nombre, para conservar los enlaces de otros archivos. – Anders

Respuesta

4

Al usar la versión JNA 3.3.0: caso

Prueba Kernel32.INSTANCE.GetFileInformationByHandle: salida

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

    } 

} 

muestra:

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 clase ejemplo:

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

¡Guau, gracias por esa respuesta detallada ...! Como mencioné, sin embargo, esto está un poco sobre mi cabeza, y soy completamente nuevo en Java para arrancar, habiendo programado solo en C# antes. Pero tengo que probar esto ahora que me proporcionó un ejemplo tan detallado ... ¿Pero no entiendo dónde especifica el archivo que se va a verificar? Probablemente esté allí, pero es difícil para mí descifrar esto. Además, ¿cuál es el ÍNDICE DE ARCHIVO ALTO frente al ÍNDICE DE ARCHIVO BAJO? En el ejemplo que utilicé (del enlace), solo había un valor de índice, entonces, ¿qué debería usar aquí para identificar el archivo? – Anders

+0

BTW, dado que JNA parece ser para acceder al código nativo en dlls, no hay una manera de hacerlo simplemente compilando el código en el enlace de ejemplo (que ya tengo en C# trabajando) en un dll, y luego llamarlo con JNA? Si es así, realmente apreciaría un ejemplo simple ... Esperaba que eso fuera más simple. – Anders

+0

@AndersSvensson Sí, puede hacerlo, pero es un poco difícil ya que comienza con C# DLL en lugar de C/C++ DLL, que es la convención de llamada DLL preferida en JNA. Debe envolver su C# DLL en C/C++ DLL antes de poder usarlo con JNA. Eso es lo que puedo entender con JNA. – ecle

0

¿No puedes usar la ruta del archivo como su id único?

ruta de archivo completa es único suficiente ...

+3

Sí, es único, pero no se conserva cuando mueve un archivo a otro directorio, que parece ser la intención detrás de la identificación del archivo. –

+0

Correcto, el punto es poder mover los archivos y cambiarles el nombre libremente, así que las rutas de archivos son en realidad lo que necesito averiguar después de dichos movimientos o renombrados. – Anders

1

En Java se necesitaría JNI, compilación C nativo, tanto para Windows (usando el código C#), y para Unix/Linux (usando el inodo de un archivo) Honestamente, no creo que esto sea muy seguro.

+0

+1 El sistema de archivos en uso también es importante, lo que dificulta aún más la portabilidad: buena suerte en FAT, por ejemplo :) –

+0

Sí, lo estudié brevemente y esperaba que hubiera una manera más sencilla. Pero esperaba no tener que compilar esto y usarlo tal como está en Java, sino más bien si había una forma de reescribirlo en Java para obtener el mismo ID ... Obtener un ID de archivo en * nix es mucho más simple, pero no puedo encontrar una forma de hacerlo para Windows, excepto este ejemplo en C#. Por cierto, la grasa no es un problema. Va a ser NTFS en Windows, y Mac OS X es el otro sistema operativo que necesito considerar. – Anders

+0

ver mi solución JNA – ecle

Cuestiones relacionadas