使用 JNA 检索文件和文件夹的唯一标识符
Using JNA to retrieve unique identifier for Files and Folders
我正在尝试结合 java.nio watchevent 实现文件同步。虽然,正如其他帖子中已知和讨论的那样,它不处理重命名和移动。我尝试了 jpathwatch,它似乎并没有真正涵盖我需要的场景,所以我尝试获取唯一的对象标识符,从而能够自己跟踪这些事件。
我遇到的问题是我尝试使用 JNA 实现 BY_HANDLE_FILE_INFORMATION,它对文件工作正常。但是当我尝试以这种方式访问目录时,我得到 null return 和错误 6。因此,我试图确定的是为文件和文件夹获取可跟踪 ID 的最佳方式。如果我犯了一些错误,我在本地或 eclipse 上遇到了一些问题,或者如果我可能需要在别处寻找此信息。
我的测试代码如下:
@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 上遇到了同样的问题。
更新:意识到我调用 getlasterror 的时间晚了,但更新了代码,它首先给出错误 5,然后给出错误 6。错误 5 表示权限问题,但所有用户和 运行 eclipse 的完全权限不幸的是,在管理员模式下没有帮助。所有文件都工作正常,没有文件夹工作。
找到问题,问题出在 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);
我正在尝试结合 java.nio watchevent 实现文件同步。虽然,正如其他帖子中已知和讨论的那样,它不处理重命名和移动。我尝试了 jpathwatch,它似乎并没有真正涵盖我需要的场景,所以我尝试获取唯一的对象标识符,从而能够自己跟踪这些事件。
我遇到的问题是我尝试使用 JNA 实现 BY_HANDLE_FILE_INFORMATION,它对文件工作正常。但是当我尝试以这种方式访问目录时,我得到 null return 和错误 6。因此,我试图确定的是为文件和文件夹获取可跟踪 ID 的最佳方式。如果我犯了一些错误,我在本地或 eclipse 上遇到了一些问题,或者如果我可能需要在别处寻找此信息。
我的测试代码如下:
@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 上遇到了同样的问题。
更新:意识到我调用 getlasterror 的时间晚了,但更新了代码,它首先给出错误 5,然后给出错误 6。错误 5 表示权限问题,但所有用户和 运行 eclipse 的完全权限不幸的是,在管理员模式下没有帮助。所有文件都工作正常,没有文件夹工作。
找到问题,问题出在 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);