Java NTFS压缩属性
我需要从Java读取并修改NTFS分区上文件的“Compressed”属性。我想象包中的某些东西可以做到这一点——见鬼,这是一个足够复杂的包,但我找不到这个属性Java NTFS压缩属性,java,ntfs,file-attributes,Java,Ntfs,File Attributes,我需要从Java读取并修改NTFS分区上文件的“Compressed”属性。我想象包中的某些东西可以做到这一点——见鬼,这是一个足够复杂的包,但我找不到这个属性 DosFileAttributes类只有经典的hidden/system/readonly/archive属性的getter 我尝试了从特定的“属性视图”中动态检索所有属性。在“dos:*”下,只有与DosFileAttributes类的公共方法相同的属性可用。我尝试了“ntfs:*”和“windows:*”,但它们不能作为有效的视图名
DosFileAttributes
类只有经典的hidden/system/readonly/archive属性的getter
我尝试了从特定的“属性视图”中动态检索所有属性。在“dos:*”下,只有与DosFileAttributes
类的公共方法相同的属性可用。我尝试了“ntfs:*”和“windows:*”,但它们不能作为有效的视图名称
我还尝试了UserDefinedFileAttributeView
,但它在我尝试的任何文件上都给了我一个空列表
我想知道如何使用这个命令(接受它对在Linux或其他操作系统下安装的NTFS分区不起作用的限制),但它似乎也不支持这个属性。帮助?尝试使用BasicFileAttributes并检查isOther()和isRegularFile()标志,而不是DosFileAttributes。这可能会告诉您文件是否已压缩。如果没有,您将不得不为NTFS创建自己的FileSystemProvider impl,或者编写小型JNI代码,使用WinAPI为您读取该标志。由于标准Java API中似乎缺少这一点,因此我考虑自己做这件事。这是我第一次体验JNA。它并没有我所希望的那么漂亮,JNA的代码似乎非常缺乏泛型,但这比玩弄JNI并试图为所需的不同平台设置糟糕的交叉编译器要好一百倍(即使您只针对一个操作系统,也至少需要x86和x64)。这是一个恼人的编译过程,首先把我从C++驱动到java,我希望永远不要返回它。 不管怎样,这似乎奏效了。希望它对其他人也有用。它提供了四种公共方法:
——调用其他方法是否可行(即,我们在Windows上,JNA本机库加载正常)isAvailable()
isCompressed(文件)
setCompressed(文件,布尔值)
——询问Windows文件所在的分区是否支持[单个]文件压缩。例如,在NTFS上为真,在FAT(U盘等)上为假卷支持文件压缩(文件)
import java.io.File;
import java.io.IOException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.ShortByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class WindowsFileOps {
private WindowsFileOps() {}
private static interface Kernel32Extra extends StdCallLibrary {
int COMPRESSION_FORMAT_NONE = 0x00000000;
int COMPRESSION_FORMAT_DEFAULT = 0x00000001;
int FSCTL_SET_COMPRESSION = 0x0009C040;
Kernel32Extra INSTANCE = (Kernel32Extra)Native.loadLibrary("kernel32",
Kernel32Extra.class, W32APIOptions.UNICODE_OPTIONS);
boolean GetVolumeInformation(
String lpRootPathName,
Pointer lpVolumeNameBuffer,
int nVolumeNameSize,
IntByReference lpVolumeSerialNumber,
IntByReference lpMaximumComponentLength,
IntByReference lpFileSystemFlags,
Pointer lpFileSystemNameBuffer,
int nFileSystemNameSize
);
}
private static Boolean isAvailable;
public static boolean isAvailable() {
if (isAvailable == null) {
try {
isAvailable = Kernel32.INSTANCE != null && Kernel32Extra.INSTANCE != null;
} catch (Throwable t) {
isAvailable = false;
}
}
return isAvailable;
}
private static String pathString(File file) {
// "\\?\" is a Windows API thing that enables paths longer than 260 chars
return "\\\\?\\" + file.getAbsolutePath();
}
private static int getAttributes(File file) throws IOException {
int attrib = Kernel32.INSTANCE.GetFileAttributes(pathString(file));
if (attrib == Kernel32.INVALID_FILE_ATTRIBUTES) {
throw new IOException("Unable to read file attributes of " + file);
}
return attrib;
}
public static boolean isCompressed(File file) throws IOException {
return (getAttributes(file) & Kernel32.FILE_ATTRIBUTE_COMPRESSED) != 0;
}
public static void setCompressed(File file, boolean compressed) throws IOException {
HANDLE hFile = Kernel32.INSTANCE.CreateFile(
pathString(file),
Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
Kernel32.FILE_SHARE_READ,
null,
Kernel32.OPEN_EXISTING,
0,
null);
try {
if (!Kernel32.INSTANCE.DeviceIoControl(
hFile,
Kernel32Extra.FSCTL_SET_COMPRESSION,
new ShortByReference((short)(
compressed
? Kernel32Extra.COMPRESSION_FORMAT_DEFAULT
: Kernel32Extra.COMPRESSION_FORMAT_NONE
)).getPointer(),
2,
null, 0,
new IntByReference(),
null
)) throw new IOException("Unable to alter compression attribute of " + file);
} finally {
Kernel32.INSTANCE.CloseHandle(hFile);
}
}
public static boolean volumeSupportsFileCompression(File file) throws IOException {
IntByReference flags = new IntByReference();
if (!Kernel32Extra.INSTANCE.GetVolumeInformation(
pathString(file.getAbsoluteFile().toPath().getRoot().toFile()),
null, 0,
null,
null,
flags,
null, 0
)) throw new IOException("GetVolumeInformation failure");
return (flags.getValue() & Kernel32.FILE_FILE_COMPRESSION) != 0;
}
}
isOther():错。isRegularFile():true;与其他文件相同。不走运。我检查了WindowsFileSystem类并发现:私有静态最终集supportedFileAttributeViews=Collections.unmodifiableSet(新哈希集(Arrays.asList(“basic”、“dos”、“acl”、“owner”、“user”));这意味着WindowsFileSystem只公开标准属性视图。我想说:把它添加到答案中。我认为如果你把这段代码贡献给jna,那就太好了。你可以随时与他们联系