C++提取文件中信息的方法

所属分类: 软件编程 / C 语言 阅读数: 87
收藏 0 赞 0 分享

对于文件比较复杂的时候,为了获取文件中的信息,需要一些比较特殊的函数,比如,getline()、replace()、atoi,atof等

例子一,读取以下文件中的数据,并保存进一个类里面。

首先,类的定义如下,感觉是struct,但是按照struct的处理,我这段代码出错了,不知道什么问题,暂时po出来吧,有空看看。

struct ImageLabel{
  std::string imagePath;//save图片路径名
  int faceBox[4];//输入点集的最外层包络矩形rect四个参数
  int landmarkPos[2*LandmarkPointsNum];//输入点集

private:
  friend class cereal::access;
  /**
   * Serialises this class using cereal.
   *
   * @param[in] ar The archive to serialise to (or to serialise from).
   */
  template<class Archive>
  void serialize(Archive& ar)
  {
    ar(imagePath, faceBox, landmarkPos);
  }
};

然后读入一系列如下文件,每个文件的数据保存格式相同,因此定义了一个vector,来顺序存储每一个文件对应的类

文件如下:*.pts文件

version: 1
n_points: 68
{
446.000 91.000
449.459 119.344
450.957 150.614
460.552 176.986
471.486 202.157
488.087 226.842
506.016 246.438
524.662 263.865
553.315 271.435
578.732 266.260
599.361 248.966
615.947 220.651
627.439 197.999
635.375 179.064
642.063 156.371
647.302 124.753
646.518 92.944
470.271 117.870
486.218 109.415
503.097 114.454
519.714 120.090
533.680 127.609
571.937 123.590
585.702 117.155
602.344 109.070
620.077 103.951
633.964 111.236
554.931 145.072
554.589 161.106
554.658 177.570
554.777 194.295
532.717 197.930
543.637 202.841
555.652 205.483
565.441 202.069
576.368 197.061
487.474 136.436
499.184 132.337
513.781 133.589
527.594 143.047
513.422 144.769
499.117 144.737
579.876 140.815
590.901 130.008
605.648 128.376
618.343 132.671
606.771 140.525
593.466 141.419
519.040 229.040
536.292 221.978
}

所有pts文件名都保存在一个TXT文件中,对应的图像名也保存在一个TXT文件中,我们需要把图片的文件路径加文件名保存到类里面,为了处理方便我们用了replace函数,直接替换pts文件名的的后三位,得到新的文件名。

void readpic(std::vector<ImageLabel> &Imagelabels){
   cout<<"test readpic"<<endl;

   string filePath = "/Users/anitafang/Downloads/Datasets/300W/300w/01_Indoor/";
  //打开png图片名存储的TXT文件
  ifstream pngfile;
  pngfile.open("/Users/anitafang/Downloads/Datasets/300W/300w/01_Indoor/pnglist.txt");
    if(!pngfile.is_open()){
    cout<<"不能打开文件!"<<endl;
  }
  //ImageLabel* mImageLabel = NULL;//保存图像信息的类
  string line;//读取文件的每一行
  while(getline(pngfile,line)){
    //mImageLabel = new ImageLabel();
    ImageLabel mImageLabel;
    //mImageLabel->imagePath=filePath+line;//将文件全路径保存在 mImageLabel->imagePath
    mImageLabel.imagePath=filePath+line;//将文件全路径保存在 mImageLabel->imagePath
    cout<<line<<endl;
    //得到pts文件路径
    string ress="pts";
    string ptss=filePath+line.replace(11,3,ress);
    cout<<line.replace(11,3,ress)<<endl;
    cout<<ptss<<endl;
    //读取pts文件里面的数据
    std::ifstream LabelsFile(ptss, std::ios::in);
    if(!LabelsFile.is_open())
      return;
   //开始读取pts文件内容
    int index=0;
    vector<Point2f> vp2f;
    char line11[1024]={0};//存放每行数据
    //将文件逐行读取到string linestr中,然后对行的内容进行判断
    while(LabelsFile.getline(line11, sizeof(line11))){
      //从第四行开始把数据写进landmark数组中
      if((index>=3)&&(index<139)){
        string x = "";
        string y = "";
        std::stringstream word(line11);
        word >> x;
        word >> y;
        cout<<atof(x.c_str())<<" "<<atof(y.c_str())<<endl;
        mImageLabel.landmarkPos[index-3] =atof(x.c_str());
        mImageLabel.landmarkPos[index+LandmarkPointsNum-3] =atof(y.c_str());
        
        vp2f.push_back(Point2f(mImageLabel.landmarkPos[index-3],mImageLabel.landmarkPos[index+LandmarkPointsNum-3]));
        cout<<"x:"<<mImageLabel.landmarkPos[index-3]<<" y:"<<mImageLabel.landmarkPos[index+LandmarkPointsNum-3]<<endl;
        
      }
      index++;
      
    }
    
  
  Rect rect = boundingRect(vp2f);

  //根据得到的矩形 输入到facebox中
  mImageLabel.faceBox[0] = rect.x;
  mImageLabel.faceBox[1] = rect.y;
  mImageLabel.faceBox[2] = rect.width;
  mImageLabel.faceBox[3] = rect.height;
  
  cout<<"facebox"<<mImageLabel.faceBox[0]<<mImageLabel.faceBox[1]<<mImageLabel.faceBox[2]<<mImageLabel.faceBox[3]<<endl;
    
     // close file
  LabelsFile.close();
    //free the object
  Imagelabels.push_back(mImageLabel);

  //mImageLabel == NULL;
    
  }
}

其中,因为GetLine读出来的数据是string类型,因此需要将数据转成int型,看到pts文件中数据是都是float型,因此先要将string转成float,用的是atof函数。

另外如果把 Imagelabels 当做类来处理只需要,最开始,ImageLabel mImageLabel;后面直接push_back,不需要delete。所有的引用都变成:mImageLabel.faceBox,不能用mImageLabel->landmarkPos。 

另外一个升级的例子,处理起来很复杂,这里把ImageLabel当做一个struct来处理,这样需要new,也需要delete,引用的时候也是用的->,这个需要注意。

文件是:labels_ibug_300W.xml

稍微看一部分,了解下它的构成。

<?xml version='1.0' encoding='ISO-8859-1'?>
<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
<name>iBUG face point dataset - All images</name>
<comment>This folder contains data downloaded from:
http://ibug.doc.ic.ac.uk/resources/facial-point-annotations/

The dataset is actually a combination of the AFW, HELEN, iBUG, and LFPW
face landmark datasets. But the iBUG people have aggregated it all together
and gave them a consistent set of 68 landmarks across all the images, thereby
turning it into one big dataset.

Note that we have adjusted the coordinates of the points from the MATLAB convention
of 1 being the first index to 0 being the first index. So the coordinates in this
file are in the normal C 0-indexed coordinate system.

We have also added left right flips (i.e. mirrors) of each image and also
appropriately flipped the landmarks. This doubles the size of the dataset.
Each of the mirrored versions of the images has a filename that ends with
_mirror.jpg.

Finally, note that the bounding boxes are from dlib's default face detector. For the
faces the detector failed to detect, we guessed at what the bounding box would have been
had the detector found it and used that.</comment>
<images>
 <image file='afw/1051618982_1.jpg'>
  <box top='206' left='469' width='216' height='216'>
   <part name='00' x='482' y='267'/>
   <part name='01' x='483' y='298'/>
   <part name='02' x='487' y='329'/>
   <part name='03' x='491' y='358'/>
   <part name='04' x='503' y='386'/>
   <part name='05' x='523' y='409'/>
   <part name='06' x='543' y='428'/>
   <part name='07' x='565' y='442'/>
   <part name='08' x='591' y='447'/>
   <part name='09' x='620' y='443'/>
   <part name='10' x='647' y='429'/>
   <part name='11' x='671' y='409'/>
   <part name='12' x='688' y='385'/>
   <part name='13' x='699' y='359'/>
   <part name='14' x='704' y='332'/>
   <part name='15' x='707' y='305'/>
   <part name='16' x='708' y='277'/>
   <part name='17' x='502' y='250'/>
   <part name='18' x='518' y='237'/>
   <part name='19' x='537' y='234'/>
   <part name='20' x='557' y='236'/>
   <part name='21' x='575' y='243'/>
   <part name='22' x='619' y='243'/>
   <part name='23' x='639' y='237'/>
   <part name='24' x='659' y='234'/>
   <part name='25' x='679' y='238'/>
   <part name='26' x='693' y='250'/>
   <part name='27' x='596' y='268'/>
   <part name='28' x='595' y='287'/>
   <part name='29' x='594' y='305'/>
   <part name='30' x='593' y='324'/>
   <part name='31' x='570' y='336'/>
   <part name='32' x='581' y='338'/>
   <part name='33' x='593' y='342'/>
   <part name='34' x='605' y='338'/>
   <part name='35' x='615' y='336'/>
   <part name='36' x='523' y='272'/>
   <part name='37' x='536' y='263'/>
   <part name='38' x='551' y='263'/>
   <part name='39' x='564' y='277'/>
   <part name='40' x='550' y='277'/>
   <part name='41' x='535' y='276'/>
   <part name='42' x='626' y='279'/>
   <part name='43' x='642' y='265'/>
   <part name='44' x='657' y='267'/>
   <part name='45' x='670' y='276'/>
   <part name='46' x='658' y='280'/>
   <part name='47' x='642' y='279'/>
   <part name='48' x='544' y='364'/>
   <part name='49' x='565' y='360'/>
   <part name='50' x='580' y='357'/>
   <part name='51' x='591' y='360'/>
   <part name='52' x='603' y='358'/>
   <part name='53' x='621' y='361'/>
   <part name='54' x='641' y='366'/>
   <part name='55' x='621' y='382'/>
   <part name='56' x='603' y='385'/>
   <part name='57' x='590' y='384'/>
   <part name='58' x='579' y='383'/>
   <part name='59' x='563' y='378'/>
   <part name='60' x='552' y='366'/>
   <part name='61' x='580' y='370'/>
   <part name='62' x='591' y='370'/>
   <part name='63' x='603' y='371'/>
   <part name='64' x='634' y='369'/>
   <part name='65' x='603' y='371'/>
   <part name='66' x='591' y='370'/>
   <part name='67' x='580' y='370'/>
  </box>
 </image>
 <image file='afw/111076519_1.jpg'>
  <box top='724' left='1122' width='150' height='150'>
   <part name='00' x='1126' y='765'/>
   <part name='01' x='1123' y='784'/>
   <part name='02' x='1123' y='804'/>
   <part name='03' x='1124' y='822'/>
   <part name='04' x='1131' y='839'/>
   <part name='05' x='1142' y='853'/>
   <part name='06' x='1157' y='865'/>
   <part name='07' x='1172' y='874'/>
   <part name='08' x='1190' y='878'/>
   <part name='09' x='1208' y='878'/>
   <part name='10' x='1225' y='873'/>
   <part name='11' x='1238' y='862'/>
   <part name='12' x='1249' y='846'/>
   <part name='13' x='1256' y='829'/>
   <part name='14' x='1261' y='810'/>
   <part name='15' x='1263' y='792'/>
   <part name='16' x='1264' y='774'/>
   <part name='17' x='1148' y='749'/>
   <part name='18' x='1160' y='745'/>
   <part name='19' x='1171' y='744'/>
   <part name='20' x='1183' y='748'/>
   <part name='21' x='1194' y='753'/>
   <part name='22' x='1227' y='756'/>
   <part name='23' x='1236' y='753'/>
   <part name='24' x='1244' y='753'/>
   <part name='25' x='1251' y='754'/>
   <part name='26' x='1256' y='759'/>
   <part name='27' x='1210' y='769'/>
   <part name='28' x='1210' y='779'/>
   <part name='29' x='1210' y='790'/>
   <part name='30' x='1209' y='800'/>
   <part name='31' x='1187' y='808'/>
   <part name='32' x='1196' y='811'/>
   <part name='33' x='1205' y='814'/>
   <part name='34' x='1212' y='813'/>
   <part name='35' x='1218' y='812'/>
   <part name='36' x='1159' y='766'/>
   <part name='37' x='1167' y='763'/>
   <part name='38' x='1176' y='764'/>
   <part name='39' x='1183' y='770'/>
   <part name='40' x='1175' y='770'/>
   <part name='41' x='1166' y='769'/>
   <part name='42' x='1225' y='776'/>
   <part name='43' x='1235' y='773'/>
   <part name='44' x='1243' y='774'/>
   <part name='45' x='1248' y='777'/>
   <part name='46' x='1241' y='779'/>
   <part name='47' x='1233' y='779'/>
   <part name='48' x='1160' y='825'/>
   <part name='49' x='1176' y='820'/>
   <part name='50' x='1190' y='822'/>
   <part name='51' x='1199' y='824'/>
   <part name='52' x='1209' y='825'/>
   <part name='53' x='1221' y='827'/>
   <part name='54' x='1229' y='833'/>
   <part name='55' x='1218' y='847'/>
   <part name='56' x='1205' y='852'/>
   <part name='57' x='1194' y='851'/>
   <part name='58' x='1184' y='849'/>
   <part name='59' x='1171' y='840'/>
   <part name='60' x='1165' y='827'/>
   <part name='61' x='1189' y='828'/>
   <part name='62' x='1199' y='830'/>
   <part name='63' x='1208' y='831'/>
   <part name='64' x='1225' y='834'/>
   <part name='65' x='1206' y='844'/>
   <part name='66' x='1196' y='844'/>
   <part name='67' x='1186' y='841'/>
  </box>
 </image>
 <image file='afw/111076519_2.jpg'>
  <box top='590' left='1028' width='180' height='180'>
   <part name='00' x='1050' y='620'/>
   <part name='01' x='1046' y='641'/>
   <part name='02' x='1040' y='663'/>

可以找到一些规律,按照这些规律来得到我们需要的数据,直接上代码:

void ReadLabelsFromFile(std::vector<ImageLabel> &Imagelabels, std::string Path = "labels_ibug_300W.xml"){
  std::string ParentPath(trainFilePath);
  std::ifstream LabelsFile(ParentPath+Path, std::ios::in);
  if(!LabelsFile.is_open())
    return;
  std::string linestr;
  while(std::getline(LabelsFile, linestr)){
    linestr = trim(linestr);
    linestr = replace(linestr, "</", "");
    linestr = replace(linestr, "/>", "");
    linestr = replace(linestr, "<", "");
    linestr = replace(linestr, ">", "");
    linestr = replace(linestr, "'", "");
 
    std::vector<std::string> strNodes = split(linestr, " ");
    static ImageLabel* mImageLabel = NULL;
    switch (strNodes.size()) {
    case 1:
      if(strNodes[0] == "image"){
        Imagelabels.push_back(*mImageLabel);
        delete mImageLabel;
      }
      break;
    case 2:
      if(strNodes[0] == "image"){
        mImageLabel = new ImageLabel();
        mImageLabel->imagePath = ParentPath + split(strNodes[1], "=")[1];
//        std::cout << mImageLabel->imagePath << std::endl;
//        cv::Mat Image = cv::imread(mImageLabel->imagePath);
//        cv::imshow("Image", Image);
//        cv::waitKey(0);
      }
      break;
    case 5:
      if(strNodes[0] == "box"){
        mImageLabel->faceBox[0] = atoi(split(strNodes[1], "=")[1].data());
        mImageLabel->faceBox[1] = atoi(split(strNodes[2], "=")[1].data());
        mImageLabel->faceBox[2] = atoi(split(strNodes[3], "=")[1].data());
        mImageLabel->faceBox[3] = atoi(split(strNodes[4], "=")[1].data());
      }
      break;
    case 4:
      if(strNodes[0] == "part"){
        int index = atoi(split(strNodes[1], "=")[1].data());
        mImageLabel->landmarkPos[index] = atoi(split(strNodes[2], "=")[1].data());
        mImageLabel->landmarkPos[index+LandmarkPointsNum] = atoi(split(strNodes[3], "=")[1].data());
      }
      break;
    default:
      break;
    }
  }
  LabelsFile.close();
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多