C++ WriteFile重叠和fwrite等价

C++ WriteFile重叠和fwrite等价,c++,file,io,C++,File,Io,在Windows上,该函数有一个名为lpOverlapped的参数,可用于指定写入文件的偏移量 我想知道,是否有一个fwrite跨平台的类似产品 我看到,如果文件是用rb+标志打开的,我可能可以使用fseek写入特定的偏移量。我的问题是——这种方法是否等同于重叠写文件,是否会在所有平台上产生相同的行为 背景 我之所以需要它,是因为我正在将阻塞的压缩数据流写入一个文件,并且我希望能够从该文件加载一个特定的块并对其进行解压缩。因此,基本上,如果我跟踪块在文件中的起始位置,我可以以更有效的方式加载块并

在Windows上,该函数有一个名为lpOverlapped的参数,可用于指定写入文件的偏移量

我想知道,是否有一个fwrite跨平台的类似产品

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

背景


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

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


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

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


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

< P>假设您使用POSIX函数,而不是从C或C++标准库中得到的解决方案,则解决方案是AK:OrdRead。
ssize_t rc = pwrite(file_handle, data_ptr, data_size, destination_offset);

假设使用POSIX函数,而不只是从C或C++标准库中得到的东西,那么解决方案是AK:定位写。

ssize_t rc = pwrite(file_handle, data_ptr, data_size, destination_offset);
虽然pwrite可能是最好的解决方案,但有一种替代方案坚持使用stdio函数。不幸的是,为了保证线程安全,您正在使用非标准stdio直接控制文件*的内部锁,并且名称不可移植。具体来说,POSIX定义了另一个集合,Windows定义了另一个集合/

也就是说,您可以使用这些半可移植的构造来使用stdio函数来确保pwrite到filenosome_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;
}
虽然pwrite可能是最好的解决方案,但有一种替代方案坚持使用stdio函数。不幸的是,为了保证线程安全,您正在使用非标准stdio直接控制文件*的内部锁,并且名称不可移植。具体来说,POSIX定义了另一个集合,Windows定义了另一个集合/

也就是说,您可以使用这些半可移植的构造来使用stdio函数来确保pwrite到filenosome_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;
}
在FrWrad之前使用FSETE。FrEnter是C STDIO,而不是C++ I/O。
OTC++ C++ I/No: PFrad比FreWE3更接近Wrave2。但是,WriteFile也是如此;pwrite、write和WriteFile基本上都是系统调用的薄包装,其中fwrite具有更高级别的用户空间缓冲。我认为这就是OP在这里实际要求的,因为他已经在使用Windows特定的WriteFile call.Yar。我想把区别弄清楚,我投赞成票的答案没有错。注意:pwrite比fwrite3更接近write2。但是,WriteFile也是如此;pwrite、write和WriteFile基本上都是系统调用的薄包装,其中fwrite具有更高级别的用户空间缓冲。我认为这就是OP在这里实际要求的,因为他已经在使用Windows特定的WriteFile call.Yar。我想把区别弄清楚,我投的答案没有错。谢谢你。我不需要为这个应用程序线程安全,但这是很好的知道。感谢这一点。我不需要为这个应用程序线程安全,但这是很好的知道。