一、IO基础
1、文件的概念:
1、文件:一组相关数据的有序集合
2、文件名:这个数据集合的名称
2、linux支持的文件类型
常规文件:-
ASCII码文件
二进制的文件
目录:d
字符设备:c
块设备:b
有名管道:p
套接口:s
符号链接:l
可记做:lsp-bcd
3、系统调用
1、用户空间进程访问内核的接口
2、把用户从底层的硬件编程中解放出来
3、极大的提高了系统的安全性
4、使用户程序具有可移植性
5、操作系统的一部分
4、库函数
1、库函数为了实现某个功能而封装起来的API集合
2、提供统一的编程接口,更加便于应用程序的移植
3、是语言或者应用程序的一部分
二、标准IO
1、文件指针
FILE指针:每个被使用的文件都在内存中开辟一个区域,用来存放文件的有关信息,这些信息是保存在一个结构体类型的变量中,该结构体类型是由系统定义的,取名为FILE。
标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE *来描述。
标准I/O库是由Dennis Ritchie在1975年左右编写的
2、流(stream)
定义:所有的I/O操作仅是简单的从程序移进或者移出,这种字节流,就称为流。
分类:文本流/二进制流。
1.文本流
定义:在流中处理的数据是以字符出现。在文本流中,’\n’被转换成回车符CR和换行符LF的ASCII码0DH和0AH。而当输出时,0DH和0AH被转换成’\n’
数字2001在文本流中的表示方法为 ‘2’ ‘0’ ‘0’ ‘1’
ASCII: 50 48 48 49
2.字节流
定义:流中处理的是二进制序列。若流中有字符,则用一个字节的二进制ASCII码表示;若是数字,则用对应的二进制数表示。对’\n’不进行变换
数字2001在二进制流中的表示方法为 00000111 11010001。
每个进程默认打开三个流:
- stdin:标准输入
- stdout:标准输出
- stderr:标准错误
3、缓存分类
1.全缓存:
刷新(fflush):标准I/O的写操作。
当填满I/O缓存,或者满足一定的条件后,就会执行刷新操作。
2.行缓存
当输入输出过程中遇到换行符('\n')时,进行I/O操作
当流遇到一个终端时,为典型的行缓存
3.不缓存
准I/O库不对字符进行缓冲,例如stderr。
很多的人机交互界面要求不可全缓存。
标准出错决不会是全缓存的。
4、文件操作
流程:打开文件 --> 操作文件 --> 关闭文件。
打开文件:fopen /关闭文件:fclose
函数原型:
FILE *fopen (const char *path, const char *mode);
返回值:成功打开文件的流指针,失败NULL
const char *path:要打开的文件
const char *mode:打开的方式
mode的选项:
r或rb :打开只读文件,该文件必须存在。
r+或r+b :打开可读写的文件,该文件必须存在。
w或wb :打开只写文件,若文件存在则文件长度清为0,即会擦些文件以前内容。若文件不存在则建立该文件。
w+或w+b或wb+ :打开可读写文件,若文件存在则文件长度清为零,即会擦除文件以前内容。若文件不存在则建立该文件。
a或ab :以追加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+或a+b或ab+ :以追加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,从头读取,但是写入的数据会被加到文件尾后,即文件原先的内容会被保留。
关闭文件:fclose
关闭文件函数原型
int fclose(FILE *stream);
FILE *stream:要关闭的文件流指针
fopen/fclose示例
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp= fopen("1.txt","r"); // 打开1.txt文件
if( NULL == fp ) // 如果打开文件失败,则输出错误原因
{
perror("fopen ");
return -1;
}
fclose(fp); // 关闭文件
return 0;
}
操作文件:fread/fwrite
读文件函数原型:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值:成功>0表示实际读取字节数,==0表示读到文件末尾 失败 -1出错
void *ptr:存储读取内容的缓存首地址
size_t size:每次读取的字节数
size_t nmemb:读取多少次
FILE *stream:读取的目标流
fread示例
#include <stdio.h>
#include <string.h>
#define N 64
int main(int argc, char *argv[])
{
//判断命令行参数个数
if( 2 > argc )
{
printf("argv:%s<filename>\n",argv[0]);
return -1;
}
//打开文件
FILE * fp = fopen(argv[1],"a+");
if( NULL == fp )
{
perror("fopen");
return -1;
}
//定义缓冲区
char a[N] = {0};
while(1)
{
int ret = fread(a,1,1,fp); //将打开文件的内容写入缓冲区中
if( 0 == ret ) // ret为fread返回值,为0则到达文件末尾,结束循环
{
break;
}
printf("%s",a);
memset(a,0,N);
}
//关闭文件
fclose(fp);
return 0;
}
写文件函数原型:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值:实际写入字节数,失败-1
const void *ptr:要写入的数据所在缓存首地址
size_t size:每次写入字节数
size_t nmemb:写入多少次
FILE *stream:写入的文件流指针
fwrite示例
#include <stdio.h>
#include <string.h>
#define N 64
int main(int argc, char *argv[])
{
//判断命令行参数个数
if( 2 > argc )
{
printf("argv:%s<filename>\n",argv[0]);
return -1;
}
//打开文件
FILE * fp = fopen(argv[1],"a+");
if( NULL == fp )
{
perror("fopen");
return -1;
}
//定义缓冲区
char a[N] ;
while(1)
{
fgets(a,N-1,stdin); // 从终端获取输入到缓冲区
if( 0 == strcasecmp(a,"quit\n"))
{
break;
}
fwrite(a,strlen(a),1,fp); // 将缓冲区内容写到打开的文件中
}
//关闭文件
fclose(fp);
return 0;
}
fputs和fgets
fgets函数用于从文本文件中读取一行字符串,并将其存储到指定的字符串变量中。它的原型如下:
char *fgets(char *str, int n, FILE *stream);
其中,str是指向字符数组的指针,用于存储读取到的字符串;n是最多要读取的字符数,包括最后
的'\0';stream是要读取的文件指针。如果读取成功,函数返回指向存储的字符串的指针,否则返回
NULL。
fputs示例用法:
#include <stdio.h>
int main() {
FILE *file = fopen("file.txt", "r"); //打开文件
if (file) //如果文件存在
{
char str[100];
while (fgets(str, sizeof(str), file) != NULL) //文件输入到缓冲区且不为空
{
printf("%s", str);
}
fclose(file); //关闭文件
}
return 0;
}
fputs函数用于将字符串写入文本文件。它的原型如下:
int fputs(const char *str, FILE *stream);
其中,str是要写入的字符串;stream是要写入的文件指针。如果写入成功,返回非负数,否则返回
EOF。
fputs示例用法:
#include <stdio.h>
int main() {
FILE *file = fopen("file.txt", "w"); // 打开文件
if (file) {
fputs("Hello, World!", file);//将"Hello, World!"写到文件中
fclose(file);//关闭文件
}
return 0;
}
fprintf/fscanf
fprintf原型如下:
int fprintf(FILE *stream, const char *format, ...);
其中,stream是一个指向要写入数据的文件指针,format是一个字符串,包含要打印的文本和格式控制符,...表示可变数量的参数,用于填充格式控制符中的占位符。
fprintf函数的用法与printf函数类似,只是需要指定输出到哪个文件中。stream可以是标准输出流(stdout)或标准错误流(stderr),也可以是通过fopen函数打开的文件指针。
fprintf示例用法:
#include <stdio.h>
int main() {
FILE *file = fopen("output.txt", "w");
if (file != NULL) {
int age = 20;
float height = 1.75;
char name[] = "John";
fprintf(file, "My name is %s.\n", name);
fprintf(file, "I am %d years old.\n", age);
fprintf(file, "I am %.2f meters tall.\n", height);
fclose(file);
}
return 0;
}
以上代码将输出打印到名为"output.txt"的文件中。
fscanf其原型如下:
int fscanf(FILE *stream, const char *format, ...);
其中,stream是一个指向要读取数据的文件指针,format是一个字符串,包含了要读取的数据类型和格
式控制符,...表示可变数量的指针参数,用于读取不同类型的数据并将其存储到相应的变量中。
fscanf函数的用法与scanf函数类似,只是需要指定从哪个文件中读取数据。stream可以是标准输入流
(stdin),也可以是通过fopen函数打开的文件指针。
fscanf示例用法:
#include <stdio.h>
int main() {
FILE *file = fopen("input.txt", "r");
if (file != NULL) {
int age;
float height;
char name[50];
fscanf(file, "%s", name);
fscanf(file, "%d", &age);
fscanf(file, "%f", &height);
printf("My name is %s.\n", name);
printf("I am %d years old.\n", age);
printf("I am %.2f meters tall.\n", height);
fclose(file);
}
return 0;
}
以上代码从名为"input.txt"的文件中读取数据,并通过printf函数将其打印到屏幕上。