You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不同类型numpy数组tobytes返回格式及C++读取pandas二进制文件问题

核心问题原因

你调用df.to_numpy()得到的数组dtype为object,这类数组在内存中存储的不是实际数值/字符串的内容,而是对应Python对象的内存指针,tobytes输出的内容是这些指针的二进制值,而非你预期的实际数据二进制,所以C++侧直接读取必然得到乱码。

1. numpy的tobytes方法作用

tobytes会直接读取数组在内存中的原始二进制序列并返回,不会做额外的类型转换、结构解析,输出内容完全由数组的dtype定义决定。如果数组是数值类型,输出的就是数值对应的二进制表示;如果是object类型,输出的就是Python对象的内存地址二进制。

2. 混合类型数组tobytes的格式

只要numpy数组的dtype是object,不管里面存的是数值、字符串还是其他Python对象,每个元素占的字节数等于系统指针长度(64位系统占8字节,32位系统占4字节),内容就是该Python对象在当前Python进程中的内存地址,和对象本身的数值没有直接关系,完全无法被其他进程/跨语言直接解析。


正确实现方案

要实现跨语言读取二进制数据,不能使用object类型数组,需要将不同类型的列拆分处理,保证Python侧的dtype和C++侧的类型一一对应:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.reshape(range(25), (5,5)))
df[0] = 101.0
df['ticker'] = 'nick'

# 导出数值列,指定为float32对应C++的float类型
numeric_cols = df.iloc[:, :5].to_numpy(dtype=np.float32)
# 导出字符串列,转成固定长度4字节的字节类型,对应C++的char[4]
str_col = df['ticker'].str.encode('utf-8').to_numpy().astype('S4')

# 写入二进制文件
with open('data.bin', 'wb') as f:
    f.write(numeric_cols.tobytes())
    f.write(str_col.tobytes())

对应C++读取代码:

#include <fstream>
#include <iostream>

using namespace std;

int main() {
  std::fstream f("data.bin", std::ios::binary | std::ios::in);
  if (!f.is_open()) { printf("open failed"); exit(1); }
  // 读取5行5列的float数值,共25个float
  float numeric_buf[25];
  f.read((char*)numeric_buf, sizeof(numeric_buf));
  cout << numeric_buf[0] << endl; // 输出预期值101
  // 读取5个长度为4的字符串
  char str_buf[5][4];
  f.read((char*)str_buf, sizeof(str_buf));
  cout << str_buf[0] << endl; // 输出nick
  return 0;
}

注意事项

  • 类型必须严格对应:np.float32对应C++float、np.float64对应C++double、np.int32对应C++int、固定长度字节类型Sx对应C++char[x]
  • 同架构下默认字节序一致,跨架构读写需要额外处理大小端转换
  • 如果字符串长度不固定,需要先存储每个字符串的长度再存储内容,不要使用object类型存储可变长度字符串

内容的提问来源于stack exchange,提问作者nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 09:45:05