Delphi - Tömörített lemezkötetek állományainak mérete

forráskód letöltése
Amikor a Microsoft 1993 augusztusában bemutatta az MS-DOS 6-os verzióját, többek között annak egyik különlegessége volt a beépített „lemezduplázó” DoubleSpace program is, melyet a későbbi verziókban a DriveSpace váltott fel. Ennek a programnak a segítségével a felhasználó megduplázhatta tárkapacitását, méghozzá úgy, hogy az operációs rendszer a fájlokat eleve tömörítve helyezte el az adott tárhelyen. Ez a funkció mind a mai napig megtalálható a Microsoft operációs rendszereiben. A következő példában azt fogjuk megvizsgálni, hogyan tudjuk lekérdezni ezeknek a tömörített fájloknak a méretét.
Példánkban a GetCompressedFileSize nevű Windows függvényt fogjuk használni, mely a tömörített állomány méretét adja vissza bájtokban, amennyiben a kijelölt lemezkötet támogatja a fájl-tömörítést.
Felépítése a következő:
GetCompressedFileSize
DWORD GetCompressedFileSize(
LPCTSTR lpFileName,
LPDWORD lpFileSizeHigh
);
Paraméterek
LPCTSTR lpFileName
String típusú mutató, mely a kijelölt fájl nevére utal.
LPDWORD lpFileSizeHigh
Duplaszó típusú mutató, melyet a függvény a duplaszó felső szavára állít. A tömörített fájl mérete a duplaszó alsó szavában kerül eltárolásra. A 4 Gigabájtnál kisebb méretű fájlok esetében a felső szóra nincs szükség. Ilyenkor a paramétert nullára lehet állítani.
)
Visszatérési érték
Sikeres lefutás esetén a függvény az lpFileSizeHigh mutató alsó szavában tárolt értékkel tér vissza, mely a tömörített állomány méretét tartalmazza bájtokban.
Megjegyzés
Ha a függvény futása sikertelen és az lpFileSizeHigh  értéke nulla, a visszatérési érték 0xFFFFFFFF lesz. A hiba okáról a GetLastError függvény nyújt bővebb tájékoztatást.
Amennyiben a függvény futása sikertelen és az lpFileSizeHigh  értéke nem nulla, a visszatérési érték 0xFFFFFFFF lesz és a GetLastError függvény értéke nem a NO_ERROR lesz.
Ahhoz, hogy meghatározhassuk a tömörített fájl méretét, először meg kell vizsgálnunk, hogy a kijelölt lemezkötet támogatja-e a tömörítést. Ehhez segítségül hívjuk a GetVolumeInformation függvényt, mely sok hasznos információt szolgáltat az adott lemezről.
GetVolumeInformation
BOOL GetVolumeInformation(
LPCTSTR lpRootPathName,
LPTSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPTSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize
);
Paraméterek
LPCTSTR lpRootPathName
A lemez gyökérkönyvtárára mutat.
LPTSTR lpVolumeNameBuffer
A lemezkötet címkéjének a nevére mutat.
DWORD nVolumeNameSize
A lemezcímke hossza.
LPDWORD lpVolumeSerialNumber
A lemez sorozatszáma.
LPDWORD lpMaximumComponentLength
A rendszer által támogatott fájlnév maximális hossza.
LPDWORD lpFileSystemFlags
Duplaszóra mutat, mely az adott rendszerre jellemző flag-eket tartalmazza.
Ez a paraméter a következők kombinációja lehet:
FS_CASE_IS_PRESERVED Amennyiben ez a flag be van állítva, a fájlrendszer érzéketlen a kis- és nagybetűkre a fájlnevekben.
FS_CASE_SENSITIVE Amennyiben a flag be van állítva, a rendszer támogatja a kis- és nagybetűk használatát a fájlnevekben.
FS_UNICODE_STORED_ON_DISK Amennyiben a flag értéket kap, a rendszer támogatja a Unicode-ot a fájlnevekben.
FS_PERSISTENT_ACLS Ennél a flag-nél a fájlrendszer letilthatja, illetve engedélyezheti az ACL-t (Access Control List), azaz az objektum-hozzáférési jogosultságot. Például az NTFS letilthatja, illetve engedélyezheti, míg a FAT nem.
FS_FILE_COMPRESSION A fájlrendszer támogatja a fájl-alapú tömörítést.
FS_VOL_IS_COMPRESSED Amennyiben ez a flag be van állítva, a kijelölt lemezkötet tömörítve van, például egy DoubleSpace kötet.
LPTSTR lpFileSystemNameBuffer
A fájlrendszer nevére utal (például FAT vagy NTFS).
DWORD nFileSystemNameSize
A fájlrendszer nevének a hosszát adja vissza karakterben.
)
Visszatérési érték
Amennyiben az összes kért információ begyűjthető, egy nem nulla értéket ad vissza eredményül. Ellenkező esetben nullát kapunk.
Esetünkben csupán az lpFileSystemFlags-ben levő FS_FILE_COMPRESSION és az FS_VOL_IS_COMPRESSED flag-eket kell megvizsgálni. Amennyiben a lemezkötet támogatja a fájl-alapú tömörítést, vagy tömörített kötetről van szó, a GetCompressedFileSize függvény segítségével lekérdezzük a kijelölt fájl tömörített méretét.
Ezután, hogy legyen összehasonlítási alapunk a tömörítést illetően, a GetFileSize függvénnyel lekérdezzük a fájl eredeti, tömörítetlen méretét is. Ez a függvény a következőképpen épül fel:
GetFileSize
DWORD GetFileSize(
HANDLE hFile,
LPDWORD lpFileSizeHigh
);
Paraméterek
HANDLE hFile
A fájl nevére mutató pointer.
LPDWORD lpFileSizeHigh
Egy duplaszó típusú változó felső szavára mutató pointer. Akár a GetCompressedFileSize esetében, a kijelölt fájl mérete ennek a változónak az alsó szavában keletkezik.
)
Visszatérési érték
Sikeres lefutás esetén a függvény az lpFileSizeHigh mutató alsó szavában tárolt értékkel tér vissza, mely a kijelölt állomány méretét tartalmazza bájtokban.
Megjegyzés
Ha a függvény futása sikertelen és az lpFileSizeHigh  értéke nulla, a visszatérési érték 0xFFFFFFFF lesz. A hiba okáról a GetLastError függvény nyújt bővebb tájékoztatást.
Amennyiben a függvény futása sikertelen és az lpFileSizeHigh  értéke nem nulla, a visszatérési érték 0xFFFFFFFF lesz és a GetLastError függvény értéke nem a NO_ERROR lesz.
Lássuk most, hogy a példaprogramban hogyan is valósítottuk meg mindezt. A függvények hívását egy OnClick eseményhez rendeltük hozzá.
procedure TForm1.Button1Click(Sender: TObject);
var
  lpRootPathName,
  lpVolumeNameBuffer,
  lpFileSystemNameBuffer: array[0..63] of char;
  lpMaximumComponentLength, lpVolumeNumber,
  lpFileSystemFlags: DWORD;
  iHigh: Integer;
  iLow : Integer;
  hFile  : THandle;
begin
  if Edit1.Text<>'' then
  begin
Először beállítjuk a gyökérkönyvtár nevét, majd meghívjuk a GetVolumeInformation függvényt. Amennyiben másik meghajtót szeretnénk vizsgálni, írjuk át a betűjelet.
    lpRootPathName:='c:\';
    GetVolumeInformation(
      lpRootPathName,
      lpVolumeNameBuffer,
      64,
      @lpVolumeNumber,
      lpMaximumComponentLength,
      lpFileSystemFlags,
      lpFileSystemNameBuffer,
      64
    );
A kapott paraméterből megvizsgáljuk, hogy a lemez tömörített-e vagy sem.
    if lpFileSystemFlags and FS_VOL_IS_COMPRESSED <> 0 then
      Label1.Caption := 'A kijelölt lemezkötet tömörített!'
    else
      Label1.Caption := 'A kijelölt lemezkötet nem tömörített!';
Ezután azt nézzük meg, hogy a lemezkötet támogatja-e a fájl-tömörítést.
    if lpFileSystemFlags and FS_FILE_COMPRESSION <> 0 then
      Label2.Caption := 'A kijelölt lemezkötet támogatja a fájl-alapú tömörítést!'
    else
      Label2.Caption := 'A kijelölt lemezkötet támogatja a fájl-alapú tömörítést!';
Lekérdezzük az eredeti fájlméretet a GetFileSize függvénnyel.
    hFile := CreateFile(PChar(Edit1.Text), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);
    iLow := GetFileSize(hFile,@iHigh);
    If ((iLow = -1) And (GetLastError <> No_Error)) Then
      RaiseLastWin32Error;
    Label2.Caption := 'A kijelölt fájl eredeti mérete: '+ IntToStr(iLow)+ ' byte';
    CloseHandle (hFile);
Ezután következik a tömörített fájl méretének vizsgálata.
    iLow := GetCompressedFileSize(PChar(Edit1.Text),@iHigh);
    If ((iLow = -1) And (GetLastError <> No_Error)) Then
      RaiseLastWin32Error;
    Label3.Caption := 'A kijelölt fájl tömörített mérete: '+ IntToStr(iLow)+ ' byte';
  end
  else
  ShowMessage('Válasszon egy fájlt!');
end;
A két utóbbi függvény esetében a duplaszó alsó és felső részét külön változóban (iLow, iHigh) tároltuk. Kiíratásra az iLow-ban tárolt alsó rész kerül. Amennyiben a függvények futtatása nem sikerül, a GetLastError meghívásával íratjuk ki a hiba okát.
Ahhoz, hogy ki tudjuk próbálni a programunkat, először létre kell hoznunk egy tömörített lemezpartíciót. Ehhez nem kell mást tennünk, mint a Sajátgépben jobb gombbal kattintsunk a tömörítendő meghajtó betűjelére, majd a megjelenő Tulajdonság ablakban jelöljük be a Meghajtó tömörítése funkciót.
Amennyiben az eredeti és a tömörített fájlméret megegyezik, akkor a lemezkötet nem támogatja a tömörítést.