Windows - Az NTFS fájlrendszer programozói megközelítésben - A ritka fájlok

4. rész

Az NTFS fájlrendszer tartalmaz egy beépített optimalizáló algoritmust, mely a kijelölt és erre alkalmas fájlokat lényegesen gazdaságosabb helykihasználással tárolja. Akár az is előfordulhat, hogy több gigabájtos állományokat elhelyezzünk egy 850 megabájtos merevlemezen. Az alábbiakban körüljárjuk a módszer lényegét, használatát parancssorból és programokból egyaránt.
Ritka fájlok (Sparse Files)
Egyes fájlok - például törölt rekordokat tartalmazó adatbázisok - tartalmazhatnak egymás után nagy mennyiségű nulla bájtokat. Az ilyen állományokat nevezik ritka fájloknak. Tárolásuk a nagy helyigény és aránytalanul kevés információ miatt gazdaságtalan. Tömörítő programokkal ugyan jelentősen csökkenthető a méretük, de közvetlenül nem, csak kicsomagolás után használhatók, ami sokszor nem megfelelő. Egy fokkal jobb megoldás a teljes kötet valós idejű tömörítése, de számolnunk kell néhány hátránnyal: tömörítésre kerülnek olyan fájlok is, melyek nem "ritkák" és lassulnak a merevlemez írási, olvasási műveletek az extra számítás igénynek köszönhetően. Az NTFS fájlrendszer egy beépített szolgáltatása révén tömörítve tárolja a ritka fájlokat. Nem íródnak ki a merevlemezre a nulla értékek, csak egy jelzés, hogy mennyi van belőlük, így jelentős tárterület takarítható meg. Keressünk bizonyítékot a működésre!
Hozzunk létre egy új szövegfájlt, nevezzük "sparse.txt"-nek és töltsük fel bármilyen karakterekkel. Az is jó, ha egy másik fájlt használunk, amire már nincs szükségünk és nagyobb méretű. Lényeg, hogy legyen egy több tíz vagy több száz MB-os állományunk. Kattintsunk rá a Windows Intézőben a jobboldali egérgombbal és válasszuk a "Tulajdonságok" ("Properties") menüt. A megjelenő ablak "Általános" ("General") oldalán nézzük meg a fájlméretet és az elfoglalt lemezterület méretét. A két adat megegyezik vagy legalábbis közel azonos. Nyissunk meg egy parancssori ablakot és adjuk ki a következő utasítást, de csak akkor, ha tényleg nincs szükség a fájl tartalmára:
fsutil file setzerodata offset=0 length=109602740 c:\sparse.txt
Az utasítás feladata, hogy az offset eltolástól indítva, length hosszban töltse fel a megadott fájlt null karakterekkel. Offset-nek használjuk a 0 értéket, hogy a feltöltés az első bájttól induljon, a length pedig legyen az állomány teljes hossza bájtban, amit az előbbi tulajdonságlapon tudunk megnézni.
Következő lépés, hogy utasítsuk az NTFS-t: kezelje ritkaként az állományt. Ehhez adjuk ki a következő parancsot:
fsutil sparse setflag c:\sparse.txt
Nézzük meg ismét a tulajdonságlapját és lássunk csodát: a példánkban szereplő 109602740 bájt (104 megabájt) hosszúságú állomány mérete továbbra is megmaradt ennyinek, de az általa felhasznált lemezterület 8192 bájtra (8 kB) csökkent. Így lehetséges, hogy több gigabájtos állományokat elhelyezzünk egy 850 megabájtos merevlemezen.

Programozók számára is fennáll a ritka fájlok kezelésének lehetősége a DeviceIoControl() Windows függvényen keresztül. Szintaxisa az alábbi:
BOOL DeviceIoControl(
  (HANDLE) hDevice,
  FSCTL_SET_SPARSE,
  NULL,  0,  NULL,  0,
  (LPDWORD) lpBytesReturned,
  (LPOVERLAPPED) lpOverlapped
);
"(HANDLE) hDevice" = a fájl azonosítója.
"FSCTL_SET_SPARSE" = megadása jelzi a fájlrendszer számára, hogy ritka fájlról van szó.
"NULL, 0, NULL, 0" = ezek az értékek nem használatosak, így adjuk meg őket, egyébként I/O buffer méretek szabályozását végzik.
"(LPDWORD) lpBytesReturned" = arra a változóra mutat, amelyik a művelet során hátralévő kimeneti adatmennyiséget tartalmazza.
"(LPOVERLAPPED) lpOverlapped" = szintén egy mutató az OVERLAPPED struktúrára mutat, mely az I/O adatforgalomról tartalmaz információkat
Hogy lehet megtudni, hogy egy fájl ritka-e? Az alábbi parancssori utasítással:
fsutil sparse queryflag c:\sparse.txt
Vagy meg kell hívni a "GetFileAttributes" függvényt és ha a visszatérési attribútumok között szerepel a FILE_ATTRIBUTE_SPARSE_FILE, akkor ritka fájlról van szó.
DWORD dwAttrib = GetFileAttributes(FileName);
return (dwAttrib & FILE_ATTRIBUTE_SPARSE_FILE);
Használhatjuk még a "GetFileInformationByHandle" függvényt is, azzal a különbséggel, hogy nem a fájl nevét, hanem az azonosítóját (handle) kell megadni. A függvény szintaxisa:
BOOL GetFileInformationByHandle(
  HANDLE hFile,
  LPBY_HANDLE_FILE_INFORMATION lpFileInformation
);
Szkriptekből a fenti függvények nem hívhatók meg.

Az NTFS fájlrendszer programozói megközelítésben cikksorozat