zoukankan      html  css  js  c++  java
  • delphi 创建 Sparse File

    https://digitaltundra.com/
    https://files.cnblogs.com/files/marklove/Bigbrain2020.7.10.zip

    //**********
    // Function: Create Sparse Files
    // Input value: FileName: Sparse File Name
    // FileSize: Sparse File Size
    // Result value: True: True or False
    // Author: 果子
    // Create Date: 2006.05.02
    //**********

    function CreateSparseFile(const FileName: String; const FileSize: Int64): Boolean;
    var
    hF: THandle;
    dirStr: String;
    Temp: DWORD;
    begin
    dirStr := ExtractFileDir(FileName) ;
    if not DirectoryExists(dirStr) then
    ForceDirectories(dirStr); //创建目录
    hF := CreateFile(Pchar(FileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
    result := (hf <> INVALID_HANDLE_VALUE);
    DeviceIOControl(hF, 590020, nil, 0, nil, 0, Temp, nil);
    SetFilePointer(hF, Int64Rec(FileSize).Lo, @Int64Rec(FileSize).Hi, FILE_BEGIN);
    SetEndOfFile(hF);
    CloseHandle(hF);
    end;

    稀疏文件,这是UNIX类和NTFS等文件系统的一个特性。
    
    开始时,一个稀疏文件不包含用户数据,也没有分配到用来存储用户数据的磁盘空间。当数据被写入稀疏文件时,NTFS逐渐地为其分配磁盘空间。一个稀疏文件有可能增长得很大。
    
    稀疏文件以64KB(不同文件系统不同)为单位增量增长,因此磁盘上稀疏文件的大小总是64KB的倍数。
    
    稀疏文件就是在文件中留有很多空余空间,留备将来插入数据使用。如果这些空余空间被ASCII码的NULL字符占据,并且这些空间相当大,那么,这个文件就被称为稀疏文件,而且,并不分配相应的磁盘块。
    
    这样,会产生一个问题,文件已被创建了,但相应的磁盘空间并未被分配,只有在有真正的数据插入进来时,才会被分配磁盘块,如果这时文件系统被占满了,那么对该文件的写操作就会失败。为防止这种情况,有两种办法:不产生稀疏文件或为稀疏文件留够空间。
    
    在计算机科学方面,稀疏文件是文件系统中的一种文件存储方式,在创建一个文件的时候,就预先分配了文件需要的连续存储空间,其空间内部大多都还未被数据填充现在有很多文件系统都支持稀疏文件,包括大部分的Unix和NTFS 。
    
    稀疏文件被普遍用来磁盘图像,数据库快照,日志文件,还有其他科学运用上。
    
     
    
    1、WINDOWS中的稀疏文件
    
    稀疏文件(Sparse File), 指的是文件中出现大量的0数据,这些数据对我们用处不大,但是却一样的占用我们的空间,针对此,WINNT 3.51中的NTFS文件系统对此进行了优化,那些无用的0字节被用一定的算法压缩起来,使得这些0字节不再占用那么多的空间,在你声明一个很大的稀疏文件时(例如 100GB),这个文件实际上并不需要占用这么大的空间,因为里面大都是无用的0数据,那么,NTFS对稀疏文件的压缩算法可以释放这些无用的0字节空间,可以说这是对磁盘占用空间以及效率的一种优化,记住,FAT32上并不支持稀疏文件的压缩(至少我在自己机子上测试得出如此结论)。
    
    
    这里,我们将粗略的介绍:
    
    1,如何判断一个磁盘是否支持稀疏文件。
    2,如何判断一个文件是否是稀疏文件。
    3,如何产生一个稀疏文件。
    4,假如系统支持稀疏文件,如何声明这个文件是稀疏文件。
    
    
    1.1 判断一个磁盘是否是稀疏文件。
    
    我们可以通过一个系统函数GetVolumeInformation 来判断某个磁盘是否支持稀疏文件的压缩。MSDN中的函数原型如下:
    
    GetVolumeInformation
    
    The GetVolumeInformation function retrieves information about a file system and volume that have aspecified root directory.
    
    BOOLGetVolumeInformation(
    
    LPCTSTR lpRootPathName,
    
      LPTSTR lpVolumeNameBuffer,
    
      DWORD nVolumeNameSize,
    
      LPDWORD lpVolumeSerialNumber,
    
      LPDWORD lpMaximumComponentLength,
    
      LPDWORD lpFileSystemFlags,
    
      LPTSTR lpFileSystemNameBuffer,
    
      DWORD nFileSystemNameSize
    
    );
    
     
    
    我们只要把查询到的Flag 跟 FILE_SUPPORTS_SPARSE_FILES 位与(&),便可以知道该磁盘是否支持。
    
     
    
     
    
     
    
     
    
     
    
    这是从我的工具集(toolset)里摘录的例子代码:
    
       CHAR szVolName[MAX_PATH], szFsName[MAX_PATH];
    
       DWORD dwSN, dwFSFlag, dwMaxLen, nWritten;
    
        BOOLbSuccess;
    
       HANDLE hFile;
    
       bSuccess = GetVolumeInformation(NULL,
    
           szVolName,
    
           MAX_PATH,
    
           &dwSN,
    
           &dwMaxLen,
    
           &dwFSFlag,
    
           szFsName,
    
           MAX_PATH);
    
       if (!bSuccess) {
    
           printf("errno:%d", GetLastError());
    
           return -1;
    
        }
    
        printf("volname:%s 	 fs name:%s sn: %d.
    ", szVolName, szFsName, dwSN);
    
       if (dwFSFlag&FILE_SUPPORTS_SPARSE_FILES) {
    
           printf("support sparse file.
    ");
    
        }else{
    
           printf("no support sparse file.
    ");
    
        }
    
     
    
    2.1 如何判断一个文件是否是稀疏文件。
    
     
    
     
    
     
    
      我们可以通过 GetFileInformationByHandle()函数来判断一个文件是否是稀疏文件。这是MSDN里面的定义。
    
     
    
    The GetFileInformationByHandlefunction retrieves file information for the specified file.
    
     
    
     
    
     
    
    BOOLGetFileInformationByHandle(
    
    HANDLE hFile,
    
      LPBY_HANDLE_FILE_INFORMATION lpFileInformation
    
    );
    
     
    
    例子代码如下:
    
     
    
    HANDLE hFile;
    
    BY_HANDLE_FILE_INFORMATION stFileInfo;
    
    //Open/create file to get the file handle
    
    hFile = CreateFile( );
    
    //Get the file information
    
    GetFileInformationByHandle(hFile,&stFileInfo);
    
    if(stFileInfo.dwFileAttributes &FILE_ATTRIBUTE_SPARSE_FILE)
    
    {
    
       //Sparse file
    
    }else{
    
      //Not sparse file
    
    }
    
     
    
     
    
    3.1, 如何产生一个稀疏文件并声明该文件是稀疏文件。
    
       大部分文件,在你改变它的EndOfFile的时候,中间的空白会被操作系统填0,也就是说,如果你用SetFilePointer() 和SetEndOfFile()来
    
    产生一个很大的文件,那么这个文件它占用的是真正的磁盘空间,即使里面全是0,因为系统默认的会在DeviceIoControl()中的ControlCode里用
    
    FSCTL_SET_ZERO_DATA标记,这个标记使得那些文件空洞被0所填充。为了节省磁盘空间,我们必须把一个文件声明为稀疏文件,以便让系统
    
    把那些无用的0字节压缩,并释放相应的磁盘空间,方法如下:
    
     
    
       hFile = CreateFile("tmp_file",
    
           GENERIC_WRITE|GENERIC_READ,
    
            FILE_SHARE_READ|FILE_SHARE_WRITE,
    
           NULL,
    
           CREATE_ALWAYS,
    
           0,
    
           NULL);
    
       DWORD dwTemp;
    
       DeviceIoControl(hFile,
    
           FSCTL_SET_SPARSE,
    
           NULL,
    
           0,
    
           NULL,
    
           0,
    
           &dwTemp,
    
           NULL);
    
       SetFilePointer(hFile, 0x100000, NULL, FILE_BEGIN);
    
       WriteFile(hFile,
    
           "123",
    
           3,
    
           &nWritten,
    
           NULL);
    
       SetEndOfFile(hFile);
    
       CloseHandle(hFile);
    
     
    
    注意到FSCTL_SET_SPARSE这个标记了吗?正是这个标记,告诉系统该文件是稀疏文件,如果该文件所在的磁盘支持稀疏
    
    文件的压缩,则系统会释放不必要的0字节空间。你可以用这个方法创建一个100GB得文件试一下(示例里是1M),记得右键看看文件属性
    
    里的‘大小’和占用空间,它被声明为100GB,但是实际上那些0字节基本不占用空间,而你写入的“123”是占用实际的
    
    磁盘空间的。
    
       注意:在FAT32得磁盘里,因为没有对SPARSE FILE得支持,所以您创建的空洞文件全部被填零,即使你声明它是一个稀疏
    
    文件,也没有任何作用,您声明这个文件多大,它就占用多大的空间。
    
       另外,如果您编译 DeviceIoControl这个函数出现 "'FSCTL_SET_SPARSE': undeclared identifier"之类的情况
    
    请这样做:
    
    #include<windows.h>
    
    #define   _WIN32_WINNT         0x0501
    
    #include<Winioctl.h>
    
    
  • 相关阅读:
    LeetCode120 Triangle
    LeetCode119 Pascal's Triangle II
    LeetCode118 Pascal's Triangle
    LeetCode115 Distinct Subsequences
    LeetCode114 Flatten Binary Tree to Linked List
    LeetCode113 Path Sum II
    LeetCode112 Path Sum
    LeetCode111 Minimum Depth of Binary Tree
    Windows下搭建PHP开发环境-WEB服务器
    如何发布可用于azure的镜像文件
  • 原文地址:https://www.cnblogs.com/marklove/p/13564972.html
Copyright © 2011-2022 走看看