C 文件读写

Posted 三季人 G

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C 文件读写相关的知识,希望对你有一定的参考价值。

C 文件读写

本章我们将介绍 C 程序员如何创建、打开、关闭文本文件或二进制文件。

一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节。C 语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。本章将讲解文件管理的重要调用。

打开文件

您可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。下面是这个函数调用的原型:

FILE *fopen( const char *filename, const char *mode );

在这里,filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:

模式描述
r打开一个已有的文本文件,允许读取文件。
w打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。
a打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。
r+打开一个文本文件,允许读写文件。
w+打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
a+打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

关闭文件

为了关闭文件,请使用 fclose( ) 函数。函数的原型如下:

 int fclose( FILE *fp );

如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。

C 标准库提供了各种函数来按字符或者以固定长度字符串的形式读写文件。

读取文件

下面是从文件读取单个字符的最简单的函数:

int fgetc( FILE * fp );

函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。

如果这个函数在读取最后一个字符之前就遇到一个换行符 ‘\\n’ 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。您也可以使用 int fscanf(FILE *fp, const char *format, …) 函数来从文件中读取字符串,但是在遇到第一个空格和换行符时,它会停止读取。
举例:

#include <stdio.h>
 
int main()

   FILE *fp = NULL;
   char buff[255];
 
   fp = fopen("/tmp/test.txt", "r");
   fscanf(fp, "%s", buff);
   printf("1: %s\\n", buff );
 
   fgets(buff, 255, (FILE*)fp);
   printf("2: %s\\n", buff );
   
   fgets(buff, 255, (FILE*)fp);
   printf("3: %s\\n", buff );
   fclose(fp);
 

写入文件

下面是把字符写入到流中的最简单的函数:

int fputc( int c, FILE *fp );

数据类型转换

一般默认从文件中读取的是字符格式或者字符串格式的数据,如果是数字要转化为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++;

C语言 文件的读写

引入

OS操作系统

打开文件fopen()函数

读写模式:
r:读取已有文件
w:文件不存在,创建文件并写入文件.文件存在,内容清零,再写入文件
a: 文件不存在,创建文件并写入文件.文件存在,以追加的形式写入文件

r+:读写已有文件
w+:文件不存在,创建文件并读写文件.文件存在,内容清零,再读写文件
a+:文件不存在,创建文件并读写文件.文件存在,以追加的形式写文件,从头开始读文件

总结:
1)
r,r+已有文件
w,w+,a,a+:已有文件+创建文件
2)如果是二进制文件,要在后面加一个b
3)以w,w+模式会将文件清空

关闭文件fclose()函数

关闭成功,返回0
关闭失败,返回EOF
总结:
1)
EOF:C标准函数库中表示文件结束符(end of file)
在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。
2)如果不关闭文件,我们的内容就没有保存在文件中

写入文件的函数

输出流

fputc()写入一个字符,成功:返回写入的字符,失败:返回EOF
fputs()写入一个字符串,成功:返回一个非负值,失败:EOF
fprintf()写入一个字符串, 成功:返回写入的字符的个数,失败:返回负数


案例
库变量:
FILE:一个适合存储文件流信息的对象类型

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//写入文件--fputc(),fputs(),fprintf()
int main()
{
	printf("1.创建文件空指针\\n");
	FILE *fp=NULL;
	printf("2.创建一个文件\\n");
	/*d:/
	与平时的转义字符\\相反
	*/
	fp=fopen("d:/AAADQLearning/test_file.txt","a");
	//w写入文件,存在,清零;不存在,创建
	//a写入文件,存在,追加;不存在,创建

	printf("3.fputc写入一个字符a\\n");
	char rc=fputc('m',fp);//成功,返回写入的字符,失败,返回EOF
	fputc('\\n',fp);

	printf("4.fputs写入一个字符串\\n");
	int rs=fputs("dq,as a result\\n",fp);//成功,返回0,失败返回EOF

	printf("5.fprintf写入一个字符串\\n");
	int rf=fprintf(fp,"as good as\\n");//成功,返回传入的字符个数;失败,返回负数

	printf("rc=%c rs=%d rf=%d\\n",rc,rs,rf);//m 0 11

	printf("写入完成!\\n");
	printf("关闭文件指针\\n");
	fclose(fp);

	getchar();
	return 0;
}

读取文件的函数

fgetc()读取一个字符,成功,返回读取的字符,失败,返回EOF
fgets()读取n-1字符串, 成功时返回字符串地址,错误或0读入时返回NULL
fscanf()读取字符串, 成功,返回正确读入项目(items)的个数,错误时返回EOF
总结:
1)
fgets()读取n-1个字符,把字符串复制给缓冲区,在末尾追加一个null
fscanf()读取时遇到空格符会停止读取,直接返回目前读到的结果


案例
1)案例1

2)案例2

读取文件代码
代码1

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//读取文件--fgetc(),fgets(),fscanf()
//输入流
int main()
{
	//创建文件指针
	FILE *fp=NULL;
	fp=fopen("D:/AAADQLearning/test_file.txt","r+");//r:读取已有文件r+读写已有文件

	char buff[1024];//使用缓冲区装读取到的字符
	char rc=fgetc(fp);
	char *rs=fgets(buff,sizeof(buff),fp);//读取1024个字符,字符串一行一行地读取

	char *temp="";
	int rf=fscanf(fp,temp);//fscanf()遇到换行符了,所以什么也没读取到就返回了
	strcat(buff,temp);
	/*
	fgetc()成功:返回读取到的字符,失败,返回EOF
	fgets()成功:返回读取到的字符串(地址),失败,返回NULL
	fscanf()成功,返回成功读取的个数,失败,返回EOF
	*/
	printf("rc=%c rs=%s rf=%d\\n",rc,rs,rf);
	printf("读取的内容:\\nbuff=%s\\n",buff);

	fclose(fp);//关闭文件指针
	printf("读取完成!\\n");

	getchar();
	return 0;
}

代码2

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//循环读取文件--fgetc(),fgets(),fscanf()
//输入流
int main()
{
	//创建文件指针
	FILE *fp=NULL;
	fp=fopen("D:/AAADQLearning/test_file.txt","r+");//r:读取已有文件r+读写已有文件

	char buff1[1024];//使用缓冲区装读取到的字符
	char buff2[1024];
	//使用fgets()循环一行行地读取文件
	printf("fgets():\\n");
	while(fgets(buff1,1024,fp)!=NULL)//只有这样才行
	{
		//输出缓冲区中的内容
		printf("%s",buff1);
	}

	//使用fscanf()循环一行行地读取文件
	printf("fscanf():\\n");
	//fscanf()遇到空格和换行时结束
	//所以fscanf(fp,"%s",buff2)!=EOF
	//表示遇到空格符或换行时,结束这一个循环,直接进行下一个循环,从没有空格和换行符的地方读取
	//最终输出:没有空格与换行,直接输出一行很长的字符串
	while(fscanf(fp,"%s",buff2)!=EOF)
	{
		printf("%s",buff2);
	}

	//使用fgetc()循环地读取文件
	printf("fgetc():\\n");
	//fgetc()会一个字符一个字符地输出,最终输出所有内容
	while(fgetc(fp)!=EOF)
	{
		printf("%c",fgetc(fp));
	}
	fclose(fp);//关闭文件指针
	printf("读取完成!\\n");

	getchar();
	return 0;
}

读写文件综合代码

#include<stdio.h>
#include<stdlib.h>
//文件--读写文件综合
const int size=100;
int main()
{
	//写文件--输出流
	FILE *fpw=NULL;
	fpw=fopen("D:/AAADQLearning/test_write.txt","a+");//写文件
	int i;
	for(i=0;i<100;i++)
	{
		fprintf(fpw,"arr[%d]\\n",i);
	}
	
	printf("完成写入!\\n");

	//读文件--输入流
	FILE*fpr=NULL;
	fpr=fopen("D:/AAADQLearning/test_file.txt","r+");//读文件

	char buff[1024];
	while(fgets(buff,1024,fpr)!=NULL)
	{
		//把读取到的文件内容追加到test_write.txt文件中
		//输出流
		fputs(buff,fpw);
	}
	printf("读取并写入文件完成!\\n");
	//关闭文件指针
	fclose(fpr);
	fclose(fpw);
	getchar();
	return 0;
}

补充

1.文件相关的函数使用时返回的结果

fgetc():成功时返回读入的字节数。错误或文件尾时返回EOF;
fputc():成功时返回写入的字节数。错误时返回EOF;
fgets():成功时返回字符串地址,错误或0读入时返回NULL;
fputs():成功时返回一个非负整数,错误时返回EOF
fprintf():成功时返回写入的字节数,错误时返回负数(negative value)
fscanf():返回正确读入项目(items)的个数,错误时返回EOF
fwrite():返回正确写入项目的个数,错误时返回0
fread():返回正确读入项目的个数,错误时返回0
fseek():成功返回0,错误返回-1。

以上是关于C 文件读写的主要内容,如果未能解决你的问题,请参考以下文章

C语言的fopen函数(文件操作/读写)

R语言读写excel文件

QT读写文件的问题

R语言读写excel文件2021.2.24

用C语言实现文件读写操作

MFC怎么读写EXCEL文件