windows - 访问非常长的文件名的 ntfs 流失败

标签 windows winapi stream ntfs

从名称很长的文件(超过 MAX_PATH 个字符长,根据 this 使用“\\?\”前缀创建)访问备用 ntfs 流时遇到一点问题.我第一次认为这是我的代码错误,但后来我尝试了一个 cmd 命令:

more < "\\?\c:\!!!Long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long filename!!!.png:streamname"

它失败并显示找不到文件的错误。该文件存在并且可以读取其内容,但我无法访问读取和写入所需的流。 我不希望我的软件无法处理长文件名,因此我正在寻找针对这种情况的任何解决方法。

我知道我可以使用 BackupRead function , 但我不确定这个解决方案是否可以在大文件上快速运行并且它在 2000 中不起作用。

GetShortPathName 给了我同样的失败结果,还有其他可以缩短文件名的 API 吗?我真的不想使用短文件名的临时连接来执行此操作。 有什么想法吗?

最佳答案

作为 CreateFile 上非常有用的页面指的是指定文件名的 lpFileName 参数:

In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" to the path.

由于您正在考虑 BackupRead,显然您希望以编程方式访问此流。如果是这样,请以编程方式进行测试。从命令提示符尝试所有这些操作是胡说八道,除了从命令提示符执行此类操作的能力之外不会建立任何东西。

考虑到这一点,让我们试试这个简单的程序——删除样板代码:

#include "stdafx.h"

int APIENTRY _tWinMain(HINSTANCE,
                       HINSTANCE,
                       LPTSTR,
                       int)
{
    /* This is the name of the file that we will try to create. Please note that
     * I have hardcoded the path to my user directory (C:\Users\nikb), and since 
     * it's unlikely that path exists on your computer, you should probably put
     * something there that makes sense.
     */
    LPCWSTR lpszFileName = L"\\\\?\\c:\\users\\nikb\\!!!Long long long long "
                           L"long long long long long long long long long long "
                           L"long long long long long long long long long long "
                           L"long long long long long long filename!!!.png:streamname";

    HANDLE hFile = CreateFileW(lpszFileName, GENERIC_WRITE, 0, NULL, 
        CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);

    if(hFile != INVALID_HANDLE_VALUE)
    {
        BYTE bBuffer[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'N', 'i', 'k', '!' };
        DWORD dwSize = 10;

        if(WriteFile(hFile, bBuffer, dwSize, &dwSize, NULL))
            ::MessageBoxW(GetDesktopWindow(), L"Success", L"WriteFile", MB_OK);
        else
            ::MessageBoxW(GetDesktopWindow(), L"Failure", L"WriteFile", MB_OK);

        CloseHandle(hFile);
    }

    return 0;

这应该可以正常工作。所以现在,让我们通过添加更多的单词来使文件名更长。同样,请务必将路径正确更新为在您的计算机上有效的内容。

LPCWSTR lpszFileName = L"\\\\?\\c:\\users\\nikb\\!!!Long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long long long long long long long long long long "
                       L"long long filename!!!.png:streamname";

现在是。它会失败。奇怪...如果我们检查 GetLastError() 的输出,我们将得到 ERROR_INVALID_NAME 那是什么原因呢?这应该可行,因为它显然不会超过 32,767 个字符,而且我们正在使用奇特的 \\?\ 语法来指定reeeeeally 长路径。对吧?

嗯……有点像。 CreateFile 上的 MSDN 页面链接到标题为 Naming Files, Paths and Namespaces 的非常有用的页面.事实上,即使您在问题中链接到该页面。这很有趣,因为它会在您提出问题之前回答您的问题:

The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "\?\" prefix. For example, "\?\D:\very long path".

因此,尽管路径本身可能有 32,767 个字符长,但路径的任何单个组件(即“部分”)都不能超过文件系统允许的最大值。事实上,如果您尝试找出 NTFS 报告的最大组件长度,它将是 255。

所以文件名是单个组件,单个组件不能超过255个字符。您指定的文件名是:

!!!Long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long filename!!!.png:streamname

快速测试显示这是 264 个字符长。毫不奇怪,264 大于 255。

关于windows - 访问非常长的文件名的 ntfs 流失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16927798/

相关文章:

windows - 写入 Windows 注册表?

java - 双击打不开jar文件

c++ - 使用补码加密文件

c - printf 不创建输出或创建错误输出

linux - 使用 Jenkins 部署到 Linux 服务器,然后从 Windows 服务器运行 selenium 测试

windows - cURL Windows 中的双引号/单引号

c++ - 从程序集调用 Win32 的 Sleep 函数会产生访问冲突错误

c++ - MFC中OnInitDialog函数之后有没有调用什么函数?

c++ - 处理 WM_KEYDOWN

node.js - 在转换流中使用 Node.js readline