1.标准I/O
标准: 任何操作系统皆可使用;使用范围很广
系统调用和库函数
系统调用:操作系统给我们提供的接口 man 2
printf 可以调用内核中的接口 直接驱动显卡运行
printf实际是库函数中的函数,然后调用系统调用
原因:针对不同的操作系统,库函数可以翻译后成标准的系统调用对接不同的系统(安卓/linux)
strlen memcpy 等函数 也是靠库函数实现 man 3
直接使用系统调用的---> 文件io
- 系统调用和库函数
系统调用就是操作系统提供的接口函数.
如果我们把系统调用封装成库函数就可以起到隔离的作用,提供程序的可移植性。
Printf就是库函数然后调用了系统调用才在显示器上显示字符。
- 流的概念 文本流 和 二进制流
就是数据的流,在程序中就是一个结构体。
不同系统,流 不一样
- Windows 和linux的换行符区别
Windows是\r\n
Linux 是\n
- 缓冲区的概念
为了减少操作IO设备的次数,提高运行效率,在内存里面设置的缓冲区,
全缓冲:缓冲区满才输出
行缓冲:遇到换行符输出
2. 文件的打开:
- 文件的打开函数
FILE *fopen (const char *path, const char *mode);
Path: 普通文件当前路径不需要加目录,其他要使用完整的路径
Mode:
返回值:出错返回NULL,所以使用fopen函数必须判断是否为空
- 文件打开的模式(非常重要)
“r” 或 “rb” | 以只读方式打开文件,文件必须存在。 |
“r+” 或 ”r+b” | 以读写方式打开文件,文件必须存在。 |
“w” 或 “wb” | 以只写方式打开文件,若文件存在则文件长度清为0。若文件不存在则创建。 |
“w+” 或 “w+b” | 以读写方式打开文件,其他同”w”。 |
“a” 或 “ab” | 以只写方式打开文件,若文件不存在则创建;向文件写入的数 据被追加到文件末尾。 |
“a+” 或 “a+b” | 以读写方式打开文件。其他同”a” |
文件的打开
#include<stdio.h>int main(int argc, const char *argv[])
{FILE *fp;int ret = 0;fp = fopen("1.txt","a");if (fp == NULL){perror("fopen");return -1;}else{printf("open success\n");ret = fclose(fp);if (ret == 0){printf("fclose success\n");}else{perror("fclose");}}return 0;
}
读写单个字符
字符的输入(读单个字符):
int fgetc(FILE *stream);
int getc(FILE *stream); //宏
int getchar(void);
字符的输出(写单个字符):
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
include<stdio.h>int main(int argc, const char *argv[])
{FILE *fp;fp = fopen("1.txt","a");if(fp == NULL){printf("fopen failed\n");return -1;}/* 读函数int rec;rec = fgetc(fp);printf("get char = %c\n",rec);
//文件指针的应用rec = fgetc(fp);printf("get char = %c\n",rec);rec = fgetc(fp);printf("get char = %c\n",rec);rec = fgetc(fp);printf("get char = %c\n",rec);fclose(fp);*/int wrc = 'c';wrc = fputc(wrc,fp);printf("fputc is %c\n",wrc);return 0;
}
按行读取字符 fgets
char *fgets(char *s, int size, FILE *stream);
成功时返回s,到文件末尾或出错时返回NULL
遇到’\n’或已输入size-1个字符时返回,总是包含’\0’
注意事项:
fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于size-1 后面会添加换行符。
按行输入字符 fputs
int fputs(const char *s, FILE *stream);
成功时返回非负整数;出错时返回EOF
puts将缓冲区s中的字符串输出到stdout,并追加’\n’
fputs将缓冲区s中的字符串输出到stream,不追加 ‘\n’
#include<stdio.h>
int main(int argc, const char *argv[])
{FILE *fp;char *rec;char buff[100];fp = fopen("1.txt","a+");if (fp == NULL){perror("fopen");return 0;}rec = fgets(buff,6,fp);if (rec== NULL){perror("fgets");return 0;}while(rec != NULL){rec = fgets(buff,6,fp);printf("buff = %s\n",buff);}
//fputs 的使用,输出字符int wrn;wrn = fputs("aaaaa",fp);//在1.txt文件追加一行字符串aaaaaif(wrn == -1)
{perror("fputs");return -1;
}return 0;
}
二进制读写(二进制读写既可以读写二进制文件,又可以读写文本文件)
文本文件和二进制的区别:
存储的格式不同:文本文件只能存储文本。
所有的文件除了文本文件就是二进制文件:比如说音频文件的读写
计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字0101001....,所以所有符号都要编码)
二进制读写函数格式:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
void *ptr 读取内容放的位置指针
size_t size 读取的块大小
size_t n 读取的个数
FILE *fp 读取的文件指针
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{FILE *fp;size_t ret;struct student{char name[16];int age;char sex[8];};struct student stu;struct student stu2;strcpy(stu.name,"zhangsan");stu.age = 49;strcpy(stu.sex,"male");fp = fopen("1.bin","w");if(fp == NULL){perror("fopen");return 0;}ret = fwrite(&stu,sizeof(stu),1,fp);if (ret == -1){perror("fwrite");return 0;}else{printf("fwrite is success\n");}fclose(fp);//以上为写入二进制内容,下面为读取二进制文件,首先需要刷新文件流指针,这里选择的是先关闭在打开fp = fopen("1.bin","r");if(fp == NULL){perror("fopen");return 0;}ret = fread(&stu2,sizeof(stu),1,fp);if (ret == -1){perror("fread");return 0;}else{printf("fread is success\n");printf("stu2.name = %s, stu2.age = %d, stu2.sex = %s \n",stu2.name,stu2.age,stu2.sex);}fclose(fp);return 0;
}
3.文件I/O
文件IO的概念:
什么是文件IO,又称系统IO,系统调用
是操作系统提供的API接口函数。
POSIX接口 (了解)
注意:文件IO不提供缓冲机制
文件IO的API
open close read read
文件描述符概念:
英文:缩写fd(file descriptor)
是0-1023的数字,表示文件。
0, 1, 2 的含义 标准输入,标准输出,错误
3.1文件I/O的读写实现
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>int main(int argc, const char *argv[])
{int fd;int ret;char buf[32]={"hello world"};char buf2[32] = {0};fd =open("test.txt",O_RDWR| O_APPEND;printf("fd = %d\n",fd);if(fd<0){perror("open");return 0;}ret = write(fd,buf,strlen(buf));if (ret < 0 ){perror("write");return 0;}printf("buf = %s\n",buf);
//write函数执行结束后,文件流指针处于末尾,所以需要重新打开文件close(fd);fd =open("test.txt",O_RDWR);printf("fd = %d\n",fd);if(fd<0){perror("open");return 0;}ret = read(fd,buf2,32);if(ret < 0){perror("read");return 0;}buf2[31] = '\0';printf("buf2 = %s\n",buf2);return 0;