在Windows上,WriteFile()
函数有一个名为lpOverlapped
的参数,可让您指定写入文件的偏移量。
我在想,是否有一个fwrite()
跨平台的等价物?
我看到如果使用rb+
标志打开文件,我可能可以使用fseek()
写入特定的偏移量。我的问题是 - 这种方法是否等同于重叠的WriteFile()
,它会在所有平台上产生相同的行为吗?
背景
我需要这个的原因是因为我将阻塞的压缩数据流写入文件,我希望能够从文件加载特定的块并能够解压缩它。因此,基本上如果我跟踪块在文件中的开始位置,我可以加载块并以更有效的方式解压缩它。我知道有更好的方法可以做到这一点,但我需要这个解决方案来实现一些向后兼容性。
答案 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
函数来确保没有缓冲冲突(pwrite
到fileno(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;
}