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文件追加一行字符串aaaaa
if(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;