代码之家  ›  专栏  ›  技术社区  ›  MNagy

Createfile2、ReadFile和WriteFile;为什么ReadFile没有读取我在WriteFile中写的内容?

  •  0
  • MNagy  · 技术社区  · 9 年前

    为了进行测试,并确保我已经把所有的东西都放下来,以便以后可以开始扩展,我尝试创建一个文件句柄,将给定的字节缓冲区写入该文件句柄,然后将该文件的一部分读入新的测试缓冲区。

    我有代码:

    const size_t vSize = 0x10000;
    
    std::vector<byte> buffer(vSize, 0);
    
    for (int i = 0; i != vSize; ++i)
    {
        buffer[i] = i & 0xff;
    }
    
    std::wstring path = ApplicationData::Current->LocalFolder->Path->Data();
    
    std::wstring testFileName = path + std::wstring(L"\\TestVariablySized");
    
    _CREATEFILE2_EXTENDED_PARAMETERS extend = { 0 };
    extend.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
    extend.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
    extend.dwFileFlags = FILE_FLAG_NO_BUFFERING;
    extend.dwSecurityQosFlags = SECURITY_ANONYMOUS;
    extend.lpSecurityAttributes = nullptr;
    extend.hTemplateFile = nullptr;
    
    HANDLE hMappedFile = CreateFile2(
        testFileName.c_str(),
        GENERIC_READ | GENERIC_WRITE,
        0,
        OPEN_ALWAYS,
        &extend);
    
    _OVERLAPPED positionalData;
    positionalData.Offset = 0;
    positionalData.OffsetHigh = 0;
    positionalData.hEvent = 0;
    
    WriteFile(
        hMappedFile,
        &buffer[0],
        vSize,
        NULL,
        positionalData);
    
    std::vector<byte> testBuffer(128);
    
    ReadFile(
        hMappedFile,
        (LPVOID)&testBuffer[0],
        128,
        NULL,
        &positionalData);
    

    不幸的是,当我在之后设置断点并检查testBuffer中的实际内容时,我发现它都是零。我在没有位置数据的情况下也尝试了上述所有方法(即在调用WriteFile/ReadFile时将其替换为NULL),但这不会改变结果。类似地,我尝试过用NULL代替CreateFile2的扩展参数,结果相同。

    我最终希望能够在给定文件中选择任意位置读取字节,所以如果我对位置数据做了一些奇怪的事情,请告诉我。

    到目前为止,我不知道问题是在CreateFile2、ReadFile、WriteFile还是它们的组合中。非常感谢您的帮助!

    编辑:结果发现ReadFile()返回False,最后一个错误代码是0x57(87)——error_INVALID_PARAMETER。目前我在谷歌上搜索这个问题,但如果我不能得到答案,我仍然对阅读建议感兴趣。我不清楚我在这里做错了什么,但我的第一个猜测是我在位置数据上犯了一个错误。

    最终编辑:删除FILE_FLAG_NO_BUFFERING在最后完成了任务。非常感谢。

    1 回复  |  直到 9 年前
        1
  •  1
  •   Remy Lebeau    9 年前

    当你通过 OVERLAPPED WriteFile() / ReadFile() 当使用 同步的 文件句柄,函数将在 重叠 重叠 之后 写入/读取的字节。你也路过了 重叠 双方 WriteFile() ReadFile() ,但您不是在倒带 重叠 在传递给之前的偏移量 ReadFile() 所以 ReadFile()

    ULARGE_INTEGER ulOffset;
    ...
    
    ulOffset.QuadPart = 0; // or whatever offset you need
    positionalData.Offset = ulOffset.LowPart;
    positionalData.OffsetHigh = ulOffset.HighPart;
    WriteFile(hMappedFile, ..., &positionalData);
    
    ...
    
    ulOffset.QuadPart = 0; // or whatever offset you need
    positionalData.Offset = ulOffset.LowPart;
    positionalData.OffsetHigh = ulOffset.HighPart;
    ReadFile(hMappedFile, ..., &positionalData);
    

    当您传递NULL而不是 重叠 结构中,函数将从文件句柄本身中存储的当前文件偏移量开始写入/读取字节,然后更新句柄以存储新的文件偏移量 之后 写入/读取的字节。因此,如果使用相同的文件句柄进行写入和读取,则必须使用 SetFilePointer() SetFilePointerEx() :

    LARGE_INTEGER liOffset;
    ...
    
    liOffset.QuadPart = 0; // or whatever offset you need
    SetFilePointerEx(hMappedFile, liOffset, NULL, FILE_BEGIN);
    WriteFile(hMappedFile, ..., NULL);
    
    ...
    
    liOffset.QuadPart = 0; // or whatever offset you need
    SetFilePointerEx(hMappedFile, liOffset, NULL, FILE_BEGIN);
    ReadFile(hMappedFile, ..., NULL);
    

    也就是说,您正在使用 FILE_FLAG_NO_BUFFERING 非常严格的限制 在文件I/O操作期间,文件偏移量、缓冲区地址和缓冲区大小可以是什么。有关使用该标志时必须遵循的特定规则的详细信息,请阅读MSDN文档:

    File Buffering