我希望获得 Java 中稀疏文件的准确(即磁盘上的实际大小,而不是包含所有 0 的正常大小)测量值。
在 Windows 上的 C++ 中,人们会使用GetCompressedFileSize
. 我还没有遇到过如何在 Java 中做到这一点?
如果没有直接的等价物,我将如何测量稀疏文件中的数据,而不是包括所有零的大小?
为了澄清起见,我希望在 Linux 操作系统和 Windows 上运行稀疏文件测量,但是我不介意编写两个单独的应用程序!
我希望获得 Java 中稀疏文件的准确(即磁盘上的实际大小,而不是包含所有 0 的正常大小)测量值。
在 Windows 上的 C++ 中,人们会使用GetCompressedFileSize
. 我还没有遇到过如何在 Java 中做到这一点?
如果没有直接的等价物,我将如何测量稀疏文件中的数据,而不是包括所有零的大小?
为了澄清起见,我希望在 Linux 操作系统和 Windows 上运行稀疏文件测量,但是我不介意编写两个单独的应用程序!
如果你是单独在 Windows 上做的,你可以用 Java Native Interface 来写
class NativeInterface{
public static native long GetCompressedFileSize(String filename);
}
在 C/C++ 文件中:
extern "C"
JNIEXPORT jlong JNICALL Java_NativeInterface_GetCompressedFileSize
(JNIEnv *env, jobject obj, jstring javaString)
{
const char *nativeString = env->GetStringUTFChars(javaString, 0);
char buffer[512];
strcpy(buffer, nativeString);
env->ReleaseStringUTFChars(javaString, nativeString);
return (jlong) GetCompressedFileSize(buffer, NULL);
}
如果您想要一个纯 Java 解决方案,您可以尝试jnr-posix。这是一个示例实现
import jnr.posix.*;
final POSIX p = POSIXFactory.getPOSIX();
final int S_BLKSIZE = 512; // from sys/stat.h
final FileStat stat = p.stat("/path/to/file");
final long bytes = stat.blocks() * S_BLKSIZE;
但是目前该功能不适用于 Windows。在修复之前,您必须使用特定于平台的代码,如下所示
在 Linux 上使用stat64
系统调用
st_blocks 字段表示分配给文件的块数,以 512 字节为单位。(当文件有洞时,这可能小于 st_size/512。)
在 Windows 上,您可以调用GetCompressedFileSize
API
或者,您也可以fsutil file layout
使用管理员权限运行以获取有关文件的详细信息。找到$DATA
流。
如果您看到居民 | 在这样的标志中没有分配集群,那么它是一个常驻文件,磁盘上的大小将为 0。
PS C:\Users> fsutil file layout .\desktop.ini
********* File 0x000800000003dbde *********
File reference number : 0x000800000003dbde
File attributes : 0x00000026: Hidden | System | Archive
File entry flags : 0x00000000
Link (ParentID: Name) : 0x001f0000000238c8: HLINK Name : \Users\desktop.ini
...
Stream : 0x080 ::$DATA
Attributes : 0x00000000: *NONE*
Flags : 0x0000000c: Resident | No clusters allocated
Size : 174
Allocated Size : 176
如果您没有看到 resident 标志,请检查Allocated Size字段,它是文件在磁盘上的大小
PS D:\> fsutil file layout .\nonresident.txt
********* File 0x000400000000084e *********
File reference number : 0x000400000000084e
File attributes : 0x00000020: Archive
File entry flags : 0x00000000
Link (ParentID: Name) : 0x0005000000000005: HLINK Name : \nonresident.txt
...
Stream : 0x080 ::$DATA
Attributes : 0x00000000: *NONE*
Flags : 0x00000000: *NONE*
Size : 1,520
Allocated Size : 4,096
Extents : 1 Extents
: 1: VCN: 0 Clusters: 1 LCN: 1,497,204
有关更多信息,您可以阅读以下问题
由于给出了 windows 的答案。我将尝试为 Linux 提供。
我不确定,但我认为它会成功(C++):
#include <linux/fs.h>
ioctl(file, BLKGETSIZE64, &file_size_in_bytes);
这可以按照@Aniket 答案 (JNI) 中描述的相同方式加载