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

C++循环读写二进制点云文件时第二次读取报错排查

二进制点云文件读写故障排查

相关代码说明

两个类成员函数共同操作同一C:\PointCloud.dat二进制文件,配合三层嵌套循环实现点云按索引读取、计算处理、回写的逻辑,相关代码如下:

Reading(按索引读点)函数

负责根据i、j、k索引读取文件中存储的point3d类型点云数据:

myRepositoryPointCloud::point3d myRepositoryPointCloud::Reading(int i, int j, int k)
{
  ifstream rf("C:\\PointCloud.dat", ios::out | ios::binary);
  if (!rf) {
      cout << "Cannot open file!" << endl;
  }

  point3d resultPt;
  rf.seekg((i * GetCntPointY() * GetCntPointZ() + j * GetCntPointZ() + k) * sizeof(point3d));

  rf.read((char *)&resultPt, sizeof(point3d));

  rf.close();
  if (!rf.good()) {
      cout << "Error occurred at reading time!" << endl;
  }
  return resultPt;
}

Writing(按索引写点)函数

负责将point3d类型点云数据写入文件对应i、j、k索引位置:

void myRepositoryPointCloud::Writing(int i, int j, int k, point3d & APoint)
{
  ofstream wf("C:\\PointCloud.dat", ios::out | ios::binary);

  if (!wf) {
      cout << "Cannot open file!" << endl;
  }

  wf.seekp((i * GetCntPointY() * GetCntPointZ() + j * GetCntPointZ() + k) * sizeof(point3d));

  wf.write((char *)&APoint, sizeof(point3d));

  wf.close();
  if (!wf.good()) {
      cout << "Error occurred at writing time!" << endl;
  }
}

循环调用逻辑

三层嵌套循环中逐点读取、处理、回写,执行逻辑为:读取对应索引位置的点数据,经球体相交计算处理后,若点满足已删除或可见的判定条件,则将修改后的点写回文件原索引位置:

point3d CurrentPoint;

for (int i = 0; i < EndPoint.i - StartPoint.i; i++)
{
  for (int j = 0; j < EndPoint.j - StartPoint.j; j++)
    {
      for (int k = 0; k < EndPoint.k - StartPoint.k; k++)
        {
          CurrentPoint = FPointCloud->Reading(i, j, k);

          if (!CurrentPoint.deleted) 
          {
            Sphere->CalcIntersectSphereToPoint(&CurrentPoint);                    

            if (CurrentPoint.deleted || CurrentPoint.visible)
            {
               FPointCloud->Writing(i, j, k, &CurrentPoint);
            }
          }
    }
}

故障表现

  • 循环执行到第二步时,Reading函数触发Error occurred at reading time!读取错误
  • 移除循环中对Writing函数的调用后,程序可正常运行

根因定位

核心故障原因是文件打开模式配置错误,附带其他逻辑问题:

  1. Writing函数截断原文件:使用ofstream打开文件时仅指定ios::out | ios::binary,未搭配ios::in参数,该模式下打开已存在文件会直接将文件截断为0字节,清空所有原有数据。第一次写入单个点后,文件仅保留当前写入的点数据,其余位置内容全部丢失,下一次循环读取其他偏移位置时,文件长度不足,read操作无法读取到足够字节,触发流错误状态,抛出读取异常。
  2. Reading函数打开模式错误:作为读文件的输入流ifstream,错误传入了写模式专用的ios::out参数,属于无效配置,会导致流打开行为不符合预期。
  3. 传参类型不匹配:Writing函数形参为point3d类型引用,调用时传入了&CurrentPoint即point3d*指针类型,正常情况下会直接编译报错。
  4. 错误处理逻辑缺失:判断文件打开失败后仅打印日志,未提前返回,后续仍对无效流对象执行seek、读写操作,会触发未定义行为。
  5. (性能问题)每次读写单个点都重复执行打开、关闭文件操作,三层循环下IO开销极高,运行效率极低。

修复方案

  • 修正Reading函数打开模式:读文件使用ios::in | ios::binary,移除错误的ios::out参数,打开失败时直接返回默认值,避免后续无效操作。
  • 修正Writing函数打开模式:需要随机覆盖写入、不破坏原有文件内容时,使用ios::in | ios::out | ios::binary模式打开,该模式不会截断原有文件,可正常跳转到指定偏移位置写入数据。
  • 修正Writing函数调用参数:传参时直接传入CurrentPoint,不要取地址传指针,匹配引用形参类型。
  • 优化错误处理:文件打开失败、读写失败时打印日志后立即返回,不要继续操作无效流。
  • 可选性能优化:在循环开始前一次性打开读写文件流,整个循环执行完成后再关闭流,避免频繁开关文件的IO开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:33:26