C++ 无法将动态数组写入文件

C++ Cannot write dynamic array to file

本文关键字:文件 数组 动态 C++      更新时间:2023-10-16

我正在尝试从浮点数的动态数组写入二进制文件。

这是我的代码:

FILE* file;
std::ofstream outStream;
file = fopen("mesh1.model", "w");
outStream = std::ofstream(file);
unsigned numTriangles;
float *vertices;
float *uvs;
unsigned degree = 0;
numTriangles = 2 * std::pow(4, degree); // numTriangles == 2 in this case
vertices = new float[9 * numTriangles];
uvs = new float[6 * numTriangles];
vertices[0] = -1.0f;
vertices[1] = 0.0f;
vertices[2] = 1.0f;
uvs[0] = 0.0f;
uvs[1] = 0.0f;
[....]
vertices[15] = 1.0f;
vertices[16] = 0.0f;
vertices[17] = -1.0f;
uvs[10] = 1.0f;
uvs[11] = 1.0f;
outStream.write((const char*)numTriangles, sizeof(numTriangles));
// Get runtime error on the line after this comment [access violation] (VS2013)
outStream.write((const char*)&(vertices), sizeof(float) * 9 * numTriangles); 
outStream.write((const char*)&(uvs), sizeof(float) * 6 * numTriangles);
delete[] vertices;
delete[] uvs;
fclose(file);
file = fopen("mesh1.model", "r");

我查看了过去有类似问题的评论,但它们没有帮助。

其中一个使用了我尝试过的reinterpret_cast但没有帮助。

这是你的罪魁祸首:

outStream.write((const char*)numTriangles, sizeof(numTriangles));

第一个参数应该是要写入的数据的地址,而不是数据本身!
将数据强制转换为预期的指针将关闭编译器,但会产生垃圾或核心转储(非法读取访问(。

您可能希望改用类似的东西:

outStream.write((const char *) & numTriangles, sizeof(numTriangles));

reinterpret_cast并不是真的必要,除非你认为C++不够冗长。

ofstream 与流接口配合得很好,也就是说,当您想利用<<运算符重载将对象的文本表示形式放入文件中时。

要编写纯二进制文件,ofstream只是非常糟糕,因为它不提供透明的const void *指针,并迫使您强制转换您尝试编写的每个数据块。

我的建议是坚持使用 STDIO 并使用 fwrite ,因为无论如何您都是从fopen开始的。不那么冗长,而且也能完成工作。

编辑:

综上所述,正如cdhowie指出的那样,编写二进制数据的原始块可能会导致各种问题。

例如,假设您在具有不同大小的不同平台上重新编译代码unsigned(这就像为 x64 而不是 x32 构建一样简单(。当新编译的可执行文件尝试读取数据时,数据会变成什么样?

如果您打算编写持久的代码,则可以考虑在可移植序列化代码上投入更多精力,该代码至少会使用独立于本机二进制表示形式的值(至少是固定大小的整数和浮点数以及字节序处理(。

另一种解决方案可能是编写文本数据并让像gzip这样的专用库对其进行压缩。这也可能让你利用iostream哲学,即以文本数据的形式编写对象。

你的三个write()调用都是错误的。 但在我们进入之前,我们需要解决一件事:

切勿在C++中使用 C 样式转换。

C++有自己的、更具体的转换运算符,您应该始终使用它们。 在这种情况下,您希望使用 reinterpret_cast .

第一种情况是错误的,因为您正在将非指针转换为指针。相反,您应该使用指向numTriangles的指针。

outStream.write((const char*)numTriangles, sizeof(numTriangles));
// Should be this:
outStream.write(reinterpret_cast<const char *>(&numTriangles), sizeof(numTriangles));

在其他两种情况下,verticesuvs 已经是指针并指向要保存的数据,因此此处不应使用 & 运算符:

outStream.write((const char*)&(vertices), sizeof(float) * 9 * numTriangles); 
outStream.write((const char*)&(uvs), sizeof(float) * 6 * numTriangles);
// Should be this:
outStream.write(reinterpret_cast<const char *>(vertices), sizeof(float) * 9 * numTriangles); 
outStream.write(reinterpret_cast<const char *>(uvs), sizeof(float) * 6 * numTriangles);