【文件I/O】(一)标准I/O

一、基本概念

1.文件类型

概念:一组相关数据的有序集合
文件类型:

  1. 常规文件 r
  2. 目录文件 d
  3. 字符设备文件 c
  4. 块设备文件 b
  5. 管道文件 p
  6. 套接字文件 s
  7. 符号链接文件 l

2.标准I/O介绍

标志I/O由ANSI C标准定义,主流操作系统上都实现了C库
标准I/O通过缓冲机制减少系统调用,实现更高的效率

3.流的概念

FILE:
标准I/O用一个结构体类型来存放打开的文件的相关信息
标准I/O的所有操作都是围绕FILEl来进行

流(stream):
FILE又被称为流(stream)
文本流/二进制流

4.文本流和二进制流

windows
二进制流:换行符 <—> ‘\n’
文本流:换行符 <—> ‘\r’‘\n’

Liniux
换行符 <—> ‘\n’

5.流的缓冲类型

全缓冲
当流的缓冲区无数据或无空间时才执行实际I/O操作

行缓冲
当输入和输出中遇到换行符(‘\n’)时,进行I/O操作
当流和一个终端关联时,典型的行缓冲

无缓冲
数据直接写入文件,流不进行缓冲

6.标准I/O流(stdin、stdout、stderr)

标准I/O预定义3个流,程序运行时自动打开

标准输入流0STDIN_FILENOstdin
标准输出流1STDOUT_FILENOstdout
标准错误流2STDERR_FILENOstderr

二、流的操作

1.打开流(fopen)

在这里插入图片描述

(1)mode参数(r、r+、w、w+、a、a+)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(2)处理错误信息(perror、strerror)

在这里插入图片描述

(3)重定向输入输出流(freopen)

在这里插入图片描述

2.关闭流(fclose)

在这里插入图片描述

在这里插入图片描述

3.示例代码

(1)fopen、perror、strerror、fclose

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main(int argc, const char **argv)
{
	FILE *fp;
	
	fp = fopen("1.txt", "r+");
	if (fp == NULL) {
		perror("fopen");
		printf("fopen: %s\n", strerror(errno));
		return -1;
	}

	fclose(fp);
	
	printf("end!\n");
	return 0;
}

(2)freopen

#include <stdio.h>

int main(int argc, const char **argv)
{
	if (freopen("1.txt", "w", stdout) == NULL) {
		perror("freopen");
		return -1;
	}
	printf("stdout --> 1.txt\n");
	
	fclose(stdout);
	
	printf("end!\n");
	return 0;
}

三、读写流

1.按字符输入(fgetc、getc、getchar)

在这里插入图片描述
在这里插入图片描述

2.按字符输出(fputc、putc、putchar)

在这里插入图片描述

在这里插入图片描述

3.按行输入(gets、fgets)

在这里插入图片描述
在这里插入图片描述

4.按行输出(puts、fputs)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.按对象读写(fread、fwrite)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.刷新流(fflush)

在这里插入图片描述

7.定位流指针(ftell、fseek、rewind)

注意事项

  1. 文件a模式打开时,函数fseek无效
  2. rewind(fp)相当于fseek(fp, 0, SEEK_SET)
  3. 这3个函数只适用于2G以下的文件

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

8.判断流是否出错和结束(ferror、feof)

在这里插入图片描述

9.格式化输出(printf、fprintf、sprintf)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

四、示例代码

1.fgetc(统计文本文件字符数)

#include <stdio.h>

int main(int argc, const char **argv)
{
	int ch;
	FILE *fp;
 	int count = 0;
 	
	if (argc < 2) {
      printf("Usage: %s <file>\n", argv[0]);
	  return -1;
   }
   
	//1
	ch = fgetc(stdin);
	if (ch == EOF) {
		perror("fgetc");
		return -1;
	}
	printf("ch is %c\n", ch);

	//2
	if ((fp = fopen(argv[1], "r")) == NULL) {
		perror("fopen");
		return -1;
	}

	while ((ch = fgetc(fp)) != EOF) {
		count++;
	}
	printf("%s total %d bytes!\n", argv[1], count);
		
	fclose(fp);
	
	return 0;
}

2.fputc(将a~z写入文件)

#include <stdio.h>

int main(int argc, const char **argv)
{
	int ch;
	int ret;
	FILE *fp;
	
	if (argc < 2) {
      printf("Usage: %s <file>\n", argv[0]);
	  return -1;
   }
   
	//1
	ret = fputc('a', stdout);
	if (ret == EOF) {
		perror("fputc");
		return -1;
	}
	putchar('\n');

	//2
	if ((fp = fopen(argv[1], "w")) == NULL) {
		perror("fopen");
		return -1;
	}

	for (ch = 'a'; ch <= 'z'; ch++) {
		fputc(ch, fp);
	}
		
	fclose(fp);
	
	return 0;
}

3.fgets(标准输入流写入buff)

#include <stdio.h>
#define N 6

int main(int argc, char **argv)
{
	char buff[N];
	
	fgets(buff, N, stdin);
	printf("%s", buff);
	
	return 0;
}

4.fputs(将内存数据输出到标准输出流)

#include <stdio.h>

int main(int argc, char **argv)
{
	puts("hello world");  //加换行
	
	char buff[] = "hello world\n";  //不加换行
	fputs(buff, stdout);
	
	return 0;
}

5.fread、fwrite(二进制文件读写)

#include <stdio.h>
#include <string.h>

struct stu {
	char name[15];
	int age;
	char sex[10];
};

int main(int argc, char **argv)
{	
	FILE *fp;
	struct stu s1,s2;
	int ret;
	
	if ((fp = fopen("1.bin", "w+")) == NULL) {
		perror("fopen");
		return -1;
	}
	
	strcpy(s1.name, "tanpeng");
	s1.age = 21;
	strcpy(s1.sex, "male");
	
	ret = fwrite(&s1, sizeof(s1), 1, fp);
	if (ret == EOF) {
		perror("fwrite");
		return -1;
	}

	fclose(fp);
	if ((fp = fopen("1.bin", "r+")) == NULL) {
		perror("fopen");
		return -1;
	}
	
	ret = fread(&s2, sizeof(s2), 1, fp);
	if (ret == EOF) {
		perror("fread");
		return -1;
	}
	printf("name:%s  age:%d  sex:%s\n", s2.name, s2.age, s2.sex);	 

	fclose(fp);
	return 0;
}

6.fflush(刷新流,刷新缓冲区)

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	FILE *fp;
	int ret;

	if ((fp = fopen("1.bin", "a+")) == NULL) {
		perror("fopen");
		return -1;
	}
	
	ret = fwrite("abcdef", 6, 1, fp);
	if (ret == EOF) {
		perror("fwrite");
		return -1;
	}
	fflush(fp);

	while(1) {
		sleep(1);
	}

	fclose(fp);
	return 0;
}

7.ftell、fseek、rewind(定位流指针)

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	FILE *fp;
	int ret;

	if ((fp = fopen("1.bin", "w")) == NULL) {
		perror("fopen");
		return -1;
	}
	
	ret = fwrite("abcdef", 6, 1, fp);
	if (ret == EOF) {
		perror("fwrite");
		return -1;
	}
	printf("start fp:%d\n", (int)ftell(fp));

	ret = fseek(fp, -4, SEEK_CUR);	
	ret = fwrite("ss", 2, 1, fp);
	if (ret == EOF) {
		perror("fwrite");
		return -1;
	}
	printf("fseek fp:%d\n", (int)ftell(fp));

	rewind(fp);	
	ret = fwrite("rr", 2, 1, fp);
	if (ret == EOF) {
		perror("fwrite");
		return -1;
	}
	printf("rewind fp:%d\n", (int)ftell(fp));
	
	fclose(fp);
	return 0;
}

8.fprintf、sprintf(格式化输出数据到文件、内存,常用sprintf)

#include <stdio.h>

int main(int argc, char **argv)
{
	FILE *fp;
	char buff[40];
	int year = 2022;
	int month = 8;
  	int day = 7;
	
	if ((fp = fopen("1.txt", "w+")) == NULL) {
		perror("fopen");
		return -1;
	}
	fprintf(fp, "%d-%d-%d\n", year, month, day);
	sprintf(buff, "%d-%d-%d", year, month, day);
	
	printf("%s\n", buff);
	
	fclose(fp);
	return 0;
}

9.fscanf、sscanf(将文件、内存数据格式化输入,可用作解析字符串)

#include <stdio.h>

int main(int argc, char **argv)
{	
	FILE  *fp;
	char buff[40];
	int year = 2022;
	int month = 8;
  	int day = 7;
	int fyear,fmonth,fday;
	int syear,smonth,sday;
	
	//1.fscanf
	if ((fp = fopen("1.txt", "w+")) == NULL) {
		perror("fopen");
		return -1;
	}
	fprintf(fp, "%d-%d-%d", year, month, day);
	rewind(fp);
	fscanf(fp, "%d-%d-%d", &fyear, &fmonth, &fday);

	printf("after fscanf:\n");
	printf("%d,%d,%d\n", fyear, fmonth, fday);

	//2.sscanf
	sprintf(buff, "%d-%d-%d", year, month, day);
	printf("%s\n", buff);
	sscanf(buff, "%d-%d-%d", &syear, &smonth, &sday);

	printf("after sscanf:\n");
	printf("%d,%d,%d\n", syear, smonth, sday);
	
	fclose(fp);	
	return 0;
}

五、案例源码

1.复制文件1

#include <stdio.h>

int main(int argc,  char *argv[])
{
   FILE *fps, *fpd;
   int ch;
   
   if (argc < 3) {
      printf("Usage : %s <src_file> <dst_file>\n", argv[0]);
	  return -1;
   }
 
   if ((fps = fopen(argv[1], "r")) == NULL) {
       perror("fopen");
	   return -1;
   }
   
   if ((fpd = fopen(argv[2], "w")) == NULL) {
       perror("fopen");
	   return -1;
   }
   
   while ((ch = fgetc(fps)) != EOF) {
      fputc(ch, fpd);
   }
   fclose(fps);
   fclose(fpd);

   return  0;
 }

2.统计文本文件行数

#include <stdio.h>
#include <string.h>

#define  N  64

int main(int argc,  char *argv[])
{
   FILE *fp;
   int line = 0;
   char buf[N];

   if (argc < 2) {
      printf("Usage: %s <file>\n", argv[0]);
	  return -1;
   }
   
   if ((fp = fopen(argv[1], "r")) == NULL) {
      printf("fopen  error\n");
      return -1;
   }
   
   while (fgets(buf, N, fp) != NULL) {
      if (buf[strlen(buf)-1] == '\n') line++;
   }

   printf("the line of %s is %d\n", argv[1], line);
   
   return  0;
 }

3.复制文件2

#include <stdio.h>

#define  N  64

int main(int argc,  char *argv[])
{
   FILE *fps, *fpd;
   int buf[N];
   int n;
   
   if (argc < 3) {
      printf("Usage : %s <src_file> <dst_file>\n", argv[0]);
	  return -1;
   }
 
   if ((fps = fopen(argv[1], "r")) == NULL) {
       perror("fopen src file");
	   return -1;
   }
   
   if ((fpd = fopen(argv[2], "w")) == NULL) {
       perror("fopen dst file");
	   return -1;
   }
   
   while ((n = fread(buf, 1, N, fps)) > 0) {
      fwrite(buf, 1, n, fpd);
   }
   fclose(fps);
   fclose(fpd);

   return  0;
 }

4.获取文件长度

#include <stdio.h>

int main(int argc,  char *argv[])
{
   FILE *fp;
   
   if ((fp = fopen("test.txt", "r+")) == NULL) {
       perror("fopen");
       return -1;
   }
  
   fseek(fp, 0, SEEK_END);
   printf("length is %ld\n", ftell(fp));   

   return  0;
 }	

5.按指定格式打印时间

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

int main()
{
   FILE *fp;
   int line = 0;
   char buf[64];
   time_t t;
   struct tm *tp;
   
   if ((fp = fopen("test.txt", "a+")) == NULL) {
       perror("fopen");
       return -1;
   }
  
   while (fgets(buf, 64, fp) != NULL)
   {
      if (buf[strlen(buf)-1] == '\n') line++;
   }   
   
   while ( 1 )
   {
      time(&t);
      tp = localtime(&t);
      fprintf(fp, "%02d, %d-%02d-%02d %02d:%02d:%02d\n", ++line, tp->tm_year+1900, tp->tm_mon+1,
                                tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
      fflush(fp);
      sleep(1);
   }	  

   return  0;
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值