一个文件就是磁盘上一段命名的存储区。对于linux系统,所有的一切都是文件。一直以来对文件的读写操作总不太熟悉,小结一下。
一般编写c程序时,系统自动为您打开三个文件。这三个文件分别是标准输入,标准输出和标准错误输出,对应的文件描述符分别为0,1,2.系统默认标准输入设备为键盘,标准输出设备为显示器。
写一个常用的计数程序先练练手。
#include<stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int ch; //为什么不用char ch?
int count=0;
FILE *file=NULL;
if((file=fopen(argv[1],"r"))==NULL)
{
printf("open file error\n");
exit(1);
}
while((ch=getc(file))!=EOF)
{
putc(ch,stdout);
count++;
}
fclose(file);
printf("file %s contain %d characteres\n",argv[1],count);
return 0;
}
标准IO
首先介绍fopen()函数。
FILE *fopen(char * path, const char *mode)
其中mode为模式字符串,可以有以下几种形式:
模式字符串 | 意义 |
“r" | 以只读的方式打开一个文件 |
“w" | 打开一个文件,可以写入,如果文件不存在,就创建,存在,则先将文件清0再写入 |
”a" | 打开一个文本文件,向已有文件尾部追加内容,如果文件不存在,先创建 |
“r+" | 打开文本文件,可以读取也可以写入 |
”w+" | 打开文本文件,可以读取和写入,文件存在先将长度清0,不存在先创建 |
“a+" | 打开文本文件,可以读取和写入,向文件末尾追加,文件不存在先创建 |
getc()
int getc(FILE *file)
从文件file中读取一个字符。那么要如何知道文件已经到达文件的结尾了呢,在文件末尾,getc函数会返回一个特殊值EOF,注意,这是针对文本文件而言的。因为我们知道文本文件字符以ASCII码表示,可以是0-127,故不可能为EOF(END OF FILE 是一个宏定义,具体值是-1),,所以可以用于判断文本文件是否结束。
那么如果对于一个二进制文件,我也要判断文件是否读到结尾?其实我之前写的那个程序就可以,因为对于二进制文件,主要是怕字符FF分不清是文件结束符标志还是真的二进制字符,但是如果我声明的是int ch,此时判断文件标示符的EOF就成了0XFFFFFFFF,它就不可能和0x000000FF相等了,这样也就可以了。
但其实c语言还提供了另外一种判断文件是否结束的标志feof()。
int feof(FILE *file)
遇到文件结束,返回非0,否则返回0.
一般常用方式如下:
while(!feof(file))
{
ch=getc(file);
printf("%c",ch);
}
ch=getc(file);
while(!feof(file))
{
printf("%c",ch);
ch=getc(file);
}
两者没有显著区别,但是上一种 确是错误的。会输出一个乱码字符。原因就是在读完最后一个字符后,fp->flag仍然没有被置为_IOEOF,因而feof()仍然没有探测到文件结尾。直到再次调用fgetc()执行读操作,feof()才能探测到文件结尾。这样就多输出了一个-1(即FF)。
但是我们平时可以完全用EOF来代替feof吗?理论上是不可以的,因为getc在出错返回时返回的也是-1,所以尽量还是用feof吧。
文件IO
字符串输入:
字符串输出:
#include<stdio.h>
#include <stdlib.h>
#define MAX 30
int main(int argc,char *argv[])
{
FILE *file=NULL;
if((file=fopen(argv[1],"a+"))==NULL)
{
printf("open file error\n");
exit(1);
}
printf("input some words\n");
char word[MAX];
// while(gets(word)!=NULL&&word[0]!='\0') //用gets时,编译有警告提示,说是gets() is dangerous,please do not use it.查了
//下,网上说gets不能保证输入的大小,如本例设置的word大小为MAX ,为30,结果未定义,用fgets
while(fgets(word,MAX,stdin)!=NULL&&word[0]!='\n') //</span><span style="color:#ff0000;">fgets读取enter,将enter存入word,并加一个'\0',所以要用'\n'判断循环</span><span style="color:#333333;">
{ //</span><span style="color:#ff0000;">是否终止,而gets的话,会扔掉换行符,必须用'\0'判断结束。</span><span style="color:#333333;">
fprintf(file,"%s",word);
}
puts("file content");
rewind(file); //回到文件开头
while(fscanf(file,"%s",word)==1) //每次读取一个word,到达空格就结束
puts(word);
if(fclose(file)!=0)
fprintf(stderr,"error close file\n");
return 0;
}
小结:
#include<stdio.h>
#define LEN 20
int main(int argc,char *argv[])
{
char ch;
FILE *file=NULL;
file=fopen(argv[1],"rb");
fseek(file,0L,SEEK_END);
long count,last;
last=ftell(file);
for(count=1;count<=last;count++)
{
fseek(file,-count,SEEK_END);
ch=getc(file);
putchar(ch);
}
putchar('\n');
fclose(file);
return 0;
}
while((byte=fread(temp,sizeof(char),BUFSIZE,soource))>0)
{
fwrite(temp,sizeof(char),bytes,dest);
}
关键概念:
int ch; //用int来控制EOF
FILE *fp;
fp=fopen("test.txt","r");
while((ch=getc(fp))!=EOF)
{
putchar(ch);
}