WriteFile重叠和fwrite等价

时间:2016-10-13 22:32:35

标签: c++ file io

在Windows上,WriteFile()函数有一个名为lpOverlapped的参数,可让您指定写入文件的偏移量。

我在想,是否有一个fwrite()跨平台的等价物?

我看到如果使用rb+标志打开文件,我可能可以使用fseek()写入特定的偏移量。我的问题是 - 这种方法是否等同于重叠的WriteFile(),它会在所有平台上产生相同的行为吗?

背景

我需要这个的原因是因为我将阻塞的压缩数据流写入文件,我希望能够从文件加载特定的块并能够解压缩它。因此,基本上如果我跟踪块在文件中的开始位置,我可以加载块并以更有效的方式解压缩它。我知道有更好的方法可以做到这一点,但我需要这个解决方案来实现一些向后兼容性。

3 个答案:

答案 0 :(得分:3)

假设你可以使用POSIX函数,而不仅仅是C或C ++标准库中的东西,解决方案是pwrite(又名:定位写入)。

PS C:\> $vaultResourceID = "subscriptions/<GUID>/resourceGroups/VaultResources/providers/Microsoft.KeyVault/vaults/<yourvaultname>
PS C:\> $vault.Properti"
PS C:\> $vault = Get-AzureRmResource -ResourceId $vaultResourceID
PS C:\> $vault.Properties.sku.name
standard
PS C:\> $vault.Properties.sku.name = 'premium'
PS C:> Set-AzureRmResource -ResourceId $vaultResourceID -Properties $vault.Properties

答案 1 :(得分:2)

我认为你混淆了“重叠”和“覆盖”/“偏移”。我没有研究为什么微软明确表示重叠写入包含偏移参数的具体细节(我认为这有意义,如下所述)。一般来说,当微软谈论“重叠”IO时,他们正在谈论如何同步事件,比如开始编写文件,接收写入完成的通知,以及开始另一次写入文件,这可能会或可能不会重叠以前写过。在最后一种情况下,通过重叠,我的意思是你认为重叠意味着什么,即在文件内容中重叠。而Microsoft意味着编写文件与您的线程运行时是否重叠。请注意,如果多个线程可以写入同一个文件,则会变得非常复杂。

如果可能的话,当然如果你想要可移植的代码,你想要避免所有这些废话,只需在每个上下文中进行最简单的写操作,这意味着避免像“重叠IO”这样的Microsoft优化,除非你真的需要性能。 (如果您需要绝对最佳的性能,您可能希望自己缓存文件并管理重叠,然后从头到尾编写一次。)

答案 2 :(得分:2)

尽管pwrite可能是最佳解决方案,但仍有一种方法可以使用stdio函数。不幸的是,为了使其成为线程安全的,您使用非标准的“stdio”来直接控制FILE*的内部锁,并且这些名称不可移植。具体来说,POSIX定义one set of "take/release file lock" names,Windows定义另一组(_lock_file / _unlock_file)。

也就是说,您可以使用这些半便携式构造来使用stdio函数来确保没有缓冲冲突(pwritefileno(some_FILE_star)如果FILE*缓冲区可能会导致问题重叠pwrite位置,因为pwrite无法修复缓冲区):

// Error checking omitted; you should actually check returns in real code
size_t pfwrite(const void *ptr, size_t size, size_t n,
               size_t offset, FILE *stream) {
    // Take FILE*'s lock and hold it for entire transaction
    flockfile(stream);  // _lock_file on Windows

    // Record position
    long origpos = ftell(stream);

    // Seek to desired offset and write
    fseek(stream, offset, SEEK_SET); // Possibly offset * size, not just offset?
    size_t written = fwrite(ptr, size, n, stream);

    // Seek back to original position
    fseek(stream, origpos, SEEK_SET);

    // Release FILE*'s lock now that transaction complete
    funlockfile(stream); // _unlock_file on Windows
    return written;
}