我是靠谱客的博主 懵懂小虾米,这篇文章主要介绍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":二进制流

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//程序事例 #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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//向标准输出写入 #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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//向文件写入 #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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//读取文件 #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'  输出;

复制代码
1
2
3
4
5
6
7
8
9
10
#include<stdio.h> int main() { char str[128]; gets(str);//从标准输入读 puts(str);//向标准输出写入 return 0; }

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//实现一个记事本 #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格式: 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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格式:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#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
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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”等)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//二进制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 被设置为一个正值 

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//获取文件大小 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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//获取文件大小 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; }

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//文件内容拷贝 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函数

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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结束)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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; }

 

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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接口函数内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部