【问题标题】:How to get a file size even if it is already open for exclusive access?即使文件已经打开以进行独占访问,如何获取文件大小?
【发布时间】:2015-11-16 05:02:28
【问题描述】:

我发现获取文件大小的唯一方法是使用GetFileSizeEx() 函数。但是,此函数需要文件的HANDLE,如果该文件已打开以进行独占访问,我将无法为其获取HANDLE,因此我将无法获得其大小。

那么有没有办法获取文件大小,即使它已经打开以供独占访问?

【问题讨论】:

  • 也许您需要澄清一些事情,您想从文件系统上的路径获取文件大小,即使它已打开以进行独占访问。是这样吗?
  • @iharob 是的,就是这样。

标签: c winapi


【解决方案1】:

编辑,(见 cmets)
使用GetFileInformationByHandle

ULONGLONG filesize = 0; 
HANDLE h = CreateFile(filename, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
if (h != INVALID_HANDLE_VALUE)
{ 
    BY_HANDLE_FILE_INFORMATION info;
    memset(&info, 0, sizeof(BY_HANDLE_FILE_INFORMATION));
    if (GetFileInformationByHandle(h, &info)) 
    { 
        ULARGE_INTEGER ul = { 0 };
        ul.LowPart = info.nFileSizeLow; 
        ul.HighPart = info.nFileSizeHigh;
        filesize = ul.QuadPart; 
    } 
    CloseHandle(h); 
} 

另一种方法,见GetFileAttributesEx


还有FindFirstFile,但这可能不准确

来自 FindFirstFile 的 MSDN 文档

注意在极少数情况下或在负载较重的系统上,文件属性 NTFS 文件系统的信息可能不是当前的 函数被调用。确保获取当前的 NTFS 文件 系统文件属性,调用GetFileInformationByHandle函数。

使用FindFirstFile

WIN32_FIND_DATA ffd;
HANDLE hfind = FindFirstFile(filename, &ffd);
if (hfind != INVALID_HANDLE_VALUE)
{
    DWORD filesize = ffd.nFileSizeLow;

    //for files larger than 4GB:
    ULARGE_INTEGER ul;
    ul.LowPart = ffd.nFileSizeLow;
    ul.HighPart = ffd.nFileSizeHigh;
    ULONGLONG llfilesize = ul.QuadPart;

    FindClose(hfind);
}

【讨论】:

  • 或者,如果文件句柄稍后将用于其他操作,也可以使用对GetFileInformationByHandle 的调用。可以通过将0x0 作为dwDesiredAccess 参数传递给CreateFile 来打开文件句柄。
  • @IInspectable GetFileInformationByHandle 看起来更适合这项任务,我编辑了答案。
  • 我认为后一种解决方案不会像发布的那样工作 - 您需要将共享模式设置为 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE 而不是 0。打开文件时,请求的访问权限必须与任何现有句柄的共享模式,并且共享模式必须与授予现有句柄的访问权限兼容。
  • FILE_SHARE_READ/FILE_SHARE_WRITE 会影响对 CreateFile 的后续调用 - 一个常见的误解。您指定的共享标志必须与任何现有句柄兼容,否则您对 CreateFile 的调用将失败。
  • @BarmakShemirani,您没有更改访问权限。如果一个文件有多个句柄,则文件的有效共享模式是每个句柄的共享模式的逻辑与。例如,如果您仅指定了 FILE_SHARE_WRITE,而原始句柄仅指定了 FILE_SHARE_READ,则新的有效共享模式将为 0。如果您指定全 1,即FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,则有效共享模式不会改变。
猜你喜欢
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 2010-10-15
  • 2023-03-14
相关资源
最近更新 更多