是否有Java等效的GetCompressedFileSize?

时间:2013-02-06 17:46:02

标签: java file filesize on-disk

我希望在Java中准确(即磁盘上的实际大小而不是包含所有0的正常大小)测量稀疏文件。

在Windows上的C ++中,可以使用GetCompressedFileSize。我还没有想到如何在Java中实现这一目标?

如果没有直接的等价物,我将如何测量稀疏文件中的数据,而不是包括所有零的大小?

为了澄清,我希望在Linux OS和Windows上运行备用文件测量,但我不介意编写两个单独的应用程序!

3 个答案:

答案 0 :(得分:1)

如果您仅在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);
}

答案 1 :(得分:1)

如果您要使用纯Java解决方案,可以尝试jnr-posix。这是一个example implementation

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;

但是目前功能won't work for Windows。在此问题解决之前,您必须使用下面的平台特定代码

  • 在Linux上,使用stat64系统调用

      

    st_blocks字段指示以512字节为单位分配给文件的块数。 (当文件有孔时,它可能小于st_size / 512。)

    • 您也可以运行stat命令。分配的块数可以在Blocks字段中看到,或使用%b格式说明符打印出来
    • 或使用du command(不带--apparent-size选项)
        

      -表观尺寸

           
          
      • 打印表观大小,而不是磁盘使用情况;尽管表观大小通常较小,但由于(“稀疏”)文件中的漏洞,内部碎片,间接块等,它可能会更大
      •   
  • 在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
        
      • 如果没有看到驻留标志,请检查 Allocation 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
        

有关更多信息,您可以阅读以下问题

答案 2 :(得分:0)

因为给出了windows的答案。我将尝试为Linux提供。

我不确定,但我认为它会起作用(C ++):

#include <linux/fs.h>
ioctl(file, BLKGETSIZE64, &file_size_in_bytes);

这可以用@Aniket答案(JNI)中描述的相同方式加载