C#已知字节结构时如何读取字节流解析Blender .blend文件
C# 解析Blender .blend文件SDNA结构体字段实现方案
解析前首先完成全局参数初始化:从文件头读取两个核心配置,一是文件字节序(小端/大端),二是指针位宽(32位文件指针占4字节,64位文件指针占8字节)。两个参数配置错误会导致全量字段读取值异常。
各类型字段解析规则
- 基础整数类型(
short/ushort/int/uint/long/ulong):按照SDNA定义的类型长度读取对应字节,对比系统当前字节序和文件字节序,不一致时先反转字节段,再调用BitConverter对应方法转换为目标值。参考实现:
// 全局缓存系统字节序,初始化时根据文件头设置是否需要反转字节 private static readonly bool _systemIsLittleEndian = BitConverter.IsLittleEndian; private bool _needReverseByteOrder; private int _pointerLength; // 取值4或8,从文件头读取配置 private short ReadInt16(ReadOnlySpan<byte> buffer, ref int offset) { ReadOnlySpan<byte> seg = buffer.Slice(offset, 2); offset += 2; if (_needReverseByteOrder) seg.Reverse(); return BitConverter.ToInt16(seg); } // 其余uint/int/long等整数类型按对应长度调整Slice参数即可
- 浮点数类型(
float/double):解析逻辑和整数一致,float读取4字节调用BitConverter.ToSingle转换,double读取8字节调用BitConverter.ToDouble转换,同样注意字节序反转处理。 - 复合值类型(
Vec2s/Vec3f/Vec4i等向量、自定义结构体):严格按照SDNA定义的字段顺序、单个字段类型长度依次连续读取即可,你当前读取Vec2s前4字节得到(1311,9206)的逻辑是正确的,例如Vec2f就是连续读取两个float值,Vec3i就是连续读取三个int值,无需额外转换。 - 指针类型:指针本质是文件写入时记录的旧内存地址值,32位文件读4字节转
uint,64位文件读8字节转ulong。你需要在解析所有FileBlock阶段,提前构建旧内存地址 -> 对应FileBlock索引的全局映射字典:读取指针拿到地址值后,若值为0则是空指针直接返回null,否则去映射字典中查找对应地址的FileBlock,就是该指针指向的目标数据块。
注意:不要直接把读取到的地址值当作C#内存指针使用,这个值只是.blend文件内部的块定位标识,和当前程序运行的内存地址没有关联。
- 字符串/名称类型:Blender内字符串分两类解析:
- 定长字符数组字段:例如Mesh结构体的名称字段是固定长度的char数组,读取对应长度的字节段,按ASCII(新版本带UTF-8标识的按UTF-8)解码,截断到第一个
\0终止符位置就是实际字符串值。 - 字符指针字段:先按照指针解析规则找到指向的FileBlock,该块的Body段就是完整字符串字节,同样解码后截断
\0终止符即可。
- 定长字符数组字段:例如Mesh结构体的名称字段是固定长度的char数组,读取对应长度的字节段,按ASCII(新版本带UTF-8标识的按UTF-8)解码,截断到第一个
内容的提问来源于stack exchange,提问作者Simon Nordon
相关产品推荐
相关产品推荐

