[英]Do I understand the combination of fseek and fwrite/fread correctly
So I have been asked to "translate" some code from C to C++, what the request really is, is to remove raw C as much as possible and replace it with C++ STL function calls.所以我被要求将一些代码从 C“翻译”到 C++,真正的要求是尽可能多地删除原始 C 并将其替换为 C++ STL function 调用。
One of the things I have to change is the usage of pwrite
and pread
to std::fwrite
and std::fread
respectively.我必须更改的一件事是分别将pwrite
和pread
用于std::fwrite
和std::fread
。 However, the current code utilize heavily the offset option of pwrite
and pread
Because data is being written to a device on a Linux or BSD system, ie, /dev/sda1
.但是,当前代码大量使用pwrite
和pread
的偏移选项,因为数据正在写入 Linux 或 BSD 系统上的设备,即/dev/sda1
。
But std::fwrite
and std::fread
does not have the offset parameter like pwrite
and pread
.但是std::fwrite
和std::fread
没有像pwrite
和pread
那样的偏移量参数。 So from what I gather I would need to seek to the offset in the file first using std::fseek
and then do the write/read operation.因此,根据我收集到的信息,我需要首先使用std::fseek
查找文件中的偏移量,然后执行写/读操作。 Is my understanding of this correct?我对此的理解正确吗?
I have written a small test program to validate my assumptions, see below, but I would like to be a little more sure before just firing of the code.我已经编写了一个小测试程序来验证我的假设,见下文,但我想在触发代码之前更加确定。
The test program is compiled like this: clang++ -std=c++17 main.cpp
测试程序是这样编译的: clang++ -std=c++17 main.cpp
#include <vector>
#include <string>
#include <ctime>
#include <algorithm>
#include <cstdio>
void write(const std::string& device, const size_t offset, const std::vector<uint8_t>& data)
{
std::FILE* fp = std::fopen(device.c_str(), "wb");
if (offset != 0)
{
std::fseek(fp, 0, offset);
}
std::fwrite(data.data(), sizeof(uint8_t), data.size(), fp);
std::fclose(fp);
}
std::vector<uint8_t> read(const std::string& device, size_t offset, const size_t size)
{
std::vector<uint8_t> data(size);
std::FILE* fp = std::fopen(device.c_str(), "rb");
if (offset != 0)
{
std::fseek(fp, 0, offset);
}
std::fread(data.data(), sizeof(uint8_t), size, fp);
std::fclose(fp);
return data;
}
std::vector<std::vector<uint8_t>> generate(const size_t num_vec, const size_t data_size)
{
std::vector<std::vector<uint8_t>> vectors;
for (size_t i = 0; i < num_vec; ++i)
{
std::vector<uint8_t> data(data_size);
std::generate(data.begin(), data.end(), rand);
vectors.push_back(data);
}
return vectors;
}
int main(void)
{
srand(static_cast<uint32_t>(time(0)));
const std::string device = "/dev/sda1";
const size_t size = 4096;
const size_t num_vec = 4;
auto vectors = generate(num_vec, size);
size_t offset = 0;
for (const auto& vec : vectors)
{
write(device, offset, vec);
auto other = read(device, offset, size);
if (vec != other)
{
std::puts("success");
}
else
{
std::puts("failure");
}
offset = offset + size;
}
}
You swapped some parameters.你交换了一些参数。 Your fseek
call should look like this你的fseek
电话应该是这样的
if (offset != 0)
{
std::fseek(fp, offset, SEEK_SET);
}
Otherwise your understanding is correct.否则你的理解是正确的。 You seek, then you read.你寻找,然后你阅读。 Note that this two-step solution is a) slower (two system calls) and b) not threadsafe if you use the same FILE*
in multiple threads.请注意,如果您在多个线程中使用相同的FILE*
,则此两步解决方案 a) 较慢(两个系统调用)和 b) 不是线程安全的。
Since you mentioned translating to C++: fwrite
and fseek
are parts of the C library.由于您提到翻译为 C++: fwrite
和fseek
是 C 库的一部分。 If you want an STL C++ solution, switch to std::fstream
instead.如果您想要 STL C++ 解决方案,请改用std::fstream
。
#include <fstream>
void write(const std::string& device, const size_t offset,
const std::vector<uint8_t>& data)
{
std::ofstream fp {device, std::ios::binary };
if (offset != 0)
{
fp.seekg(offset);
}
fp.write(reinterpret_cast<const char*>(data.data()),
sizeof(uint8_t) * data.size());
}
Your understanding is correct, but the parameters are wrong.你的理解是对的,但是参数不对。 To seek a n
th byte from beginning of a file use:要从文件开头查找第n
个字节,请使用:
// parameter descriptions:
// descriptor, offset, origin
std::fseek(file, n, SEEK_SET);
From description of the function:根据 function 的描述:
If the stream is open in binary mode, the new position is exactly offset bytes measured from the beginning of the file if origin is SEEK_SET, from the current file position if origin is SEEK_CUR, and from the end of the file if origin is SEEK_END.如果 stream 以二进制模式打开,则新的 position 正好是从文件开头测量的偏移字节(如果 origin 是 SEEK_SET),如果 origin 是 SEEK_CUR,则从当前文件 position 开始,如果 origin 是 SEEK_END,则从文件末尾开始测量。 Binary streams are not required to support SEEK_END, in particular if additional null bytes are output.二进制流不需要支持 SEEK_END,特别是如果额外的 null 字节是 output。
See example at the bottom of a cppreference page .请参阅 cppreference 页面底部的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.