读取一般 的文本数据时,采用 fgetc、getline、fscanf,根据指定的字符串类型、整型或实型数据格式读取即可,三种方法使用如下:
一、fgets方法
- 从文件读取单个字符
int fgetc(FILE *stream);
从指定的流 stream获取下一个字符(一个无符号字符),并把位置标识符往前移动。
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流。
返回值: 该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。 - 从流中读取一个字符串
char *fgets( char *buf, int n, FILE *fp );
函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
如果这个函数在读取最后一个字符之前就遇到一个换行符 ‘\n’ 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。您也可以使用 int
fscanf(FILE *fp, const char *format, …)
函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取。
- 实例:
#include <stdio.h> int main() { FILE *fp; int c; int n = 0; fp = fopen("file.txt", "r"); if (fp == NULL) { perror("打开文件时发生错误"); return(-1); } do { c = fgetc(fp);//从文本中读取一个字符并以int的形式返回 if (feof(fp))//到达文件结尾 { break; } printf("%c", c); } while (1); fclose(fp); return(0); }
假设我们有一个文本文件 file.txt,它的内容如下。文件将作为实例中的输入:
We are in 2019
编译并运行上面的程序,这将产生以下结果:
We are in 2019
二、getline方法
getline为c++中的函数,C语言里面是没有的。
对此函数有两种使用方法,只是参数不同而已。
- 指定将n个字符写入s(包括终止空字符)。
getline(char * s,streamsize n);
这里的 定界字符是换行字符(’\n’),使用示例如下:
#include <iostream> #include<fstream> using namespace std; int main(){ char name[]="test.txt"; fstream fs(name,ios::in); char str[25]; if(fs.is_open()){ while(!fs.eof()){ fs.getline(str,25); cout<<str<<endl; } } return 0; }
- 直到提取的字符为分隔字符delim,或者已将n个字符写入s(包括终止空字符)
getline(istream &, string &, char del);
第一个参数打开的流,第二个参数保存读入的内容,第三个参数字段的分割副,默认是 ‘\n’
直接看代码理解:
#include <iostream> #include <string> #include <fstream> using namespace std; /** 读文件 */ int main(int argc,char **argv) { filebuf fb; string filename = "test.txt"; if(fb.open(filename.c_str(),ios::in) == NULL) { cout << "error" << endl; } istream is(&fb); string input; while(getline(is,input,'\n')) { cout << input.substr(pos1+1) << endl; } fb.close(); return 0; }
三、fscanf方法
这里我直接采用C语言中文网的解释来说明了。网址:http://c.biancheng.net/view/2073.html
这两个函数的原型为:
int fscanf ( FILE *fp, char * format, ... );
int fprintf ( FILE *fp, char * format, ... );
fp 为文件指针,format 为格式控制字符串,… 表示参数列表。与 scanf() 和 printf() 相比,它们仅仅多了一个 fp 参数。例如:
FILE *fp;
int i, j;
char *str, ch;
fscanf(fp, "%d %s", &i, str);
fprintf(fp,"%d %c", j, ch);
fprintf() 返回成功写入的字符的个数,失败则返回负数。fscanf() 返回参数列表中被成功赋值的参数个数。
以上就是三种方法的简单总结,但是对于一般文本,需要指定读取“row ”后面的单个数据时,我们不知道数据的行列位置,此时按行读取和单个字符读取就很麻烦。那么重点来了!!!
以DEM数据的TXT格式为例,数据在TXT中存储为:
ncols 562
nrows 401
xllcorner 0
yllcorner 0
cellsize 5
NODATA_value -9999
-11123 -11123 -11123 -11123 -11123。。。。。。。
如果此时我只需要知道NODATA_value 的值和第一个数据的值,就需要有筛选的读取了。
很简单,还是采用fscanf的方法,不过需要稍作变化,把指定文本NODATA_value也加进去,直接看代码(因为编译器版本不支持fscanf,这里改为fscanf_s):
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
float nodata_value = 0.0;
void main()
{
char demfilename[30] = "E:\\***\\DEMdata.txt";
FILE *demfile;
int fileOK = 0;
double firstdata=0.0;
fileOK = fopen_s(&demfile, demfilename, "r");
if (fileOK != 0)//文件打开失败
{
cout << "DEM文件打开失败!\n" << endl;
exit(1);//退出程序
}
fscanf_s(demfile, "NODATA_value %f\n", &nodata_value);
fscanf_s(demfile, "%f", &firstdata);
cout << setw(13) << "NODATA_value" << setw(7) << nodata_value << endl;
cout << "第一个数据:" << firstdata << "\n";
}
代码运行效果如图:
如果需要把整个TXT文件全部读取的话,以读取NODATA_value的方法来读取前面6行字符和数据,后面的点云数据选择以上三种文件读取方法中的任意一种就可以啦。
需要完整点云读取代码也可私聊。