如何正确从Parquet文件中读取固定长度数组物理类型的Decimal值
问题原因说明
这个现象是Parquet格式标准中Decimal类型的编码规则决定的,属于预期行为,不是parquet-cpp库的问题。
核心规则
Parquet规范明确要求:使用FIXED_LEN_BYTE_ARRAY物理类型存储Decimal逻辑类型时,值必须编码为大端序的有符号补码整数,且编码后的字节序列长度需要匹配Decimal精度对应的最小字节数,不足时会在高位补符号位:
- 负数高位补
0xFF - 正数高位补
0x00
你示例中多出来的0xFF就是负数对应的补位符号字节。
补位的设计原因
虽然数值本身的补码已经携带符号信息,但补位规则是为了解决跨语言、跨实现的兼容问题:
部分框架解析字节序列时,默认按无符号整数处理,或者如果读取到的字节长度和预期精度要求的长度不匹配时,会自动高位补0,导致原本的负数被误解析为超大正数。统一补符号位的规则可以保证所有符合规范的实现,读取完整编码后的字节序列都能得到正确的符号和数值。
处理方案
如果需要获取原始的无补位字节,可以按以下规则处理编码后的字节序列:
- 负数:去掉开头连续的
0xFF,直到剩余字节的最高位为1即可 - 正数:去掉开头连续的
0x00,直到剩余字节的最高位为0即可
注意处理时要保留足够的字节长度,避免截断有效数值位。
官方依据
该规则明确写入Parquet格式官方规范的逻辑类型(Logical Types)章节中Decimal部分的编码要求。
内容的提问来源于stack exchange,提问作者Alon Granot
相关产品推荐
相关产品推荐

