c++ - 如何将二进制文件转换为 size_t?
问题描述
我试图理解指针和二进制文件,但我被困住了。我想将包含 5 个水果的列表写入二进制文件。所以首先我尝试写 (size_t) 5,然后为每个水果片写它的大小,然后是字符串本身。这是我到目前为止得到的:
// Write
vector<string> fruit_list = {"Apple", "Pear", "Banana", "Cherry", "Melon"};
ofstream fruits_out;
fruits_out.open("fruits.bin", std::ios::binary | std::ios::out);
size_t fruit_total = fruit_list.size();
fruits_out.write((char*)&fruit_total, sizeof(fruit_total));
for (const string& fruit : fruit_list){
size_t fruit_size = fruit.size();
fruits_out.write((char*)&fruit_size, sizeof(fruit_size));
fruits_out.write(&fruit.c_str()[0], fruit_size);
}
fruits_out.close();
// Read
ifstream fruits_in;
fruits_in.open ("fruits.bin", std::ios::binary | std::ios::in);
char *buffer = new char;
fruits_in.read((char*)&buffer, sizeof(size_t));
cout << *buffer << endl;
我什至无法读取第一个值。请帮助我,不管这件事,我已经坚持了很长时间。
解决方案
您编写的代码很好(减去缺少错误处理,并且无需使用&c_str()[0]
whenc_str()
本身就足够了)。
但是,您的阅读代码都是错误的。您不仅要分配buffer
大小仅为 1 字节的 a,然后还要尝试将sizeof(size_t)
字节数读入其中。但更糟糕的是,您正在读取buffer
变量所在的堆栈空间,而不是您分配buffer
的指向的动态内存!
就像编写代码将size_t
by 指针传递给一样ostream::write()
,您也可以将size_t
by 指针传递给istream::read()
。
尝试更多类似的东西:
std::ostream& writeSizeT(std::ostream &out, size_t value)
{
out.write(reinterpret_cast<char*>(&value), sizeof(value));
/* alternatively:
uint64_t temp = htobe64(value); // or equivalent...
out.write(reinterpret_cast<char*>(&temp), sizeof(temp));
*/
return out;
}
std::ostream& writeString(std::ostream &out, const std::string &value)
{
size_t size = value.size();
if ((writeSizeT(out, size)) && (size > 0)) {
out.write(value.c_str(), size);
}
return out;
}
std::ostream& writeFruitList(std::ostream &out, const std::vector<std::string> &list)
{
if (writeSizeT(out, list.size())) {
for (const std::string &fruit : list){
if (!writeString(out, fruit)) {
break;
}
}
}
return out;
}
std::vector<std::string> fruit_list = {"Apple", "Pear", "Banana", "Cherry", "Melon"};
std::ofstream fruits_out("fruits.bin", std::ios::binary);
writeFruitList(fruits_out, fruit_list);
fruits_out.close();
std::istream& readSizeT(std::istream &in, size_t &value)
{
in.read(reinterpret_cast<char*>(&value), sizeof(value));
/* alternatively:
uint64_t temp;
if (in.read(reinterpret_cast<char*>(&temp), sizeof(temp))) {
temp = be64toh(temp); // or equivalent...
value = static_cast<size_t>(temp);
}
*/
return in;
}
std::istream& readString(std::istream &in, std::string &value)
{
value.clear();
size_t size;
if ((readSizeT(in, size)) && (size > 0)) {
value.resize(size);
in.read(&value[0]/*or: value.data()*/, size);
}
return in;
}
std::istream& readFruitList(std::istream &in, std::vector<std::string> &list)
{
list.clear();
size_t size;
if (readSizeT(in, size)) {
list.reserve(size);
std::string fruit;
for (size_t i = 0; (i < size) && (readString(in, fruit)); ++i){
list.push_back(std::move(fruit));
}
}
return in;
}
std::vector<std::string> fruit_list;
std::ifstream fruits_in("fruits.bin", std::ios::binary);
readFruitList(fruits_in, fruit_list);
fruits_out.close();
for (const auto &fruit: fruit_list) {
std::cout << fruit << std::endl;
}
推荐阅读
- r - 带有加权数据的 Weibull 分布
- sql - 如何在查询行源类型中附加默认值?
- json - 读取json数据时动态识别对象类型
- java - android应用程序上的R.string Resources $ NotFoundException错误
- css - 具有不同背景颜色的相同组件
- javascript - 使用 Fade Javascript 多次更改文本
- c# - WPF 依赖属性回调
- mysql - MySQL:按连接表的最大日期排序
- angular - 如何根据角度 4/角度 2 中的国家/地区选择预先选择电话代码?
- c# - 我想从已发布的 .net webforms 项目中获取代码隐藏