【发布时间】:2019-10-15 14:55:48
【问题描述】:
在我的粒子系统模拟代码中,我为粒子定义了一个类,每个粒子都有一个包含其位置的属性pos,即double pos[3];,因为每个粒子有3 个坐标分量。所以用particles = new Particle[npart];定义的粒子对象(因为我们有npart许多粒子),然后例如第二个粒子的 y 分量将通过double dummycomp = particles[1].pos[1]; 访问
为了在使用二进制文件之前将粒子保存到文件中,我会使用(保存为 txt,浮点精度为 10,每行一个粒子):
#include <iostream>
#include <fstream>
ofstream outfile("testConfig.txt", ios::out);
outfile.precision(10);
for (int i=0; i<npart; i++){
outfile << particle[i].pos[0] << " " << particle[i].pos[1] << " " << particle[i].pos[2] << endl;
}
outfile.close();
但现在,为了节省空间,我尝试将配置保存为二进制文件,我的尝试受here 启发,如下所示:
ofstream outfile("test.bin", ios::binary | ios::out);
for (int i=0; i<npart; i++){
outfile.write(reinterpret_cast<const char*>(particle[i].pos),streamsize(3*sizeof(double)));
}
outfile.close();
但我在尝试运行它时遇到了分段错误。我的问题是:
- 我在
reinterpret_cast或者更确切地说是在streamsize()的论点中做错了吗? - 理想情况下,如果保存的二进制格式也可以在 Python 中读取,那就太好了,我的方法(一旦修复)是否允许这样做?
旧保存方法的工作示例(非二进制):
#include <iostream>
#include <fstream>
using namespace std;
class Particle {
public:
double pos[3];
};
int main() {
int npart = 2;
Particle particles[npart];
//initilizing the positions:
particles[0].pos[0] = -74.04119568;
particles[0].pos[1] = -44.33692582;
particles[0].pos[2] = 17.36278231;
particles[1].pos[0] = 48.16310086;
particles[1].pos[1] = -65.02325252;
particles[1].pos[2] = -37.2053818;
ofstream outfile("testConfig.txt", ios::out);
outfile.precision(10);
for (int i=0; i<npart; i++){
outfile << particles[i].pos[0] << " " << particles[i].pos[1] << " " << particles[i].pos[2] << endl;
}
outfile.close();
return 0;
}
并且为了将粒子位置保存为二进制,将上述样本的保存部分替换为
ofstream outfile("test.bin", ios::binary | ios::out);
for (int i=0; i<npart; i++){
outfile.write(reinterpret_cast<const char*>(particles[i].pos),streamsize(3*sizeof(double)));
}
outfile.close();
第二个附录:在 Python 中读取二进制文件
我设法使用 numpy 在 python 中读取保存的二进制文件,如下所示:
data = np.fromfile('test.bin', dtype=np.float64)
data
array([-74.04119568, -44.33692582, 17.36278231, 48.16310086,
-65.02325252, -37.2053818 ])
但是考虑到 cmets 对二进制格式的不可移植性提出的质疑,我不相信这种在 Python 中的阅读方式会一直有效!如果有人能阐明这种方法的可靠性,那就太好了。
【问题讨论】:
-
旁注:使用
ifstream和ofstream时不需要指定方向; “i”表示“in”,“o”表示“out”,您很少需要显式关闭它们中的任何一个 - 析构函数会处理这些。 -
请不要重新发明轮子。使用像 cereal 或 Boost serialization 这样的健全的库进行序列化。
-
pos的定义是什么?是[3]吗? -
那么粒子对象定义为particles = new Particle[npart]; -- 在哪里?评论和描述不是事实,只有代码才是事实。请发帖minimal reproducible example。
-
当您需要联系
reinterpret_cast时,您需要停下来想一想“我是不是在这里写了一个错误”,答案是通常“是”。跨度>
标签: c++ fstream binaryfiles