自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
讲给Android程序员看的前端系列教程(图文版)
讲给Android程序员看的前端系列教程(视频版)
Android程序员C语言自学完备手册
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn/lfdfhl
文件与流
在C语言中有三种标准流:
- stdin(standard input stream)标准输入流。在大多数环境中为从键盘输入;scanf( )和getchar( )等函数会从该流中读取字符
- stdout(standard output stream)标准输出流。在大多数环境中为输出至显示器界面。printf( )、puts( )、putchar( )等函数会向该流中写入字符。
- stderr(standard error stream)标准错误流。在大多数环境中为输出至显示器界面。
在C语言中用FILE表示文件类型并提供相应的操作。FILE定义在<stdio.h>头文件中,其具体实现方法因编译器而异,一般以结构体的形式实现。表示标准流的stdin、stdout、stderr都是指向FILE的指针。
文件常见操作
接下来介绍常见的文件操作。
1、打开文件
利用fopen( )打开文件,函数如下:
FILE *fopen( const char *filename, const char *mode );
第一个参数:该参数为字符串类型,表示要打开的文件的名称
第二个参数:该参数为字符串类型,表示打开模式(只读、只写、更新、追加)
fopen( )函数会为要打开的文件创建流并返回一个指向文件对象的FILE*型指针。
2、关闭文件
利用fclose( )打开文件,函数如下:
int fclose( FILE *stream );
输入参数:要关闭的文件的指针
返回值:成功关闭返回0,否则返回EOF
练习:文件的打开与关闭
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp=fopen("D:\\test.txt","r");
if(fp==NULL){
puts("文件打开失败");
}else{
puts("成功打开文件");
}
int result=fclose(fp);
if(result==0){
puts("成功关闭文件");
}else{
puts("文件关闭失败");
}
return 0;
}
结果如下:
成功打开文件
成功关闭文件
3、从文件中读取数据
利用fscanf( )从文件中读取数据,函数如下:
int fscanf( FILE *stream, const char *format, ... );
与scanf( )函数比起来,fscanf( )函数多了一个输入参数即FILE *stream;它表示从哪个文件读取数据。除此以外,它与scanf( )函数完全相同。例如,要从fp中读取十进制整数值并保存是x,代码如下:
fscanf(fp,"%d",&x);
练习:从文件读取学生的成绩并计算各科平均成绩
在D盘根目录下准备成绩文件score.txt
内容如下:
小明 70 84
小王 80 90
小坤 90 90
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int number=0;
char name[20];
int chinese;
int math;
int chinese_sum=0;
int math_sum=0;
FILE *fp=fopen("D:\\score.txt","r");
if(fp!=NULL){
puts("开始读取数据");
while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){
printf("%s %d %d\n",name,chinese,math);
number++;
chinese_sum=chinese_sum+chinese;
math_sum=math_sum+math;
}
puts("-------------");
printf("平均 %d %d\n",chinese_sum/number,math_sum/number);
}else{
puts("文件打开失败");
}
int result=fclose(fp);
if(result==0){
puts("成功关闭文件");
}else{
puts("文件关闭失败");
}
return 0;
}
核心代码就一行:
while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){ }
在此,利用fscanf( )函数读取score.txt中的每一行数据并将学生名字存入变量name,语文成绩存入chinese,数学成绩存入math;fscanf( )函数的返回值为读取到的数据个数。其余的代码不再解释,也可以参照之前关于scanf( )函数的介绍。
结果如下:
开始读取数据
小明 70 84
小王 80 90
小坤 90 90
-------------
平均 80 88
成功关闭文件
4、向文件中写入数据
利用fprintf( )向文件中写入数据,函数如下:
int fprintf( FILE *stream, const char *format, ... );
fprintf( )函数的使用也很简单,与printf( )函数比起来它多了一个输入参数即FILE *stream;它表示向哪个文件写入数据。除此以外,它与printf( )函数完全相同。例如,要向fp中写入十进制整数值,代码如下:
fprint(fp,"%d",x);
练习:向文件中写入当前时间
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
FILE *fp;
time_t currentTime = time(NULL);
struct tm *timeStruct = localtime(¤tTime);
if ((fp = fopen("D:\\time.txt", "w"))!= NULL){
puts("将当前日期和时间保存至文件");
int year=timeStruct->tm_year + 1900;
int month=timeStruct->tm_mon + 1;
int day=timeStruct->tm_mday;
int hour=timeStruct->tm_hour;
int minute=timeStruct->tm_min;
int second=timeStruct->tm_sec;
fprintf(fp,"%d %d %d %d %d %d\n",year,month,day,hour,minute,second);
fclose(fp);
}
return 0;
}
要点概述:
- include包含了与时间相关的头文件<time.h>
- 利用time( )函数得到系统的日历时间(Calendar Time)
- 利用localtime( )得到本地时间;该方法的返回值是struct tm类型的指针
- 从timeStruct中分别获取年月日时分秒
- 利用fprintf( )将年月日时分秒保存至文件
5、scanf( )、fscanf( )、printf( )、fprintf( )小结
在本文开头,我们提到:标准流的stdin、stdout、stderr都是指向FILE的指针。也就是说:这三者都可以直接传递给fscanf( )、fprintf( )函数的第一个参数。因此可知,以下两组代码的功能是相同的。
scanf("%d",&x);
fscanf(stdin,"%d",&x);
printf("%d",x);
fprintf(stdout,"%d",x);
也就是说:
scanf( )是输入源被限定为标准输入流的fscanf( )
printf( )是输出目标被限定为标准输出流的fprintf( )
6、fgetc( )和fputc( )
之前我们利用putchar( )和getchar( )将键盘输入的文字显示到控制台
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
while((ch=getchar())!=EOF){
putchar(ch);
}
return 0;
}
在该示例中是从键盘读入数据,输出到控制台。
在此,介绍两个非常类似的函数。
首先来看fgetc( ):
int fgetc( FILE *stream );
该函数用于从文件中读取一个字符并将其转为int型作为函数的返回值。
接着来看fputc( ):
int fputc( int ch, FILE *stream );
该函数用于向文件中写入一个字符。
练习:将文件内容显示至控制台
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
FILE *fp;
char fileName[FILENAME_MAX];
printf("请输入文件路径:");
scanf("%s",fileName);
if((fp=fopen(fileName,"r"))==NULL){
puts("文件打开失败");
}else{
while((ch=fgetc(fp))!=EOF){
putchar(ch);
}
fclose(fp);
}
return 0;
}
核心代码:
利用fgetc( )从文件中读取数据,利用putchar( )将数据显示至控制台
结果如下:
请输入文件路径:d:\\score.txt
小明 70 84
小王 80 90
小坤 90 90
练习:文件的复制
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
FILE *sfp;
FILE *dfp;
char sName[FILENAME_MAX];
char dName[FILENAME_MAX];
printf("请输入源文件路径:");
scanf("%s",sName);
printf("请输入目标文件路径:");
scanf("%s",dName);
if((sfp=fopen(sName,"r"))==NULL){
puts("源文件打开失败");
}else{
if((dfp=fopen(dName,"w"))==NULL){
puts("目标文件打开失败");
}else{
while((ch=fgetc(sfp))!=EOF){
fputc(ch,dfp);
}
fclose(dfp);
fclose(sfp);
}
}
return 0;
}
核心代码:
利用fgetc( )从源文件sName中读取数据,利用fputc( )将数据写至目标文件dName。假若dName不存在,则会先创建该文件再进行文件的拷贝;这点和Java中的FileOutputStream是非常类似的。
结果如下:
请输入源文件路径:d:\\score.txt
请输入目标文件路径:d:\\copy.txt
7、fgets( )和fputs( )
与fgetc( )和fputc( )类似,可采用fgets( )和fputs( )从文件中读出或者写入字符串。
先来看fputs( ):
int fputs( const char *str, FILE *stream );
将str指向的字符串写入stream指向的文件流,成功返回非负数;反之EOF。请注意:该函数输入完成后不会增加额外的特殊字符(如换行符等)
示例如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("D:\\test.txt", "w");
fputs("hello c programming\n", fp);
fputs("hello c++ programming\n", fp);
fclose(fp);
puts("已将字符串写入文件");
return 0;
}
结果如下:
已将字符串写入文件
再来看fgets( ):
char *fgets( char *str, int count, FILE *stream );
该函数从文件指针stream指向的文件内读取字符串并保存到指针str所指向的内存空间中,直至已读size-1个字符或出现换行符或文件末尾时为止;当读取错误或者读到文件末尾EOF返回NULL。请注意:该函数会读取最后的换行符’\n’
示例如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[300];
FILE *fp= fopen("D:\\test.txt", "r");
//读取第一行的内容
char *strLine1=fgets(str, 200, fp);
printf("%s",strLine1);
//读取第二行的内容
char *strLine2=fgets(str, 200, fp);
printf("%s",strLine2);
fclose(fp);
return 0;
}
结果如下:
hello c programming
hello c++ programming
刚才我们事先知道D:\test.txt文件中有两行文字,所以连续两次调用fgets( )读取数据。但是,很多时候我们事先是不可能知道的文件的内容;所以,代码需要优化:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[300];
FILE *fp= fopen("D:\\test.txt", "r");
char *stringLine;
while((stringLine=fgets(str, 200, fp))!=NULL){
printf("%s",stringLine);
}
fclose(fp);
return 0;
}
8、fread( )和fwrite( )
虽然可使用函数 fprintf ( )和 fscanf( ) 从磁盘文件中读写任何类型的文件,但是效率并不高。所以,我们可采用fread( )和fwrite( )按照二进制的形式对文件进行读写操作。
原型如下:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
两个函数输入参数的个数和类型一致,概述如下:
- 第一个参数:指向读写数据首地址的指针。
- 第二个参数:要操作的单个数据的大小。例如,int型数据的大小就是sizeof(int)
- 第三个参数:数据个数
- 第四个参数:文件指针
练习:利用fread( )和fwrite( )读写基本类型数据
代码如下(写):
#include <stdio.h>
#include <stdlib.h>
//利用fwrite()写数据
int main()
{
FILE * fp;
int buffer[] = {9, 5, 2, 7};
if((fp = fopen ("D:\\number.txt", "wb"))!=NULL){
fwrite (buffer, sizeof(int), 4, fp);
fclose (fp);
}
puts("已将数据按照二进制的形式存入文件");
return 0;
}
结果如下(写):
已将数据按照二进制的形式存入文件
代码如下(读):
#include <stdio.h>
#include <stdlib.h>
//利用fread()读数据
int main()
{
int i;
FILE * fp;
int buffer[4];
if((fp = fopen ("D:\\number.txt", "rb"))!=NULL){
fread(buffer, sizeof(int), 4, fp);
fclose (fp);
}
for(i=0;i<4;i++){
printf("%d ",buffer[i]);
}
return 0;
}
结果如下(读):
9 5 2 7
练习:利用fread( )和fwrite( )读写结构体
代码如下(写):
#include <stdio.h>
#include <stdlib.h>
//利用fwrite()写数据
typedef struct{
int age;
char name[20];
}Student;
int main()
{
int i;
FILE * fp;
Student stu1={18,"zxx"};
Student stu2={19,"hmm"};
Student stu3={29,"lqn"};
Student studentArray[3]={stu1,stu2,stu3};
if((fp = fopen ("D:\\student.txt", "wb"))!=NULL){
for(i=0;i<3;i++){
fwrite(&studentArray[i],sizeof(Student),1,fp);
}
puts("已将结构体类型数据按照二进制的形式存入文件");
fclose (fp);
}
return 0;
}
结果如下(写):
已将结构体类型数据按照二进制的形式存入文件
代码如下(读):
#include <stdio.h>
#include <stdlib.h>
//利用fread()读数据
typedef struct{
int age;
char name[20];
}Student;
int main()
{
FILE *fp;
Student stu;
if((fp = fopen ("D:\\student.txt", "rb"))!=NULL){
while((fread(&stu,sizeof(Student),1,fp))==1){
printf("%d %s\n",stu.age,stu.name);
}
fclose(fp);
}
return 0;
}
结果如下(读):
18 zxx
19 hmm
29 lqn
9、fread( )和fwrite( )使用小结
- 打开文件的模式为“rb”或者“wb”表示按照二进制读或者按照二进制写
- 按照二进制方式将数据存入硬盘中文件,我们打开该文件后是无法读懂的
- 每次读或写数据后指针都会指向下一个待写或者待读数据的位置
- 在利用fread( )和fwrite( )读写完数据后需调用fclose( )方法关闭流
更多推荐
C语言自学完备手册(32)——文件
发布评论