[英]Reading binary data without reinterpret_cast
Just because I've never read binary files before I wrote a program that reads binary STL files. 仅仅因为我在编写读取二进制STL文件的程序之前从未读过二进制文件。 I use
ifstream
s read member that takes a char* a parameter. 我使用
ifstream
的读取成员获取char *参数。 To cast my struct to a char* I use a reinterpret_cast. 要将我的结构转换为char *,我使用reinterpret_cast。 But as far as I remember every book about C++ I read said something like "don't use reinterpret_cast except you have to".
但据我记得每本关于C ++的书我读到的都说“不要使用reinterpret_cast,除非你必须”。 What would be a better way read binary data, not necessarily direct, but at last into a struct and without reinterpret_cast?
什么是更好的方式读取二进制数据,不一定是直接的,但最后到一个结构,没有reinterpret_cast?
The main function: 主要功能:
std::ifstream in (cmdline[1].c_str(), std::ios::binary);
in.seekg(80, std::ifstream::beg); //skip header
int numTriangle;
in.read (reinterpret_cast<char*>(&numTriangle), sizeof(int)); //determine number of triangles
//create triangle data type and read data
triangle* t = new triangle();
for (int i = 0; i < numTriangle; ++i) {
in.read(reinterpret_cast<char*>(t), triangle::size);
std::cout << *t; // there's an opertor<< for triangle
}
delete t;
in.close(); //close file read from
And the triangle struct 和三角形结构
//attempt to get the right size of a class without structure padding
#pragma pack(push)
#pragma pack(1)
//standard STL triangle data structure
struct triangle {
public:
float n[3]; //normals, 4*3=12 bytes
float x[3]; //first point of the triangle, 4*3=12 bytes
float y[3]; //second point of the triangle, 4*3=12 bytes
float z[3]; //third point of the triangle, 4*3=12 bytes
long int a; //attributes, 2 bytes
static const int size = 12+12+12+12+2; //sum of member variables
//static const int size = sizeof(n) + sizeof(x) + sizeof(y) + sizeof(z) + sizeof(a);
};
#pragma pack(pop)
(Extra question: #pragma pack(1) doesn't work with cygwins g++-4. How can I determine the size of the struct?) (额外的问题:#pragma pack(1)不适用于cygwins g ++ - 4.如何确定结构的大小?)
Well, that code looks fine. 好吧,那段代码看起来不错。 You are even caring about the padding issue.
你甚至关心填充问题。 I don't see how you can avoid casting here.
我看不出你怎么能避免在这里施展。 You can do this sequence:
你可以这样做:
static_cast<char*>(static_cast<void*>(t))
But really, i don't do that in my code. 但实际上,我不会在我的代码中这样做。 It's just a more noisy way of doing a direct reinterpret_cast to
char*
. 这只是一种更为嘈杂的方式,可以直接对
char*
reinterpret_cast。 (See casting via void* instead of using reinterpret_cast ). (请参阅通过void *而不是使用reinterpret_cast进行转换 )。
The struct size can be determined using sizeof
. 可以使用
sizeof
确定结构大小。 You just have to initialize the static
member out of the class inside the .cpp
(however, then the compiler doesn't know the value of ::size
anymore and can't inline it). 您只需要在
.cpp
内的类中初始化static
成员(但是,编译器不再知道::size
的值,并且不能内联它)。
Alternatively, you can write it as a static inline member function. 或者,您可以将其编写为静态内联成员函数。 In its body, the class type is considered complete and
sizeof (triangle)
is allowed. 在它的主体中,类类型被认为是完整的并且允许
sizeof (triangle)
。 Or you can just use sizeof
like you have in the comment, but use the type and not the members (referring to nonstatic members that way is allowed only in C++0x) : 或者您可以在注释中使用
sizeof
,但是使用类型而不是成员(指的是仅在C ++ 0x中允许的非静态成员):
//standard STL triangle data structure
struct triangle {
public:
float n[3]; //normals, 4*3=12 bytes
float x[3]; //first point of the triangle, 4*3=12 bytes
float y[3]; //second point of the triangle, 4*3=12 bytes
float z[3]; //third point of the triangle, 4*3=12 bytes
long int a; //attributes, 2 bytes
static int size() { return sizeof(triangle); } // this way
static const int size = sizeof(float[3])*4 + sizeof(long int); // or this way
};
However, the second way is not nice since you can easily forget updating it when you add a member. 但是,第二种方式并不好,因为您在添加成员时很容易忘记更新它。
额外的问题:看看__attribute__((packed))
。
Using streams for file i/o (esp. binary) is just nasty in my opinion. 在我看来,使用文件i / o(特别是二进制)的流是非常讨厌的。 I'd rather just use the old C functions like fopen and fread if I were you.
如果我是你,我宁愿只使用旧的C函数,如fopen和fread。
Also, memory mapping of a file is a technique which is given too little love, IMO. 此外,文件的内存映射是一种给予太少爱的技术,IMO。 I don't know of any standard/portable libraries that support it, but if you're on Windows I suggest checking this MSDN article
我不知道任何支持它的标准/可移植库,但是如果你在Windows上我建议查看这篇MSDN文章
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.