步骤1:包含头文件 #include < fstream >
包括:1)ofstream : 写文件 (2)ifstream : 读文件 (3)fsream : 读写文件
如:
- ifstream fin;
- ofstream fout;
打开文件 fin.open ("文件路径" ,打开方式)
打开方式包括:
如:
fin.open("/home/bing/slambook14/slambook/ch2/test1.txt",ios::in);
- fout << x << " " << y << endl;
- fout.close();
为了保持健壮性,读文件要有验证代码:
- if(!fin.is_open())
- {
- std::cerr<<"cannot open the file"
- }
- //或者
- if(!fin)
- {
- std::cerr<<"cannot open the file";
- }
第一种读的方式(按元素直接读):
- //申请读空间:
- char buf[1024]={0}; 就是临时申请一个 1024大的读空间(又叫buffer),并且初始化为0。
- while (fin >> buf)
- {
- cout << buf << endl;//每一次的buf是空格或回车键(即白色字符)分开的元素
- }
- 文件:
- 1 2 3
- a b c
- 112
- geya
- 读取结果:
- 1
- 2
- 3
- a
- b
- c
- 112
- geya
第二种读的方式(使用getline按行读):
默认读取数据时,它会传递并忽略任何白色字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。
为了解决这个问题,可以使用一个叫做 getline 的 C++ 函数。此函数可读取整行白色字符,只看换行符,即不看,包括前导和嵌入的空格,并将其存储在字符串对象中。
getline:
getline()函数是istream类中的一个成员函数,所以在使用它时,速妖使用istream的对象cin来调用它。getline (char* s, streamsize n ),作用是从istream中读取至多n个字符保存在s对应的数组中。即使还没读够n个字符,如果遇到换行符'\n'则读取终止
- char buf[1021]={0};
- while(fin.getline(buf,sizeof(buf)))
-
- {
- std::cout<<buf<<std::endl;
-
- }
- 文件:
- 1 2 3
- a b c
- 112
- geya
- 读取结果:
- 1 2 3
- a b c
- 112
- geya
第三种读的方式(get):
- char c;
- while ((c = fin.get()) != EOF)
- {
- std::cout << c;
- }
- 文件:
- 1 2 3
- a b c
- 112
- geya
- 读取结果:
- 1 2 3
- a b c
- 112
- geya
第四种读的方式:
若已知文件里头数据的顺序,则直接定义字符变量存储单个元素,以白色字符为分割
- char a,s1,s2,s3,s4,s5;
- std::string s6;
- fin >> a >> s1 >> s2 >> s3>>s4>>s5>>s6;
- std::cout<<a<<" "<<s1<<" "<<s2<<" "<<s3<<" "<<s4<<" "<<s5<<" "<<s6;
- 文件:
- 1 2 3
- a b c
- 112
- geya
- 读取结果:
- 1 2 3 a b c 112
一般默认从文件中读取的是字符格式或者字符串格式的数据,如果是数字要转化为float等格式怎么办呢?
方法一:直接定义负责接受的变量数据类型,按行分后再按单词分
下面这个例子就是实际应用中经常用到的例子,比如一个人有多个手机号:
一行代表一个人的信息,以行为单位存储信息:
- #include "libHelloSLAM.h"
- #include<iostream>
- #include<fstream>
- #include<string>
- #include<vector>
- #include <sstream>
- struct people{
- std::string name;
- std::vector<int> phonenum;
- };
- int main( int argc, char** argv )
- {
- std::ifstream fin;
- fin.open("/home/bing/slambook14/slambook/ch2/test.txt",std::ios::in);
- if(!fin.is_open())
- {
- std::cerr<<"cannot open the file";
-
- }
- char line[1024]={0};
- std::vector<people> People;
- //从文件中提取“行”
- while(fin.getline(line,sizeof(line)))
- {
- //定义局部变量
- people p;
- //从“行”中提取“单词”
- std::stringstream word(line);
- word>>p.name ;
- int num;
- while(word>>num)
- p.phonenum.push_back(num);
- People.push_back(p);
- }
- std::cout<<People[1].name<<"'s phonenumber is:"<< People[1].phonenum[1];
-
- }
- 文件:
- gyb 1333 12212
- lck 212 33113
- ddl 332 41311
-
- 输出:
- lck's phonenumber is:33113
反正最重要的是以下两个:
//从文件中提取“行”
fin.getline(line,sizeof(line))
//从“行”中提取“单词”
std::stringstream word(line);
这里用到了stringstream,需要包含
如:
- #include <string>
- #include <sstream>
- #include <iostream>
- #include <stdio.h>
- using namespace std;
- int main()
- {
- stringstream sstream;
- string strResult;
- int nValue = 1000;
-
- // 将int类型的值放入输入流中
- sstream << nValue;
- // 从sstream中抽取前面插入的int类型的值,赋给string类型
- sstream >> strResult;
- cout << "[cout]strResult is: " << strResult << endl;
- printf("[printf]strResult is: %s\n", strResult.c_str());
- //这里的 str() 方法是将 stringstream 类型转换为 string 类型
- return 0;
- }
1、stringstream其实和ostringstream一样可以看错一个内存,起到暂时存储的作用 其实还有个tringsteam可以读写,待深入研究;
2、一般流的读写用<< 和>> ,而不用=
如读:word>>p.name ;把word中的东西读到p.name中
写:cin>>word
3、读写操作可以作为条件使用,若没东西可以读写了,则返回-1
如:
while(word>>num){}
**********************************************************************
补充看到的orbslam中的读取文件的代码
- void LoadImages(const string &strPathToSequence, vector<string> &vstrImageFilenames, vector<double> &vTimestamps)
- {
- // step 1 读取时间戳文件
- ifstream fTimes;
- string strPathTimeFile = strPathToSequence + "/times.txt";
- fTimes.open(strPathTimeFile.c_str());
- while(!fTimes.eof())
- {
- string s;
- getline(fTimes,s);
- // 当该行不为空的时候执行
- if(!s.empty())
- {
- stringstream ss;
- ss << s;
- double t;
- ss >> t;
- // 保存时间戳
- vTimestamps.push_back(t);
- }
-
- string strPrefixLeft = strPathToSequence + "/image_0/";
- const int nTimes = vTimestamps.size();
- vstrImageFilenames.resize(nTimes);
-
- for(int i=0; i<nTimes; i++)
- {
- stringstream ss;
- ss << setfill('0') << setw(6) << i;
- vstrImageFilenames[i] = strPrefixLeft + ss.str() + ".png";
- }
**********************************************************************
最好把文件名用全局变量定义出来
string filename=“./test.txt"
**********************************************************************
- //多文件,按文件名顺序读写
- //使用boost::format进行字符串的格式化
- boost::format fmt("./%s/%d.%s");
- for(int i =0 ;i<5;i++)
- cv::imread((fmt%"color"%(i+1)%"png").str())
*****************************************************************************
读特定列:
- int main()
- {
- ifstream ff1;
- ff1.open("/home/bing/ORB/ORB_SLAM2/LiGT/LiGT_results.txt");
- char line[1024] = {0};
-
- if(!ff1.is_open()) cerr<<"can not open";
-
- float globalt[1000][3];
- int ii=0;
- while(ff1.getline(line,sizeof(line)))
- {
-
- std::stringstream word(line);
- for(int qq=0;qq<12;qq++)
- {
- float tamp;
- word>>tamp;
- // cout<< tamp<< " "<<qq<<endl;
- if (qq == 9) globalt[ii][0] = tamp;
- if (qq == 10)globalt[ii][1] = tamp;
- if (qq == 11)globalt[ii][2]= tamp;
- }
- ii++;
- }
*****************************************************************************
有些参数太多,改起来又要重新编译,所以最好用超参数定义在外部txt文件中,其定义和读取举例如下:
- using namespace std;
- using namespace cv;
- bool config::GetFile(const string &filename)
- {
- if (config_ == NULL)
- config_ = std::shared_ptr<config>(new config);
- else
- config_->file_ = FileStorage(filename.c_str(), FileStorage::READ);
-
- if(config_->file_.isOpened() == false)
- {
- cerr<<"con not open";
- return false;
- }
- return true;
-
- }
- static T GetParameter(const string &key)
- {
- return T(config_->file_[key]);
-
- }
-
-
- dataset_ = Dataset::Ptr(new Dataset(Config::Get<std::string>("dataset_dir")));
************************************************************************8
- ifstream fin(dataset_path_ + "/calib.txt");
- if (!fin) {
- LOG(ERROR) << "cannot find " << dataset_path_ << "/calib.txt!";
- return false;
- }
-
- for (int i = 0; i < 4; ++i){ //一共有P0,P1,P2,P3四个相机,这里就是要把四个相机的参数全部读取到
- //前三个字符是P0:所以这里定义了一个长度为3的字符数组,读完这三个字符后就遇到了第一个空格,fin将会跳过这个空格,读取参数
- char camera_name[3];
- for (int k = 0; k < 3; ++k) {
- fin >> camera_name[k];
- }
-
- //将相机后面对应的12个参数读入到projection_data[12]中
- double projection_data[12];
- for (int k = 0; k < 12; ++k) {
- fin >> projection_data[k];
- }