我是靠谱客的博主 懵懂小虾米,最近开发中收集的这篇文章主要介绍I/O接口库函数和系统调用I/O接口函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

访问文件方式(1)C库I/O函数;(2)系统调用I/O函数

1、C文件I/O接口库函数

标准C对I/O的概念进行抽象,对于C程序,所有的I/O操作就是移进、移出字节的事情,这种字节流被称为流。可以形象的认为流就是文件。C库函数读取、写入流基本都是完全缓冲,因为I/O函数和磁盘打交道速度太慢,所以就有了一个缓冲区,当缓冲区被塞满的时候,一起打包放入到文件或者设备。这就是完全缓冲。

1.文件常量

EOF:文件结束标志;FOPEN_MAX:程序最多打开文件个数;

2.文件I/O函数

功能函数名适用于
字符输入函数getchar标准输入流
字符输出函数putchar 标准输出流
字符输入函数fgetc, getc所有输入流
字符输出函数fputc, putc所有输出流
文本行输入函数fgets, gets所有输入流
文本行输出函数fputs, puts所有输出流
格式化输入函数scanf标准输入流
格式化输出函数printf标准输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread 文件
二进制输出fwrite 文件

3.打开流(文件) 

参数介绍:参数1:文件的路径;

                  参数2:打开方式;

失败返回NULL;

打开方式介绍:

"r":在文件开始读文件

"r+":在文件开始处读和写

"w":如果文件存在则清空,否则创建文件

"w+":文件存在则清空文件,否则创建文件读和写

"a":如果文件不存在,创建文件并写入,否则在文件末尾写入

"a+":读和写,同上

"t":文本流

"b":二进制流

//程序事例
#include<stdio.h>
#include<stdlib.h>
int main()
{
  FILE *fp = fopen("./txt.txt","a+");
  if(NULL == fp)
  {
    perror("fopen");
    exit(1);
  }
  fclose(fp);
  return 0;
}

4.字符I/O

//向标准输出写入
#include<stdio.h>
#include<stdlib.h>
int main()
{
  int ch = 0;
  do{
    //ch = getchar();//从标准输入读取数据
    //putchar(ch);//像标准输出输出数据
    ch = getc(stdin);//可以理解为getchar对getc的封装
    putc(ch,stdout);//putchar对putc的封装
  }while(ch != EOF);
  return 0;
}
//向文件写入
#include<stdio.h>
#include<stdlib.h>
int main()
{
  FILE *fp = fopen("./txt.txt","a+");
  if(NULL == fp)
  {
    perror("fopen");
    exit(1);
  }
  int ch = 0;
  while((ch = getc(stdin)) != EOF)
  {
    putc(ch,fp);//向文件内写入
  }
  fclose(fp);
  return 0;
}
//读取文件
#include<stdio.h>
#include<stdlib.h>
int main()
{
  FILE *fp = fopen("./txt.txt","r");
  if(NULL == fp)
  {
    perror("fopen");
    exit(1);
  }
  int ch = 0;
  while((ch = getc(fp)) != EOF)
  {
    fputc(ch,stdout); 
  }
  fclose(fp);
  return 0;
}

 

5.未格式化的行I/O

未格式化:输入什么就是什么;

行:遇到 'n'  输出;

#include<stdio.h>

int main()
{
  char str[128];
  gets(str);//从标准输入读
  puts(str);//向标准输出写入
  return 0;
}

注:fgets如果读取到文件尾(EOF)或者读取错误返回NULL; 

//实现一个记事本
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  FILE *fp = fopen("./txt.txt","a+");
  if(NULL == fp)
  {
    perror("fopen");
    exit(1);
  }
  char line[128];//缓冲区
  while(1)
  {
    line[0] = 0;//清空缓冲区
    fgets(line,sizeof(line),stdin);
    if(strcmp(line,"quitn") == 0)
      break;
    fputs(line,fp);//把缓冲区内容写入文件
  }
  fclose(fp);
  return 0;
}

6.格式化的行I/O

scanf格式: 

#include<stdio.h>
int main()
{
  //char buf[8] = {0};
  //scanf("%4s",buf);//限制buf输入的字符个数为4个
  //printf("%sn",buf);
  //int i = 0;
  //scanf("%x",&i);//输入1234  
  //printf("%#xn",i);//输出0x1234   十六进制
  int a = 0;
  scanf("%o",&a);
  printf("%#on",a);
  //八进制:
  //%o  1234
  //%#o 01234
  return 0;
}

printf格式:

#include<stdio.h>
int main()
{
  printf("%c %c n",'a',65);
  printf("%d %ldn",1977,650000L);
  printf("[%10d] n",1977); //10个位置右对齐
  printf("[%-10d]n",1977); //10个位置左对齐
  printf("%010d n",1977); //右对齐,左边的空格用0补全
  printf("%d %x %#x %o %#o n",100,100,100,100,100);
  // %x 十六进制  1234
  // %#x   0x1234
  // %o 八进制  1234
  // %#o 01234
  printf("%4.2f n",3.1486); //4表示预留多少个位置(包含小数点),2表示小数点后有几位,会四舍五入
  printf("[%*d] n",5,10);//5就是*,表示有五个位置,d就是10
  printf("%s n","hello world");
  return 0;
}
///
a.out
a A 
1977 650000
[      1977] 
[1977      ]
0000001977 
100 64 0x64 144 0144 
3.15 
[   10] 
hello world 
int main()
{
  char buf[100];
  float f = 0;
  FILE *fp = fopen("./txt.txt","w+");
  if(NULL == fp)
  {
    strerror(errno);
    exit(1);
  }
  fprintf(fp,"%f %s",3.1416,"helloworld");//字符串不可以有空格,不然空格后面字符串输不出来
  rewind(fp);//使光标回到文件开头
  fscanf(fp,"%f",&f);
  fscanf(fp,"%s",buf);
  fclose(fp);
  printf("%f %sn",f,buf);
  return 0;
}

7.二进制I/O (二进制读写“rb”,“wb”等)

//二进制I/O读取结构体向文件
#include<stdio.h>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS 
#pragma warning(disable:4996)
typedef struct A{
	int a;
	int b;
	char c;
	char str[20];
}A;

int main()
{
	FILE *fp = fopen("./txt.txt","a+b");
	if (NULL == fp)
	{
		perror("fopen");
		exit(1);
	}
	A x = { 1, 2, 'a', "hello world" };
	//fwrite(&x, 1, sizeof(x), fp); //向文件写入结构体
	A y;
	fread(&y, 1, sizeof(y), fp); //从文件读取结构体
	fclose(fp);
	return 0;
}

返回值:若成功,返回0;若失败非0值 

该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值 

下面两个程序都是获取文件大小 

//获取文件大小
int main()
{
	FILE *fp = fopen("./txt.txt","a+b");
	if (NULL == fp)
	{
		perror("fopen");
		exit(1);
	}
	int total = 0;
	int count = 0;
	char buf[100] = { 0 };
	while (!feof(fp))  //光标没有到达文件尾返回0,否则非0
	{                  //二进制读取文件只能用feof来判断是否到达文件尾,而文本流可以feof也可以EOF
		buf[0] = 0;
		count = fread(buf, 1, sizeof(buf), fp);//返回实际读取到多少,只有这么用,返回值才表示真正读取到多少字节
		if (ferror(fp) != 0)//如果错误,他会对于返回错误码,0是正确
		{
			perror("fp");
			exit(1);
		}
		total += count;
	}
	printf("total = %d n", total);
	fclose(fp);
	return 0;
}
//获取文件大小
int main()
{
	FILE *fp = fopen("./txt.txt","a+b");
	if (NULL == fp)
	{
		perror("fopen");
		exit(1);
	}
	long total = 0;
	int ret = fseek(fp, 0, SEEK_END);
    if(ret != 0)
    {
        perror("fseek");
        exit(2);
    }
	total = ftell(fp);
    if(total == -1L)
    {
        perror("ftell");
        exit(3);
    }
	printf("total = %d n", total);
	fclose(fp);
	return 0;
}

 

int main()
{
	FILE *fp_1 = fopen("scr_txt.txt", "a+");
	char buf[128] = { 0 };
	//给源文件写入
	while (1)
	{
		buf[0] = 0;
		fgets(buf,sizeof(buf),stdin);
		if (strcmp(buf, "quitn") == 0)
			break;
		fputs(buf, fp_1);
	}
	fclose(fp_1);
	//把源文件内容拷贝到目标文件
	fp_1 = fopen("scr_txt.txt", "a+b");
	FILE *fp_2 = fopen("dst_txt.txt", "a+b");
	if (!fp_1 || !fp_2)
	{
		perror("fopen");
		exit(1);
	}

	while (!feof(fp_1))
	{
		buf[0] = 0;
		size_t ret = fread(buf, 1, sizeof(buf), fp_1);
		if (ferror(fp_1) != 0)
		{
			perror("fp_1");
			exit(3);
		}
		fwrite(buf, ret, 1, fp_2);//把fp_2改为stdout,输出到标准输出
		if (ferror(fp_2) != 0)
		{
			perror("fp_2");
			exit(4);
		}
	}
	fclose(fp_1);
	fclose(fp_2);
	return 0;
}
//文件内容拷贝
int main()
{
	FILE *fp_1 = fopen("./scr_txt.txt", "a+b");
	if (NULL == fp_1)
	{
		perror("fp_1");
		exit(1);
	}
	FILE * fp_2 = fopen("./dst_txt.txt", "a+b");
	if (fp_2 == NULL)
	{
		perror("fp_2");
		exit(2);
	}
	fseek(fp_1, 0, SEEK_END);
	long scr_size = ftell(fp_1);
	char *buf = (char *)malloc(scr_size);
	assert(buf);
	rewind(fp_1);
	fread(buf, scr_size, 1, fp_1);
	fwrite(buf, scr_size, 1, fp_2);
	free(buf);
	fclose(fp_1);
	fclose(fp_2);
	return 0;
}

 

2.系统文件I/O接口函数 (基本不带缓冲)

除了上面c库函数接口,还有系统调用接口。常用的就是5个函数:open、read、write、lseek以及close。

1.文件描述符

对于内核而言,所有对文件的操作都通过文件描述符来操作,文件描述符是一个小的非负整数,当打开或者创建一个文件,内核都会向进程返回一个文件描述符。读和写一个文件时,使用的文件描述符参数就是open返回值。其实,当我们创建一个文件,就会对应创建一个数据结构来描述该目标文件,于是就有了文件结构体,open打开文件,为了使得文件和进程关联起来,在进程task_struct里面的I/O相关信息里面有个文件描述符指针,指向一个文件描述表就是数组,每个元素就是对该文件的属性描述,而数组下标就是文件描述符,大多是操作系统默认文件描述符0是标准输入,1是标准输出,2是标准错误。

文件描述符分配规则:从文件描述符表下标0开始查找,空闲的下标,作为当前文件的文件描述符(如果我们不关闭0,1,2,一般文件描述符从3开始)。

当我们一直打开文件,而不关闭文件,就会导致文件描述符越来越大,当然有上限,就会导致打开文件失败。其实,文件描述符最大多少可以调整,输入指令ulimit -a,进行对应修改。

2.open函数

当我们打开一个文件,除非有O_APPEND选项 当前文件偏移量从文件尾开始,否则是从文件开始处。

3.close函数

4.lseek函数

下面程序是求文件大小:前面讲讲到的,还有下面的,一共三种方法获取文件大小

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
  int fp = open("./txt.txt",O_RDONLY);
  if(fp<0)
  {
    perror("open");
    exit(1);
  }
  off_t total = lseek(fp,0,SEEK_END);
  if(total<0)
  {
    perror("lseek");
    exit(2);
  }
  close(fp);
  printf("total = %ldn",total);
  return 0;
}

5.read函数和write函数

下面程序是从标准输入读取,并且标准输出 (ctrl +d结束)

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  char buf[1024] = {0};
  int n = 0;
  while((n = read(0,buf,sizeof(1024)-1)) >0)
  {
    if(write(1,buf,n) != n)
    {
      perror("write");
      exit(1);
    }
  }
  if(n<0)
  {
    perror("read");
    exit(2);
  }
  return 0;
}
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{
  int fd = open("./txt.txt",O_WRONLY);
  if(fd<0)
  {
    perror("open");
    exit(1);
  }
  char buf[128] = {0};
  while(fgets(buf,sizeof(buf)-1,stdin))  //ctrl+d结束
  {
    long size = strlen(buf);
    if(write(fd,buf,size)!= size)
    {
      perror("write");
      exit(2);
    }
    buf[0] = 0;
  }
  close(fd);
  return 0;
}

 

下面程序实现拷贝文件内容

#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main()
{
  int scr_fd = open("./txt.txt",O_RDONLY);
  if(scr_fd<0)
  {
    perror("open");
    exit(1);
  }
  int dst_fd = open("./scr.txt",O_CREAT|O_WRONLY);
  if(dst_fd<0)
  {
    perror("open");
    exit(2);
  }
  ssize_t n = 0;
  char buf[10] = {0};
  while((n = read(scr_fd,buf,sizeof(buf)-1))>0)
  {
    if(write(dst_fd,buf,n) != n)
    {
      perror("write");
      close(scr_fd);
      close(dst_fd);
      exit(3);
    }
  }
  if(n<0)
  {
    perror("read");
    close(scr_fd);
    close(dst_fd);
    exit(4);
  }
  close(scr_fd);
  close(dst_fd);//可以使用goto语句,可以少些close
  return 0;
}

 

最后

以上就是懵懂小虾米为你收集整理的I/O接口库函数和系统调用I/O接口函数的全部内容,希望文章能够帮你解决I/O接口库函数和系统调用I/O接口函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部