I/O库函数
1. I/O库函数
系统调用是文件操作的基础,但只支持数据块的读写,I/O库函数能以最适合应用程序的逻辑单元读写,这也就是我们学习I/O库函数的意义
2 . I/O库函数与系统调用
在Unix/Linux中,I/O库函数建立在系统调用的基础上
- 系统调用函数:
open() , read(), write(), lseek(), close() - I/O库函数:
open() , read(), write(), lseek(), close()
示例9.1, 示例9.2分析了fopen, fwrite ,fread I/O库函数与open,write, read系统调用的区别
每个I/O库函数的根都在对应的系统调用函数中。fopen()依赖于open(), fread()依赖于read(),
- 系统调用中,文件描述符fd是一个整数变量,I/O中,fp是文件流指针
- open的返回值是整数文件描述符fd,I/O库函数fopen。返回一个FILE结构体指针,如果fopen()失 败,则返回NULL, FILE结构体包含 一个内部缓冲区char fbufIBLKSIZE]和一个整数fd字段:,它记录open。在FILE结构体中 返回的文件描述符,将初始化为空,并将FILE结构体的地址返回。
-
如果FILE结构体中的fbuff] 为空,则发出read(fd, fbuf, BLKSIZE)系统调用,从文件中读取BLKSIZE字节,其中 BLKSIZE与文件系统块大小匹配。然后它从fbuf]]返回一个char.随后,fgetc()从fbuf[] 返回一个char,只要它仍然有数据一这样,库I/O read函数发出read。系统调用,仅用于重 新填充fbutl ],它们总是将BLKSZ1SE字节的数据从操作系统内核传输到用户空间
I/O库函数的算法
fread算法
fread函数从文件流中读取数据,对应于系统调用中的read;fwrite函数从文件流中写数据,对应于系统调用中的write
函数原型:
#include<stdio.h>
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
参数说明:
*ptr 要读取数据的缓冲区,也就是要存放读取数据的地方。
size:指定每个数据记录的长度。
nitems: 计数,给出要传输的记录个数。
返回值:成功读取到数据缓冲区的记录个数,当到达文件尾时,他的返回值可能会消耗与nitems,甚至可以是0
size_t fwrite(const coid *ptr, size_t size , size_t nitimes, FILE *stream);
他从指定的数据缓冲区ptr中把数据写入文件流,返回成功写入的记录个数。
fwrite函数
fWrite()算法与fread()算法相似,只是数据传输方向不同,最开始,FILE结构体的内 部缓冲区是空的'在每次调用fwrite。时,它将数据写人内部缓冲区,并调整缓冲区的指 针、计数器和状态变量,以跟踪缓冲区中的字节数。如果缓冲区已满,则发出write。系统
调用,将整个缓冲区写入操作系统内核。
fclose函数
fclose函数关闭指定的文件流stream,这个操作会使所有未写出的数据都写出。因为stdio库函数会对数据进行缓冲,所有调用fclose函数是很重要的。
如果程序需要确保数据已经全部写出,就应该调用fclose函数。虽然程序正常结束时,也会自动的调用fclose函数,但这样就不能检测出调用fclose所产生的错误了。
函数原型如下:
#include<stdio,h>
int fclose(FILE *stream);
I/O库模式
fopen()中的模式参数可以指定为:"r"、" w"、"a”,分别代表读、写、追加。每个模式字符串可包含一个+号,表示同司时读写,或者在写入、追加情况下,如果文件不存在则创建文件。
"r+":表示读/写,不会截断文件。
"w+":表示读/写,但是会先截断文件; 如果文件不存在,会创建文件。
"a+":表示通过追加进行读/写;如果文件不存在,会创建文件
字符模式I/O
int fgetc(FILE *fp);//返回的是整数
int ungetc(int c,FILE *fp);
int fputc(int c,FILE *fp);
行模式I/O
char *fgets(char *buf,int size,FILE *fp)//从fp中读取最多为一行(以\n结尾)的字符。
int fputs(char *buf,FILE *fp)//将buf中的一行写入fp中。
格式化I/O
//格式化输出:(FMT=格式字符串)
scanf(char *FMT,&items);
fscanf(fp,char *FMT,&items);
//格式化输出:
printf(char *FMT,items);
fprintf(fp,char *FMT,items);
内存中的转换函数
sscanf(buf,FMT,&items);
sprintf(buf,FMT,items);
注意,sscanf()和sprintf()并非I/O函数,而是内存中的数据转换函数。例如,atoi()是 一个标准库函数,将一串ASCII数字转换成整数,但是大多数Unix/Linux系统没有itoA() 函数,因为转换可由sprintf完成,所以不需要它。
其他I/O库函数
- fseek()、ftell()、rewind():更改文件流中的读/写字节位置。
- •feof()、ferr()、fileno。:测试文件流状态。
- fdopen():用文件描述符打开文件流。
- freopen():以新名称重新打开现有的流。
- setbuf。、setvbuf。:设置缓冲方案。
- popen():创建管道,复刻子进程来调用sh。
限制混合 fread-fwrite
由于不同的系统对于读写指针的处理方式不同导致得到不同结果
fread()/ fwrite()会发出read()/write()系统调用来填充/清除内部缓冲区。当read()/write()使用文件 OFTE中的读/写指针时,fread()/fwrite()会使用FILE结构体中局部缓冲区的读/写指针。 如果没有fseek()来同步这两个指针,其结果就取决于它们在实现中的使用方式。
解决方式:
fseek(fp, (long)20, 0);
插在freadyufwrite之间
文件流缓冲
每个文件流都有一个FILE结构体,其中包含一个内部缓冲区。对文件流进行读写需要 遍历FILE结构体的内部缓冲区
- 无缓冲
- 行缓冲
- 全缓冲
变参函数
在I/O库函数中,printf()相当独特,因为多种不同类型的可变数量参数可以调用它。这 是允许的,因为最初的C语言不是一种类型检查语言。这些函数必须至少使用 一个参数进行声明,后跟3个点,
myprintf()的算法
假设格式字符串fmt=“char=%c string=%s integer=%d u32=%x\n”。这意味着分别有 char、char*、int、unsigned int和type的4个附加参数。myprint()的算法如下:
(1)扫描格式字符串fmt。打印任何不是%的字符。对于每个‘n’字符,打印一个额外的'\r字符。
(2)当遇到‘%’时,得到的下一个字符必须是‘c’、‘s’、‘u’、‘d’或‘x’中的一个。使用va_arg(ap,type)来提取相应的参数。然后后通过参数类型调用打印函数。
(3)当fmt字符串扫描结束时,算法结束
问题解决
文件操作都有什么?
文件的操作命令
(1)文件的创建
命令:touch 文件名称 —– 空文件
(2)文件的查看
命令:cat/more/less/tail 文件
(3)修改文件的内容
命令:vim 文件
(4)删除文件
同目录删除: rm -rf 文件
压缩文件的操作命令
Linux中的打包文件一般是以.tar结尾的,压缩的命令一般是以.gz结尾的。
而一般情况下打包和压缩是一起进行的,打包并压缩后的文件的后缀名一般.tar.gz。
命令:tar -zcvf 打包压缩后的文件名 要打包压缩的文件
其中:z:调用gzip压缩命令进行压缩
c:打包文件
v:显示运行过程
f:指定文件名
(2)解压压缩包
命令:tar [-xvf] 压缩文件
其中:x:代表解压
二进制文件和文本文件如何转换?
https://blog.csdn.net/renyongwang1988/article/details/8050506
#include <cstdio>
#include <stdio.h>
#include <string.h>
#define NSIZE 8
void print_2(int val2);
/***********文本文件转二进制**********/
void Text2Bin(const char* sIn,const char* sOut){
char a[255];
int count = 0;
int ch;
for(int j=0; j<255;j++)a[j]='\0';
FILE* fin=fopen(sIn,"r");
FILE* fout=fopen(sOut,"w");
for(int i=0 ; i<=255 ; i++)fscanf(fin,"%c",&a[i]);
for(int k=0 ; k<=254&&a[k] !='\0'; k++)
{
ch = a[k];
for(int a=7;a>=0;a--) fprintf(fout,"%d",ch>>a&1);
//fprintf(fout,"\n");
}
fclose(fin);
fclose(fout);
}
/***********二进制文件转文本文件**********/
void Bin2Text(const char* sIn,const char* sOut){
FILE* fin=fopen(sIn,"r");
FILE* fout=fopen(sOut,"w");
char str[255*8];
for(int r=0; r<255 ;r++) str[r]='\0';
int i = 0, j = 0, iTemp = 0, flag = 0;
int ibina[NSIZE];
char cRead[NSIZE];
char cChar;
for(int a=0 ; a<=255 ; a++)fscanf(fin,"%c",&str[a]);
//for(int f=0 ; f<=255 ; f++)printf("%c",str[f]);
while(flag <= 255){
//printf("%d",flag);
for(int b=flag ; b>=flag && b<flag+NSIZE ; b++)
{
//printf("%d",b%8);
cRead[b%8] = str[b];
//printf("%c",cRead[b%8]);
}
for(i = 0; i < NSIZE; i++)
{
ibina[i] = (cRead[i]-'0');
}
iTemp = 1;
cChar = 0;
for(j = 7; j >=0 ; j--)
{
//printf("%c",ibina[j]);
//printf("%d\n",cChar);
cChar+=ibina[j]*iTemp;
iTemp *= 2;
}
printf("%c",cChar);
fprintf(fout,"%c",cChar);
flag=flag+8;
}
fclose(fin);
fclose(fout);
}
int main(){
Text2Bin("d:\\a1.txt","d:\\a2.txt");
Bin2Text("d:\\a2.txt","d:\\b2.txt");
printf("\nSuccessfully converted file!\n");
return 0;
}
数据结构如何读写
从文件读取结构体
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char c;
char *str;
char s[100];
int h;
} st;
int main(void)
{
FILE *fp;
st sb;
fp=fopen("st.txt","r");
if(!fp)
{
printf("errror!\n");
exit(-1);
}
fread(&sb,sizeof(sb),1,fp);
printf("sb:c=%c,str=%s,s=%s,h= %d\n", sb.c, sb.str, sb.s, sb.h);
printf("sizeof(sb)=%d:&c=%x,&str=%x,&s=%x,&h=%x\n", sizeof(sb), &sb.c, &sb.str, &sb.s, &sb.h);
fclose(fp);
return 0;
}
将结构体写入文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char c;
char *str;
char s[100];
int h;
} st;
int main(void)
{
FILE *fp;
st sa, sb;
char *str = "abcdefg";
sa.c = 'K';
sa.str = "abcdefg";
strcpy(sa.s, str);
sa.h = -3;
fp = fopen("st.txt", "w+");
if (!fp)
{
printf("errror!\n");
exit(-1);
}
printf("sa:c=%c,str=%s,s=%s,h= %d\n", sa.c, sa.str, sa.s, sa.h);
printf("sizeof(sa)=%d:&c=%x,&str=%x,&s=%x,&h=%x\n", sizeof(sa), &sa.c, &sa.str, &sa.s, &sa.h);
fwrite(&sa, sizeof(sa), 1, fp);
rewind(fp);
fread(&sb, sizeof(sb), 1, fp);
printf("sa:c=%c,str=%s,s=%s,h= %d\n", sa.c, sa.str, sa.s, sa.h);
fclose(fp);
return 0;
}
实验截图








