2010-10-25 12 views
10

Estoy probando un archivo disperso. Pero mi código de prueba no funciona bien.¿Cómo crear un archivo disperso en NTFS?

HANDLE h = CreateFileW(L"D:\\sparse.test", 
     GENERIC_READ|GENERIC_WRITE, 
     FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
     0, 
     CREATE_ALWAYS, 
     FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SPARSE_FILE, 
     0); 

DWORD d = GetFileAttributes(L"D:\\sparse.test"); 
// The function returns 32(FILE_ATTRIBUTE_ARCHIVE). 
// Where is FILE_ATTRIBUTE_SPARSE_FILE flag? 
// How do I make a sparse file. 

DWORD written; 
WriteFile(h, "aaa", 3, &written, 0); 
SetFilePointer(h, 2*1024*1024*1023, 0, FILE_BEGIN); 
SetEndOfFile(h); 
WriteFile(h, "bbb", 3, &written, 0); 

Respuesta

7

usted tiene que crear un archivo normal, a continuación, utilizar DeviceIoControl con FSCTL_SET_SPARSE para que sea un archivo disperso.

+0

Oh, gracias. Lo intentaré. ¿No hay una interfaz Win32? – Benjamin

+0

@Benjamin: No conozco otra forma de hacer este trabajo. –

+0

Sí, funciona bien. Muchas gracias. – Benjamin

5
#include <windows.h> 
#include <string> 
#include <iostream> 

HANDLE CreateSparseFile(LPCTSTR lpSparseFileName) 
{ 
    // Use CreateFile as you would normally - Create file with whatever flags 
    //and File Share attributes that works for you 
    DWORD dwTemp; 

    HANDLE hSparseFile = CreateFile(lpSparseFileName, 
     GENERIC_READ | GENERIC_WRITE, 
     FILE_SHARE_READ | FILE_SHARE_WRITE, 
     NULL, 
     CREATE_ALWAYS, 
     FILE_ATTRIBUTE_NORMAL, 
     NULL); 

    if (hSparseFile == INVALID_HANDLE_VALUE) 
     return hSparseFile; 

    DeviceIoControl(hSparseFile, 
     FSCTL_SET_SPARSE, 
     NULL, 
     0, 
     NULL, 
     0, 
     &dwTemp, 
     NULL); 
    return hSparseFile; 
} 

DWORD SetSparseRange(HANDLE hSparseFile, LONGLONG start, LONGLONG size) 
{ 
    // Specify the starting and the ending address (not the size) of the 
    // sparse zero block 
    FILE_ZERO_DATA_INFORMATION fzdi; 
    fzdi.FileOffset.QuadPart = start; 
    fzdi.BeyondFinalZero.QuadPart = start + size; 
    // Mark the range as sparse zero block 
    DWORD dwTemp; 
    SetLastError(0); 
    BOOL bStatus = DeviceIoControl(hSparseFile, 
     FSCTL_SET_ZERO_DATA, 
     &fzdi, 
     sizeof(fzdi), 
     NULL, 
     0, 
     &dwTemp, 
     NULL); 
    if (bStatus) return 0; //Sucess 
    else { 
     DWORD e = GetLastError(); 
     return(e); //return the error value 
    } 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    if (argc < 3) { 
     std::cerr << "USAGE: SparseFile filename size" << std::endl; 
     return 1; 
    } 

    try { 
     ULONGLONG size = std::stoull(argv[2]); 
     HANDLE h = CreateSparseFile(argv[1]); 
     if (h == INVALID_HANDLE_VALUE) { 
      std::cerr << "Unable to create file" << std::endl; 
      return 1; 
     } 
     if (SetSparseRange(h, 0, size) != 0) { 
      std::cerr << "Unable to set sparse range" << std::endl; 
      return 1; 
     } 
     LARGE_INTEGER seek; 
     seek.QuadPart = size; 
     if (!SetFilePointerEx(h, seek, 0, 0)) { 
      std::cerr << "Unable to seek to desired offset" << std::endl; 
      return 1; 
     } 
     SetEndOfFile(h); 
     CloseHandle(h); 
    } catch (const std::exception &ex) { 
     std::cerr << ex.what() << std::endl; 
    } 

    return 0; 
} 
+0

¿Esto agrega cosas nuevas a la respuesta de 2010? –

+3

@ThomasWeller es un ejemplo de trabajo completo que usa la misma idea. – zenden2k

Cuestiones relacionadas