获得可用空间c++

来源:互联网 发布:理财入门指导软件 编辑:程序博客网 时间:2024/05/16 12:14
INFO:   Understanding   and   Using   GetDiskFreeSpace   and   GetDiskFreeSpaceEx     ID:   Q231497                     --------------------------------------------------------------------------------     The   information   in   this   article   applies   to:         Microsoft   Win32   Application   Programming   Interface   (API),   on   platform(s):     Microsoft   Windows   versions   95,   98       Microsoft   Windows   NT   versions   3.51,   4.0,   4.0   SP4       Microsoft   Windows   2000         --------------------------------------------------------------------------------             SUMMARY     Win32   programs   use   GetDiskFreeSpaceEx   or   GetDiskFreeSpace   to   determine   the   total   size   of   a   volume   and   how   much   free   space   can   be   allocated   by   the   caller.   Because   some   Windows   platforms   have   features   such   as   enforceable   disk   quotas   while   others   don't,   applications   that   use   these   APIs   must   interpret   the   returned   sizes   correctly.   In   addition,   because   most   Windows   platforms   support   volumes   larger   than   4   gigabytes   (GB),   Win32   programs   must   use   64-bit   integer   math   with   these   APIs.   This   article   explains   how   to   use   GetDiskFreeSpaceEx   and   GetDiskFreeSpace   in   a   way   that   works   on   all   Win32   platforms.                   MORE   INFORMATION     Generally,   Win32   programs   should   use   GetDiskFreeSpaceEx   to   determine   the   total   size   of   a   volume   and   the   amount   of   free   space   that   the   caller   can   use.   The   one   case   where   this   isn't   possible   is   when   the   program   runs   on   retail   Windows   95   (build   950.6)   because   GetDiskFreeSpaceEx   was   introduced   to   Windows   95   in   OEM   Service   Release   2   (OSR2).           If   your   program   can   run   on   retail   Windows   95,   you   should   not   directly   call   GetDiskFreeSpaceEx   because   this   function   is   not   implemented   in   retail   Windows   95,   and   calling   it   directly   will   prevent   your   program   from   loading.   Instead,   you   should   dynamically   link   to   it   via   GetProcAddress.   If   the   returned   pointer   is   non-NULL,   then   your   application   can   safely   call   GetDiskFreeSpaceEx   through   the   pointer;   if   the   returned   pointer   is   NULL,   then   you   should   revert   to   GetDiskFreeSpace.   The   example   code   later   in   this   article   demonstrates   how   to   do   this.           Drive   and   UNC   Name   Parameter     GetDiskFreeSpace   on   Windows   95   and   Windows   98   requires   a   trailing   backslash   for   both   drive   letters   and   UNC   names.   Although   Windows   NT   does   not   require   the   trailing   backslash,   you   should   add   one   if   your   program   can   run   on   both   platforms.       Windows   95/98-specific   Behavior     The   information   in   this   section   applies   to   all   versions   of   Windows   95   and   Windows   98.   GetDiskFreeSpace   returns   a   maximum   total   size   and   maximum   free   size   of   2GB.   For   example,   if   you   have   a   6GB   volume   and   5GB   are   free,   GetDiskFreeSpace   reports   that   the   drive's   total   size   is   2GB   and   2GB   are   free.   This   limitation   originated   because   the   first   version   of   Windows   95   only   supportsed   volumes   of   up   to   2GB   in   size.   Windows   95   OSR2   and   later   versions,   including   Windows   98,   support   volumes   larger   than   2GB.   GetDiskFreeSpaceEx   does   not   have   a   2GB   limitation,   because   it   is   preferred   over   GetDiskFreeSpace.   GetDiskFreeSpace   returns   a   maximum   of   65536   for   the   numbers   of   total   clusters   and   free   clusters   to   maintain   backward   compatibility   with   the   first   version   of   Windows   95.   The   first   version   of   Windows   95   supports   only   the   FAT16   file   system,   which   has   a   maximum   of   65536   clusters.   If   a   FAT32   volume   has   more   than   65536   clusters,   the   number   of   clusters   are   reported   as   65536   and   the   number   of   sectors   per   cluster   are   adjusted   so   that   the   size   of   volumes   smaller   than   2GB   may   be   calculated   correctly.   What   this   means   is   that   you   should   not   use   GetDiskFreeSpace   to   return   the   true   geometry   information   for   FAT32   volumes.       Windows   NT/2000-specific   Behavior     On   Windows   NT   and   Windows   2000,   GetDiskFreeSpace   is   not   limited   to   2GB;   it   reports   the   full   size   of   the   drive   and   the   full   amount   of   free   space.   Windows   2000   supports   disk   quotas.   When   quota   hard   limits   are   being   enforced,   GetDiskFreeSpace   returns   the   quota   size   for   the   user   as   the   total   disk   space   and   returns   the   user's   remaining   unused   quota   for   the   free   space.   This   is   done   so   that   programs   can   determine   how   much   disk   space   they   can   actually   use.   GetDiskFreeSpaceEx   returns   values   subject   to   enforced   quota   limits   also,   but   specifically   returns   the   number   of   bytes   available   to   the   user   who   is   running   the   program.       Using   Returned   Sizes     GetDiskFreeSpaceEx   returns   three   64-bit   values;   Win32   programs   should   be   careful   to   retain   all   64   bits   in   order   to   properly   handle   drive   sizes   larger   than   4GB.   To   determine   how   much   disk   space   you   can   use,   use   the   lpFreeBytesAvailableToCaller   member   because   it   takes   into   account   disk   quotas,   to   which   the   program's   user   may   be   limited.           GetDiskFreeSpace   returns   four   32-bit   values   that   Win32   programs   must   multiply   together   to   get   the   total   size   of   the   volume   and   the   free   space   on   the   volume.   While   it   seems   understandable   to   use   32-bit   integer   multiply   operations   to   get   the   sizes,   doing   so   will   lead   to   incorrect   results   when   the   drive   is   larger   than   2GB.   The   proper   way   to   multiply   the   returned   values   of   GetDiskFreeSpace   is   to   use   64-bit   math.       Sample   Code     The   following   sample   code   demonstrates   how   to   use   GetDiskFreeSpaceEx   and   GetDiskFreeSpace   on   all   Windows   platforms.   Important   elements   of   the   code   include:           How   to   determine   at   run   time   whether   GetDiskFreeSpaceEx   is   present   and   if   not,   how   to   revert   to   GetDiskFreeSpace.             How   to   use   64-bit   math   to   report   the   returned   sizes   for   all   volumes,   even   if   they   are   larger   than   2   GB.                           /*                 Determines   the   amount   of   free   space   available   for   the   caller.                 Runs   on   Windows   95   retail   and   later,   and   on   Windows   4.0   and   later.                     Uses   GetDiskFreeSpaceEx   if   available,   otherwise   reverts   to                 GetDiskFreeSpace.                     To   determine   the   amount   of   available   space   correctly:                       *   Use   64-bit   math   with   the   return   values   of   both   GetDiskFreeSpace                       and   GetDiskFreeSpaceEx   so   that   you   can   determine   the   sizes   of                       volumes   that   are   larger   than   2GB.                     Programs   that   need   to   determine   how   much   free   space   the   current   user                 can   have   (such   as   whether   there   is   enough   space   to   complete   an                 installation)   have   an   additional   requirement:                       *   Use   the   lpFreeBytesAvailableToCaller   value   from                       GetDiskFreeSpaceEx   rather   than   lpTotalNumberOfFreeBytes.                           This   is   because   Windows   2000   has   disk   quota   management   that                       administrators   may   use   to   limit   the   amount   of   disk   space   that                       users   may   use.           */                     #include   <windows.h>           #include   <stdio.h>                   typedef   BOOL   (WINAPI   *P_GDFSE)(LPCTSTR,   PULARGE_INTEGER,                                                                           PULARGE_INTEGER,   PULARGE_INTEGER);               void   main   (int   argc,   char   **argv)           {                 BOOL     fResult;                     char     *pszDrive     =   NULL,                               szDrive[4];                     DWORD   dwSectPerClust,                             dwBytesPerSect,                             dwFreeClusters,                             dwTotalClusters;                     P_GDFSE   pGetDiskFreeSpaceEx   =   NULL;                     unsigned   __int64   i64FreeBytesToCaller,                                                   i64TotalBytes,                                                   i64FreeBytes;                     /*                       Command   line   parsing.                           If   the   drive   is   a   drive   letter   and   not   a   UNC   path,   append   a                         trailing   backslash   to   the   drive   letter   and   colon.     This   is                         required   on   Windows   95   and   98.                 */                   if   (argc   !=   2)                 {                       printf   ("usage:     %s   <drive|UNC   path>/n",   argv[0]);                       printf   ("/texample:     %s   C:///n",   argv[0]);                       return;                 }                     pszDrive   =   argv[1];                     if   (pszDrive[1]   ==   ':')                 {                       szDrive[0]   =   pszDrive[0];                       szDrive[1]   =   ':';                       szDrive[2]   =   '//';                       szDrive[3]   =   '/0';                           pszDrive   =   szDrive;                 }                     /*                       Use   GetDiskFreeSpaceEx   if   available;   otherwise,   use                       GetDiskFreeSpace.                           Note:   Since   GetDiskFreeSpaceEx   is   not   in   Windows   95   Retail,   we                       dynamically   link   to   it   and   only   call   it   if   it   is   present.     We                         don't   need   to   call   LoadLibrary   on   KERNEL32.DLL   because   it   is                         already   loaded   into   every   Win32   process's   address   space.                 */                   pGetDiskFreeSpaceEx   =   (P_GDFSE)GetProcAddress   (                                                                   GetModuleHandle   ("kernel32.dll"),                                                                                                     "GetDiskFreeSpaceExA");                 if   (pGetDiskFreeSpaceEx)                 {                       fResult   =   pGetDiskFreeSpaceEx   (pszDrive,                                                                       (PULARGE_INTEGER)&i64FreeBytesToCaller,                                                                       (PULARGE_INTEGER)&i64TotalBytes,                                                                       (PULARGE_INTEGER)&i64FreeBytes);                       if   (fResult)                       {                             printf   ("/n/nGetDiskFreeSpaceEx   reports/n/n");                             printf   ("Available   space   to   caller   =   %I64u   MB/n",                                             i64FreeBytesToCaller   /   (1024*1024));                             printf   ("Total   space                               =   %I64u   MB/n",                                             i64TotalBytes   /   (1024*1024));                             printf   ("Free   space   on   drive               =   %I64u   MB/n",                                             i64FreeBytes   /   (1024*1024));                       }                 }                 else                 {                       fResult   =   GetDiskFreeSpace   (pszDrive,                                                                                 &dwSectPerClust,                                                                               &dwBytesPerSect,                                                                                 &dwFreeClusters,                                                                               &dwTotalClusters);                       if   (fResult)                       {                             /*   force   64-bit   math   */                               i64TotalBytes   =   (__int64)dwTotalClusters   *   dwSectPerClust   *                                                                 dwBytesPerSect;                             i64FreeBytes   =   (__int64)dwFreeClusters   *   dwSectPerClust   *                                                                 dwBytesPerSect;                                 printf   ("GetDiskFreeSpace   reports/n/n");                             printf   ("Free   space     =   %I64u   MB/n",                                               i64FreeBytes   /   (1024*1024));                             printf   ("Total   space   =   %I64u   MB/n",                                               i64TotalBytes   /   (1024*1024));                       }                 }                     if   (!fResult)                       printf   ("error:   %lu:     could   not   get   free   space   for   /"%s/"/n",                                       GetLastError(),   argv[1]);           }       Notes   on   64-bit   Integer   Math     Microsoft   Visual   C++   versions   4.0   and   later   support   a   64-bit   integer   type   called   __int64.   The   compiler   generates   code   to   do   the   64-bit   math   because   the   Intel   x86   family   of   microprocessors   supports   8-bit,   16-bit,   and   32-bit   integer   math,   but   not   64-bit   integer   math.           To   perform   a   64-bit   integer   multiply,   one   of   the   arguments   must   be   64-bit;   the   other   can   be   either   32-bit   or   64-bit.   When   functions   such   as   GetDiskFreeSpace   return   only   32-bit   integer   values   that   will   be   multiplied   together   but   you   need   to   have   a   64-bit   integer   to   contain   the   product,   cast   one   of   the   values   to   an   __int   64   as   follows:           i64TotalBytes   =   (__int64)dwTotalClusters   *   dwSectPerClust   *                                                   dwBytesPerSect;       The   first   multiply   is   of   a   64-bit   integer   with   a   32-bit   integer;   the   result   is   a   64-bit   integer,   which   is   then   multiplied   by   another   32-bit   integer,   resulting   in   a   64-bit   product.           Many   Win32   API   functions   that   take   a   64-bit   quantity   do   so   as   two   separate   32-bit   quantities.   Others,   such   as   QueryPerformanceCounter,   take   a   single   64-bit   quantity.   The   LARGE_INTEGER   union   type   defined   in   the   Platform   SDK   WINNT.H   header   file   manages   these   differing   ways   to   handle   64-bit   integers.   There's   a   corresponding   ULARGE_INTEGER   for   unsigned   large   integers.           The   LARGE_INTEGER   union   consists   of   a   64-bit   __int64   member   (QuadPart)   and   two   32-bit   values   (HighPart   and   LowPart).   Each   of   the   two   32-bit   values   is   one-half   of   the   64-bit   integer.   The   HighPart   member   is   a   signed   long   integer,   while   the   LowPart   is   an   unsigned   long   integer.   Since   the   LARGE_INTEGER.QuadPart   member   is   an   __int64,   you   can   easily   intermix   LARGE_INTEGER   variables   with   __int64   variables.   To   perform   integer   math   with   LARGE_INTEGER   variables,   always   use   the   QuadPart   member   to   treat   the   LARGE_INTEGER   as   the   single   64-bit   value   it   represents.   Use   the   32-bit   HighPart   and   LowPart   members   when   you   must   pass   a   LARGE_INTEGER   to   a   function   in   two   32-bit   parts.           An   equivalent   to   the   above   example   using   LARGE_INTEGERs   instead   of   __int64   variables   is:           liTotalBytes.QuadPart   =   (__int64)dwTotalClusters   *   dwSectPerClust                                                         *   dwBytesPerSect;           Additional   query   words:   available   drive   volume   unused   setup   empty
原创粉丝点击