从第100个字节读取文件

时间:2016-12-03 08:32:27

标签: winapi

如何使用ReadFile函数和C ++

从第100个字节读取文件

我使用了这段代码,但它读取了文件的前100个字节

我想读第二个100字节

hndl = CreateFileW(L"1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(hndl, 100, NULL, FILE_BEGIN);
ReadFile(hndl, pbytReadBuffer, 100, NULL, &ol);

2 个答案:

答案 0 :(得分:4)

ReadFile API提供两种不同的方法来设置同步I / O时的起始偏移量:

  • 使用隐式存储的文件指针(可以通过SetFilePointer API调用进行操作)。
  • 或者通过OVERLAPPED结构传递显式偏移量。

您的代码失败是因为您正在设置隐式存储的文件指针,但随后(可能)传递零初始化OVERLAPPED结构,忽略文件指针(有关详细信息,请参阅Synchronization and File Position)。

以下任一解决方案均可使用。首先,通过使用隐式存储的文件指针。当您想要在连续调用中读取文件块时,这很有用:

hndl = CreateFileW(L"1.txt", GENERIC_READ, 0, nullptr,
                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
// Move the file pointer to offset 100
SetFilePointer(hndl, 100, NULL, FILE_BEGIN);
// Read contents from the current offset
DWORD dwBytesRead{0};
ReadFile(hndl, pbytReadBuffer, 100, &dwBytesRead, nullptr);

或者,您可以传递OVERLAPPED结构来传递偏移量。这忽略了隐式存储的文件指针。它的效率稍高,因为它不需要对文件I / O API进行两次调用。

hndl = CreateFileW(L"1.txt", GENERIC_READ, 0, nullptr,
                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
OVERLAPPED ol{};
// Set the offset from the start of the file
ol.Offset = 100;
ReadFile(hndl, pbytReadBuffer, 100, nullptr, &ol);

请注意,为简洁起见,这些样本中省略了错误处理。在实际代码中,您始终必须检查错误。

答案 1 :(得分:-1)

你需要像这样的代码

HANDLE hFile = CreateFile(L"c:\\windows\\notepad.exe", FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
    OVERLAPPED ov = {};
    ov.Offset = 100;
    UCHAR buf[100];
    ULONG cb;
    if (ReadFile(hFile, buf, sizeof(buf), &cb, &ov))
    {
    }
    else
    {
        GetLastError();
    }
    CloseHandle(hFile);
}

你不需要调用SetFilePointer - 在OVERLAPPED结构中更好地设置偏移量

修改

对于每个读/写操作,我们需要指定起始字节偏移量。我们可以通过在OVERLAPPED中设置OffsetOffsetHigh中的值来执行此操作。

或间接仅当同步模式下打开文件时 - I / O管理器可以使用FILE_OBJECT中的当前文件位置 - 所以我们不能直接设置偏移量 - 它将来自FILE_OBJECT.CurrentByteOffsetFILE_OBJECT.CurrentByteOffset我们可以设置SetFilePointer每次读/写操作都会更新此偏移量 - 前进到已读/写的字节数。当然,只有当文件的所有操作都是顺序的

时,同步模式下使用的文件才是正确的

如果我们在OVERLAPPED中使用直接偏移并使用 - 那么FILE_OBJECT.CurrentByteOffset会被忽略 - 这意味着以前调用SetFilePointer - 也会失去所有效果 - 将被使用{{1来自offset并且在读取操作OVERLAPPED之后将根据偏移+字节重新更新