c++,如何一次将几个简单的矢量写入一个二进制文件
c++, how to write several simple vectors to a binary file in one shot
我有非常简单但巨大的向量:
struct Vectors //of the same types and the same sizes
{
vector<int> A;
vector<int> B;
vector<int> C;
vector<int> D;
vector<int> E;
vector<int> F;
}
并希望一次性将它们写入二进制文件。
到目前为止,我在file.write(reinterpret_cast<const char*>(&A[0]), sizeof(A));
、file.read(reinterpret_cast<char*>(&A[0]), sizeof(binaryfile));
的帮助下成功地将单个矢量写入并读取到二进制文件中
我一个接一个地对这6个矢量做了同样的事情,但当我试图读取二进制文件时,出现了一个错误:vector subscript out of range
问题可能是自动填充吗?如何克服它?有可能一次写入然后读取整个矢量结构吗?这样它就可以在我内存mmap二进制文件后随时使用了吗?顺便说一句,我并不坚持使用向量,我可以使用数组或任何更适合我的数据类型。。。
读取和写入矢量的整个数据段的诀窍是在写入之前先获取数据块的大小,然后在读取之前先获取该数据块的尺寸。但当然,读取时您不知道大小,因此大小也需要在文件中。这允许您为向量分配那么多空间,然后读取那么多数据。
以下是一种可能的实现方式。我走了捷径。你的文件头可能应该有一个可以检查的标识符,这样你就知道你正在读取一个声称正确遵循你布局的文件。你真的,真的需要检查文件打开和读写是否有效。我没有为我的运算符==((编写测试,我用它来测试加载/保存对(尽管我在调试器中检查过一次值(。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
struct Vectors {
std::vector<int> A, B, C, D, E, F;
bool save(const char * filename);
bool load(const char * filename);
bool operator == (const Vectors &rhs);
};
void initialize_dummy_ints(std::vector<int> &v, int size){
v.resize(size);
for (int n = 0; n < size; ++n)
v[n] = n + 1;
}
bool Vectors::save(const char * filename){
std::ofstream out(filename, std::ios::binary);
int a=A.size(), b=B.size(), c=C.size(), d=D.size(), e=E.size(), f=F.size();
out.write(reinterpret_cast<const char*>(&a), sizeof(a));
out.write(reinterpret_cast<const char*>(&b), sizeof(b));
out.write(reinterpret_cast<const char*>(&c), sizeof(c));
out.write(reinterpret_cast<const char*>(&d), sizeof(d));
out.write(reinterpret_cast<const char*>(&e), sizeof(e));
out.write(reinterpret_cast<const char*>(&f), sizeof(f));
out.write(reinterpret_cast<const char*>(&A[0]), sizeof(int)*A.size());
out.write(reinterpret_cast<const char*>(&B[0]), sizeof(int)*B.size());
out.write(reinterpret_cast<const char*>(&C[0]), sizeof(int)*C.size());
out.write(reinterpret_cast<const char*>(&D[0]), sizeof(int)*D.size());
out.write(reinterpret_cast<const char*>(&E[0]), sizeof(int)*E.size());
out.write(reinterpret_cast<const char*>(&F[0]), sizeof(int)*F.size());
// always check to see if the file opened, and if writes succeeded.
// I am being lazy here so I can focus on the actual question
return true;
}
bool Vectors::load(const char *filename){
std::ifstream in(filename, std::ios::binary);
int a, b, c, d, e, f;
in.read(reinterpret_cast<char*>(&a), sizeof(a));
in.read(reinterpret_cast<char*>(&b), sizeof(b));
in.read(reinterpret_cast<char*>(&c), sizeof(c));
in.read(reinterpret_cast<char*>(&d), sizeof(d));
in.read(reinterpret_cast<char*>(&e), sizeof(e));
in.read(reinterpret_cast<char*>(&f), sizeof(f));
A.resize(a); B.resize(b); C.resize(c); D.resize(d); E.resize(e); F.resize(f);
in.read(reinterpret_cast<char*>(&A[0]), sizeof(int)*A.size());
in.read(reinterpret_cast<char*>(&B[0]), sizeof(int)*B.size());
in.read(reinterpret_cast<char*>(&C[0]), sizeof(int)*C.size());
in.read(reinterpret_cast<char*>(&D[0]), sizeof(int)*D.size());
in.read(reinterpret_cast<char*>(&E[0]), sizeof(int)*E.size());
in.read(reinterpret_cast<char*>(&F[0]), sizeof(int)*F.size());
// always check to see if the file opened, and if writes succeeded.
// I am being lazy here so I can focus on the actual question
return true;
}
bool matches(const std::vector<int> &l, const std::vector<int> &r){
if (l.size() != r.size())
return false;
for (size_t x = 0; x < l.size(); ++x)
if (l[x] != r[x])
return false;
return true;
}
bool Vectors::operator==(const Vectors &rhs){
return matches(A, rhs.A) && matches(B, rhs.B) && matches(C, rhs.C) && matches(D, rhs.D) && matches(E, rhs.E) && matches(F, rhs.F);
}
int main()
{
// setup
Vectors starting_values;
initialize_dummy_ints(starting_values.A, 10);
initialize_dummy_ints(starting_values.B, 12);
initialize_dummy_ints(starting_values.C, 14);
initialize_dummy_ints(starting_values.D, 10);
initialize_dummy_ints(starting_values.E, 5);
initialize_dummy_ints(starting_values.F, 2);
// write to file
starting_values.save("data.bin");
// read back in to memory
Vectors loaded_values;
loaded_values.load("data.bin");
// compare
if (loaded_values == starting_values)
std::cout << "success";
else
std::cout << "failure";
return 0;
}
- 你不能简单地在一个命令中写出一个向量列表。尽管矢量保证它们将数据存储在连续的存储空间中,但不同矢量的数据不会是连续的
- 如果你用你现在的方式写出向量,就不可能正确地读回来,因为你不知道向量有多少元素
给定一个向量,正确的写和读方法如下:
void writeVector(ostream& file, const vector<int>& A) {
size_t count = A.size();
file.write(reinterpret_cast<const char*>(&size), sizeof(size));
file.write(reinterpret_cast<const char*>(A.data()), sizeof(A[0]) * count);
}
void readVector(istream& file, vector<int>& A) {
size_t size = 0;
file.read(reinterpret_cast<char*>(*size), sizeof(size));
A.resize(size); // Make sure the vector has space for what you're about to read in!
file.read(reinterpret_cast<char*>(A.data()), sizeof(A[0]) * count);
}
我想不出任何方法可以像你想的那样在一次拍摄中写出所有向量。我怀疑这是不可能的。使用vector<vector<int>>
而不是struct Vectors
可能会有所帮助,因为这样你就可以简单地在循环中运行上面的代码:
void writeVectors(ostream& file, const vector<vector<int>>& stuff) {
size_t count = stuff.size();
file.write(reinterpret_cast<const char*>(&size), sizeof(size));
for(const vector<int>& v : stuff) {
writeVector(file, v);
}
}
void readVectors(istream& file, vector<vector<int>>& stuff) {
size_t count = 0;
file.read(reinterpret_cast<char*>(*size), sizeof(size));
A.resize(size); // Make sure the vector has space for what you're about to read in!
for(const vector<int>& v : stuff) {
readVector(file, v);
}
}
现在,如果你想要的是可以在一次拍摄中轻松写出的东西,那么你必须选择静态大小的东西。基本上,这意味着您需要使用数组。如果你有这样一个结构:
struct Vectors {
int A[50];
int B[50];
int C[50];
// ... etc ...
};
然后以下读/写命令将起作用:
file.write(reinterpret_cast<const char*>(&A), sizeof(A));
file.read(reinterpret_cast<char*>(&A), sizeof(A));
我不认为会有填充,但不能保证。
如果Vectors
的定义如下:,上述可能也适用
#include <array>
struct Vectors {
array<int,50> A;
array<int,50> B;
array<int,50> C;
// ... etc ...
};
这两种方法都需要对每个数组的大小设置一个严格的上限,如果你想让它们看起来是动态大小的,你还需要安排一些特定的值来用作元素不存在的标记(一种方法是#include <limit>
,然后有const int EMPTY = numeric_limits<int>::min();
(。
YOur sizeof((是绝对错误的
对于类型为T(在您的情况下为int(的向量作为大小,您应该放置v.size()*sizeof(T)
类似的东西
file.write(reinterpret_cast<const char*>(&A[0]), A.size()*sizeof(A[0]));
更新
如果您使用的是C++11,那么您可以直接作为A.data()
访问底层存储,因此
file.write(reinterpret_cast<const char*>(A.data()), A.size()*sizeof(A[0]));
我想一次性将它们写入二进制文件。
你不能做这样的事。为了使用单个函数批量写入所有矢量,矢量中分配的所有数据必须是连续的(不能保证(。您可以一个接一个地保存向量,这可能是最好、最简单的解决方案。
注意:
file.write(interpret_cast(&A[0](,sizeof(A((;
是错误的。sizeof(A)
实际上是堆栈上向量的大小,而&A[0]
返回指向堆中数据的指针。使用A.size() * sizeof(A[0])
获取数据大小,使用A.data()
获取数据指针
您得到的错误是在读取时,这是因为您没有在向量上分配足够的内存。向量的大小为0,并且索引0
不存在,因此&A[0]
抛出异常。使用函数A.data()
可以解决这个问题,但仍然需要分配足够的内存来填充向量。
如果你的代码看起来像这个
size_t sizeToRead; // Retrieved from somewhere
file.read(reinterpret_cast<char*>(A.data()), sizeToRead);
确保你在上面的线路之前打电话给:
A.resize(sizeToRead);
或者以这样的大小启动A:
vector<int> A(sizeToRead);
- 如何将包含另一个对象向量的对象保存到文件中,并使用C++中的二进制文件从文件中读回?
- 如何在标准c ++中流式传输/读取二进制文件的中间部分并写入另一个文件?
- 是否可以在一个循环中写入多个二进制文件
- 程序错误地读取了二进制文件的一个字节
- 如何创建一个新的二进制文件并用常量值填充它?
- 无法一次从二进制文件中读取一个 int
- 在 NDK 上编译两个带有 gradle 的项目,其中一个依赖于另一个的二进制文件
- 我有一个预处理的 C/C++ 源文件 (cacti.i).如何从这个 .i 文件生成可执行二进制文件,以便我可以像 ./
- C++:如何在线程中读取二进制文件并将其写入另一个线程?
- 将XSD文件嵌入一个(二进制文件)中
- 从一个二进制文件中读取信息,并写入另一个二进制文件
- 将 tesseract 编译/捆绑为一个二进制文件
- 如何将所有依赖项和共享库编译为一个二进制文件
- 我正在尝试读取一个包含字符串和整数的二进制文件..并打印出与字符串对应的整数
- 获取二进制文件的所有可能变体 - 给定一个模式
- C 打开一个二进制文件
- 在 Google 的C++测试框架中为多个单元测试创建一个二进制文件
- 如何从不同部分读取二进制文件的var?(例如,2个字节,另一个位置有2个字节?)
- 在读取 Visual C++ 中的二进制文件(而不是其他编译器)后,每隔一个字符都是 NULL
- Python:将二进制文件读取到一个结构中,然后拆包