使用JNA检索文件和文件夹的唯一标识符

时间:2015-07-29 17:20:00

标签: java eclipse jna createfile kernel32

我试图与java.nio watchevent一起实现文件同步。虽然,如其他帖子所知和讨论的那样,它不会处理重命名和移动。我尝试了jpathwatch,它似乎并没有真正涵盖我需要的场景,因此我尝试获取唯一的对象标识符,从而能够自己跟踪这些事件。

我遇到的问题是我尝试使用JNA实现BY_HANDLE_FILE_INFORMATION,并且它适用于文件。但是当我尝试以这种方式访问​​目录时,我得到null返回和错误6。因此,我试图确定是获取文件和文件夹的可跟踪ID的最佳方法。如果我犯了一些错误,我在本地或使用eclipse发出som问题,或者我可能需要到其他地方寻找这些信息。

我的测试代码如下:

@Override
public String getUniqueFileId(Path file) {
    BY_HANDLE_FILE_INFORMATION nfo = new BY_HANDLE_FILE_INFORMATION();
    HANDLE handle = com.sun.jna.platform.win32.Kernel32.INSTANCE.CreateFile(file.toString(), 0x80000000, 0x00000001, null, 3, 0x80, null);
    if(Kernel32.INSTANCE.GetLastError() != 0) {
        LOGGER.error("Error occured for '" + file.toString() + "' (Error " + Kernel32.INSTANCE.GetLastError() + ")");
    }
    Kernel32.INSTANCE.GetFileInformationByHandle(handle, nfo);
    if(Kernel32.INSTANCE.GetLastError() != 0) {
        LOGGER.error("Error occured for '" + file.toString() + "' (Error " + Kernel32.INSTANCE.GetLastError() + ")");
    }
    String identifier = nfo.nFileIndexHigh + nfo.nFileIndexLow.toString() + Integer.toHexString(nfo.dwVolumeSerialNumber.intValue());
    com.sun.jna.platform.win32.Kernel32.INSTANCE.CloseHandle(handle); 
    return identifier;
}

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

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 List<String> getFieldOrder() {
        return Arrays.asList(new String[] { 
            "dwFileAttributes", 
            "ftCreationTime", 
            "ftLastAccessTime", 
            "ftLastWriteTime",
            "dwVolumeSerialNumber",
            "nFileSizeHigh",
            "nFileSizeLow",
            "nNumberOfLinks",
            "nFileIndexHigh",
            "nFileIndexLow"
        });
    };  
}; 

boolean GetFileInformationByHandle(HANDLE hFile, BY_HANDLE_FILE_INFORMATION lpFileInformation);

}

如果有人发现任何问题或者可以让我朝着正确的方向努力,我会很高兴。

我正在使用Wondows 10 / Eclipse但在Windows 8上遇到了同样的问题。

UPDATE:意识到我把getlasterror称为迟到了,但是更新了代码并且它给出了med第一个错误5,然后是错误6.错误5表示权限问题,但是对于所有用户的完全权限以及在管理员模式下运行eclipse不幸没有帮助。所有文件都正常工作,没有文件夹工作。

1 个答案:

答案 0 :(得分:0)

发现问题,这与createFile中的dwFlagsAndAttributes有关。

使用这些参数可以检索文件和文件夹的标识符。

private final int GENERIC_READ = 0x80000000;
private final int FILE_SHARE_READ = 0x00000001;
private WinBase.SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES = null;
private final int OPEN_EXISTING = 3;
private final int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;

调用createFile

HANDLE handle = com.sun.jna.platform.win32.Kernel32.INSTANCE.CreateFile(file.toString(), GENERIC_READ, FILE_SHARE_READ, SECURITY_ATTRIBUTES, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);