欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

文件I/O流

程序员文章站 2024-03-04 20:31:06
...

对于每一个ANSI C程序而言,至少打开三个流:标准输入(stdin)、标准输出(stdout)、标准错误(stderr),他们都是一个指向FILE结构的指针。

标准输入为:键盘设备 
标准输出为:终端或屏幕。

标准库I/O一般情况:

1. 程序必须为同时处于活动状态的每个文件声明一个指针变量,其类型为: FILE* ,这个指针指向一个结构,当它处于活动状态时由流使用。

2. 流通过fopen函数打开,打开流的时候,必须指定需要访问的文件或者设备已经访问的方式。fopen函数和操作系统去验证文件或者设备确实存在,验证访问方式,然后初始化FILE结构

3.根据需要对文件进行读取和写入。

4.最后,fclose函数可以关闭流。关闭一个流可以防止与它相关的文件被再次访问,保证任何存储于缓冲区中的数据被正确的写入文件中。

文件I/O流

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

1> r 只读 ,文件必须已存在

2> w 只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节再重新写,也就是替换掉原来的文件内容

3> a 只能在文件末尾追加数据,如果文件不存在则创建

4> r+ 允许读和写,文件必须已存在

5> w+ 允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写

6> a+ 允许读和追加数据,如果文件不存在则创建

使用fopen打开文件时如果出错,fopen将返回NULL并设置errno,必须对此进行处理:

if (fp == NULL) {
         perror("fopen");
         exit(1);
}

2.int fclose ( FILE * stream );//需与fopen配套使用(打开流一定要关闭)

字符I/O:

3.int getc ( FILE * stream ); 

4.int putc ( int character, FILE * stream );

int main()
{
	FILE *fp = fopen("log.txt", "wt");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	//int i = 0;                                //将hello czf!写入log.txt
	//while (i++ < 10)
	//{
	//	fputs("hello czf!\n", fp);
	//} 

	//int ch;                                   //计算文件中的!
	//size_t count = 0;
	//do{
	//	ch = getc(fp);
	//	if ('!' == ch)
	//	{
	//		printf("%c : %d\n",ch, count);
	//	}
	//	count++;
	//} while (ch != EOF);
	//printf("end = %d\n", ch);

	int ch = 'A';

	while (ch <= 'Z')                              //将A-Z逐个写入fp
	{
		putc(ch, fp);
		putc('\n', fp);
		ch++;
	}

	fclose(fp);
	return 0;
}
未格式化的行I/O

char * gets ( char * str ); 
int puts ( const char * str )

5.char * fgets ( char * str, int num, FILE * stream ); 
6.int fputs ( const char * str, FILE * stream ); 


int main()
{
	char buf[255] = {0};
	while (1)                                    //从标准输入读入,打印到标准输出
	{
		gets(buf);
		if (strcmp("quit", buf) == 0)
		{
			break;
		}
		//printf("echo:%s\n", buf);
		puts(buf);
	}
	printf("quit!\n");

	FILE *fp = fopen("myfile.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	char buf[128];
	while (1)                                     //从文件读到缓冲区,再从缓冲区读到屏幕
	{
		fgets(buf, 10, fp);
		if (feof(fp))
		{
			printf("end of file!   quit!\n");
			break;
		}
		fputs(buf, stdout);		
		fflush(stdout);
		Sleep(1000);
	}

	char buf[128];
	while (1)
	{
		printf("enter:");
		fgets(buf, 128, stdin);
		if (strncmp("quit", buf, 4) == 0)
		{
			break;
		}
		fputs(buf, fp);
	}

	fclose(fp);
	return 0;
}
格式化的行I/O

int scanf ( const char * format, ... ); //返回成功转换和分配的字段的数量
int printf ( const char * format, ... ); //返回值为打印的字符数,出现错误,打印负值 printf("%d", printf("%d",2));  21

输出缓存刷新到目标地址的时机:
1.\n
2.scanf
3.exit
4.内核缓存满
5.fflush(stdout);

7.int fscanf ( FILE * stream, const char * format, ... ); 
8.int fprintf ( FILE * stream, const char * format, ... ); 

#include <stdio.h>
#include <string.h>
int main()
{
	float f;
	char buf[16] = {0};
	char name[16] = {0};
	FILE *fp = fopen("log.txt", "w+");
	if(NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	
	fprintf(fp, "%f %s", 3.14159, "PI");		
	rewind(fp);                                     //将流的读写位置充值到最开始

	fscanf(fp, "%f %s", &f, buf);

	printf("%f, %s\n", f, buf);

	fclose(fp);
	return 0;
}
二进制I/O:

9.size_t fread ( void * ptr, size_t size, size_t count, FILE* stream );  <缓冲区名> <一个单元的大小> <要读多少单元> <流>
10.size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );  <写出缓冲区> <单元大小> <多少个单元> <流>

#include <stdio.h>

int main()
{
	char buff[] = {'A' , 'B' , 'C'};
	FILE *fp = fopen("myfile.bin","wb+");
	if(NULL == fp){
		perror("fopen");
		return 1;
	}	

	fwrite(buff,sizeof(char),sizeof(buff),fp);
	
	fclose(fp);
	return 0;
}
11.int fseek(FILE *stream, long offset, int whence); <流> <偏移量> <偏移位置>//进行文件写入位置的定位

fseek的whence和offset参数共同决定了读写位置移动到何处,whence参数的含义如下:
SEEK_SET
从文件开头移动offset个字节
SEEK_CUR
从当前位置移动offset个字节
SEEK_END
从文件末尾移动offset个字节

offset可正可负,负值表示向前(向文件开头的方向)移动,正值表示向后(向文件末尾的方向)移动,如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸,从原来的文件末尾到fseek移动之后的读写位置之间的字节都是0。

12. void rewind(FILE *stream)  ==   int fseek(FILE *stream, 0, SEEK_SET) //回到流的最开始

13.long ftell(FILE *stream);//报告每次写入的位置

14.int fflush(FILE *stream);

15.对比EOF和feof函数的区别?
feof()判断文件结尾:  二级制文本的结束标志
EOF   文本文件的结尾标志

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()

{
	char buf[20];
	FILE *fp = fopen("/bin/ls","rb");
	if(NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	fseek(fp,0,SEEK_END);                   //将写入位置移动到文件结尾
	long lsize = ftell(fp);                 //报告文件为准
	rewind(fp);                             //把光标移动到文件开始

	printf("size -> %d\n",lsize);
	
	char *buff = (char*)malloc(sizeof(char)*lsize);
	assert(buff);	
	ssize_t t = fread(buff,lsize, 1 ,fp);   //将fp读进buff
	
	FILE *ofp = fopen("myls","wb+");
	if(NULL == ofp){
		perror("fopen");
		return 1;
	}
	
	fwrite(buff,lsize, 1, ofp);

	fclose(fp);
	fclose(ofp);
	free(buff);
//	float d;
//	char name[20];
//	FILE *fp = fopen("czf.txt","w+");
//	if(NULL == fp)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	int i = 0;
//	for(; i < 5; i++){
//		printf("Please Enter a name:\n");
//		gets(name);
//		fprintf(fp, "Name %d is [%-10.20s]\n",i+1 ,name );
//	}
	
//	fprintf(fp, "%s %f\n","PI" ,3.14 );
//	rewind(fp);
//	fscanf(fp,"%s %f",&buff, &d);
//	printf("%s %f\n",buff,d);	

//	fclose(fp);
	return 0;
}