我需要解析具有以下规范的文件:
V-Ray网格格式说明(.vrmesh)
现在使用以下方法解析前两个值:
char id[7];
fgets( id, 7, file );
uint32_t fileversion;
char bytesFileversion[4];
fgets( bytesFileversion, 4, file );
fileversion = bytesFileversion[3] | (bytesFileversion[2] << 8) | (bytesFileversion[1] << 16) | (bytesFileversion[0] << 24);
id和fileversion都可以打印好。
不幸的是,下一个字段是一个很长的int / uint64_t,我尝试用以下几种方式读取它:
uint64_t lookUpTable;
char bytes[8];
fgets( bytes, 8, file );
//It should work... but it acually doesn't work
lookUpTable = static_cast<uint64_t> (bytes[7]) |
(static_cast<uint64_t> (bytes[6]) << 8) |
(static_cast<uint64_t> (bytes[5]) << 16) |
(static_cast<uint64_t> (bytes[4]) << 24) |
(static_cast<uint64_t> (bytes[3]) << 32) |
(static_cast<uint64_t> (bytes[2]) << 40) |
(static_cast<uint64_t> (bytes[1]) << 48) |
(static_cast<uint64_t> (bytes[0]) << 56);
但是它没有用,我也发现了一个在Python https://github.com/bdancer/vray_tools/blob/master/VRayProxy.py中解析文件ok的实现,我无法理解为什么它可行,而我的实现却没有。
我试图修改那个py文件来读取/打印两个uint_32
self.lookupOffset = self.binRead("I", 4)[0]
self.report(" lookupOffseta = %i" % self.lookupOffset)
self.lookupOffset = self.binRead("I", 4)[0]
self.report(" lookupOffsetb = %i" % self.lookupOffset)
令人惊讶的是,我没有得到与使用
在C ++中完成相同的结果 uint32_t lookUpTableA;
char bytesLookUpTableA[4];
fgets( bytesLookUpTableA, 4, file );
lookUpTableA = bytesLookUpTableA[3] | (bytesLookUpTableA[2] << 8) | (bytesLookUpTableA[1] << 16) | (bytesLookUpTableA[0] << 24);
uint32_t lookUpTableB;
char bytesLookUpTableB[4];
fgets( bytesLookUpTableB, 4, file );
lookUpTableB = bytesLookUpTableB[3] | (bytesLookUpTableB[2] << 8) | (bytesLookUpTableB[1] << 16) | (bytesLookUpTableB[0] << 24);
所以它开始对我来说似乎是巫术。
提前感谢您的任何提示!
的二进制文件答案 0 :(得分:2)
计算机可以在两种布局中订购多字节整数: Big Endian 和 Little Endian 。 Big endian是最重要的字节,Little Endian是最不重要的字节 找出二进制文件具有哪种布局以及平台具有哪种布局。在开始编码之前非常重要的研究。
我建议将64位数据直接读入64位整数:
uint64_t data;
data_stream.fread((char *) &data, sizeof(data);
如果您的平台和数据文件具有相同的整数布局,则您的工作将在此处停止。
如果您的平台字节顺序与数据不同,那么您将不得不重新排列字节:
uint64_t data;
data_stream.fread((char *) &data, sizeof(data);
uint64_t converted_data;
converted_data = (data & 0x000000000000FF) << 56
| (data & 0x0000000000FF00) << 48
| (data & 0x00000000FF0000) << 40
| (data & 0x000000FF000000) << 32
| (data & 0x0000FF00000000) << 24
| (data & 0x00FF0000000000) << 16
| (data & 0xFF000000000000) << 8;
在上面的代码段中,converted_data
和data
属于同一类型,因此不需要强制转换。也没有对齐问题。
答案 1 :(得分:1)
除了armadillo.vrmesh之外,这似乎可以正常地从http://help.chaosgroup.com/vray/help/maya/sdk22/vrmesh_format.html读取示例文件,因为它使用不同的id字符串。版本是一致的,偏移量在文件范围内并且始终接近结束。我找不到文件内容其余部分的简单描述,所以我没有尝试进一步解码。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct VMeshInfo
{
std::string filename;
std::string id;
uint32_t version;
uint64_t lookup_offset;
bool read(const std::string& name)
{
filename = name;
std::ifstream f(filename, std::ios::binary);
if (!f)
{
std::cerr << "Error opening file '" << filename << "'\n";
return false;
}
char buffer[8] = { 0 };
if (!f.read(buffer, 7))
{
std::cerr << "Error reading id from file '" << filename << "'\n";
return false;
}
id = buffer;
if (id != "vrmesh")
{
std::cerr << "id != 'vrmesh' in file '" << filename << "'\n";
return false;
}
if (!f.read(reinterpret_cast<char*>(&version), sizeof version))
{
std::cerr << "Error reading version from file '" << filename << "'\n";
return false;
}
if (!f.read(reinterpret_cast<char*>(&lookup_offset), sizeof lookup_offset))
{
std::cerr << "Error reading lookup_offset from file '" << filename << "'\n";
return false;
}
return true;
}
void print(std::ostream& f)
{
f << "filename: " << filename << "\n";
f << "id: " << id << "\n";
f << "version: " << version << "\n";
f << "lookup_offset: " << lookup_offset << "\n";
f << "====================\n";
}
};
int main()
{
std::vector<std::string> files{ "cube.vrmesh", "cylinder_bend.vrmesh", "objects.vrmesh" };
for (auto& filename : files)
{
VMeshInfo info;
if (info.read(filename))
{
info.print(std::cout);
}
else
{
std::cerr << "Error reading file info!\n";
continue;
}
}
return 0;
}
输出:
filename: cube.vrmesh
id: vrmesh
version: 4096
lookup_offset: 798
====================
filename: cylinder_bend.vrmesh
id: vrmesh
version: 4096
lookup_offset: 271397
====================
filename: objects.vrmesh
id: vrmesh
version: 4096
lookup_offset: 68051
====================