标准IO操作
一、文件操作
1.linux下的文件类型
b:块设备文件 存储类设备(硬盘sdo,sdi等)
c:字符设备文件 输入设备(鼠标键盘等),输出设备(显示屏等)
d:目录文件:文件夹
-:普通文件:.c .h a.out .jpg .mp4等
l:软链接文件:快捷方式
s:套接字文件:网络通信等
p:管道文件:进程间通信
二、文件操作方法
linux系统下有两种文件操作方法:标准io和文件io。
标准IO:c库提供的一套对文件操作的操作方法——库函数(标准库)。
文件IO:linux内核提供的一套文件操作的操作方法——系统调用。
文件操作步骤:1.打开文件;2.对文件实现读写;3.关闭文件。
标准IO文件操作:1.打开文件 fopen;
2.读写fgetc/fputc fgets/fputs fread/fwrite;
3.关闭文件 fclose。
三、标准IO函数
1.FILE * fopen(const char *pathname , const char * mode)
功能:打开一个文件获得一个文件流指针。(文件流:数据从文件流入流出体现出来的字节流)
参数:pathname:打开的文件的路径地址;mode:打开方式
打开方式包括:
“r” 只读不写,文件需存在;“r+”,以读写的方式打开,文件需存在;
“w”如果文件存在则清空,反之以只写的方式创建文件并打开;
“w+”如果文件存在则清空,以读写的方式打开,反之创建打开;
“a”以追加写的方式打开,文件不存在则创建,存在则续写;
“a+”以读写的方式打开,文件不存在创建,存在则续写。
返回值:打开成功返回文件流指针,失败则为空。
例如:
FILE *fp = fopen("./1.txt", "w+");if(NULL == fp){printf("fopen error\n");return -1;}
标准IO:
FILE ---->文件流
FILE *----->文件流指针
2.fputc/fgetc
int fputc(int c,FILE * stream)
功能:向文件中写入一个字符;
参数:c:要写入的字符;stream要写入的文件的文件流指针;
返回值:成功:对应的ASCII码值,失败:EOF
int fgetc(FILE * stream)
功能:从文件中读取一个字符;
参数:stream:要读取的文件的文件流指针;
返回值:成功:读到的字符对应的ASCII码值;失败,EOF,读到文件末尾,EOF。
利用fputc和fgetc函数完成对文件的拷贝:
#include<stdio.h>int main(int argc, const char *argv[])
{if(argc != 3){printf("We need three inputs!\n");return -1;}FILE *fp = fopen(argv[1], "r");if(NULL == fp){printf("fopen error\n");return -1;}FILE *fc = fopen(argv[2],"w");if(NULL == fc){printf("fopen error\n");}while(1){int ret = fgetc(fp);if(EOF == ret){break;}fputc(ret,fc); }fclose(fp);fclose(fc);return 0;
}
fgetc函数主要打开普通文件:
文本文件:.txt .c .h
二进制文件:.jpg a.out .png .mp4
2.fputs/fgets
int fputs(const char *s,FILE * stream)
功能:向文件中写入字符串;
参数:字符串首地址s,要写入的文件流指针:stream
返回值:成功:非负的整型数据 失败:EOF
int *fgets(char *s, int size , FILE * stream)
功能:从文件中读取下一行数据;
参数:s:用来存放读取到的数据的内存空间的首地址;size:希望从字节中读到的字节数;stream:要读取的文件流指针;
返回值:成功:存储空间的首地址;失败:NULL;读到文件末尾返回NULL;
主要用来处理文本文件而不能处理二进制,因为fputs不能写0,fgets读数据会保留\n;
利用fgets函数和fputs函数进行文件的拷贝:
#include<stdio.h>int main(int argc, const char *argv[])
{if(argc != 3){printf("We need three inputs!\n");return -1;}FILE *fp = fopen(argv[1], "r");if(NULL == fp){printf("fopen error\n");return -1;}FILE *fc = fopen(argv[2],"w");if(NULL == fc){printf("fopen error\n");}char s[11] = {0};fgets(s, 11, fp);fputs(s,fc);fclose(fp);fclose(fc);return 0;
}
fgets和gets的区别:
fgets:
1.从指定的已打开文件中读取最多一行数据(遇到\n停止读取);
2.fgets保留\n字符并字符串末尾添加\0,(s【strlen(s)- 1】=‘\0’);
3.有字节数限制,最多读取n-1个字符,可有效防止缓冲区溢出;
gets:
1.指定从终端设备读取数据;
2.gets会将终端读到的\n字符替换成\0;
3.gets函数是危险的,因为在读取过程中没有字节限制,容易发生内存越界。
3.fread/fwrite
size_t fwrite(const void *ptr,size_t size, size_t nmemb, FILE * stream)
功能:向文件中写入nmemb个大小是size的数据到文件中;
参数:ptr:要写入的数据的首地址;size:每个元素的字节数;nmemb:要写入的元素个数;stream:要写入的文件流指针;
返回值:成功:返回写入元素的个数;失败:
size_t fread(void *ptr ,size_t size,size_t nmemb,FILE *stream)
功能:从文件中读取nmemb个大小是size的元素;
参数:ptr:存储读到数据的首地址;size:每个元素的大小;nmemb:希望从文件中读取的元素个数;stream:要读取的文件流指针。
返回值:成功:读到的元素的个数;读到文件末尾返回0。
fwrite和fread函数主要处理二进制文件。
利用fread和fwrite完成对文件的复制:
#include<stdio.h>
#include<stdlib.h>int main(int argc, const char *argv[])
{if(argc != 3){printf("We need three inputs!\n");return -1;}FILE *fp = fopen("./1.txt","r");if(NULL == fp){printf("open error!\n");return -1;}FILE *fc = fopen("./2.txt","w");if(NULL == fc){printf("open error!\n");fclose(fp);return -1;}fseek(fp,0,SEEK_END);long len = ftell(fp);fseek(fp,0,SEEK_SET);printf("%ld\n",len);fseek(fc, len-1, SEEK_SET);int ret = fputc('\0', fc);if (EOF == ret){printf("磁盘空间不足\n");fclose(fp);fclose(fc);return -1;}rewind(fc);char *buff = malloc(len);size_t t = fread(buff, 1, len, fp);if(t != (size_t)len){printf("read error\n");fclose(fp);fclose(fc);free(buff);return -1;}size_t p = fwrite(buff, 1, len, fc);if(p != t){printf("write error\n");fclose(fp);fclose(fc);free(buff);return -1;}free(buff);fclose(fp);fclose(fc);return 0;
}
4.其他函数
(1)fseek
int fseek (FILE *stream,long offset ,int whence)
功能:实现文件流的重新定位;
参数:stream:需要定位的文件流指针;offset:偏移量(可正可负);whence:定位的相对位置;
相对位置包括:SEEK_SET 从头开始偏移;SEEK_CUR 从当前位置开始偏移;SEEK_END从文件末尾开始偏移;
返回值:成功:返回当前的偏移量;失败:-1。
#include<stdio.h>int main(int argc, const char *argv[])
{FILE *fp = fopen("./2.txt","w");if(NULL == fp){printf("open error!\n");return -1;}fseek(fp,10 ,SEEK_SET);fputc('A',fp);long offset = ftell(fp);printf("offset = %ld\n",offset);fseek(fp,7 ,SEEK_END);fputc('D',fp);offset = ftell(fp);printf("offset = %ld\n",offset);fseek(fp,-2 ,SEEK_END);fputc('B',fp);offset = ftell(fp);printf("offset = %ld\n",offset);fseek(fp,0,SEEK_END);long len = ftell(fp);fseek(fp,0,SEEK_SET);printf("%ld\n",len);fclose(fp);return 0;}
(2)ftell
long ftell(FILE * stream)
功能:获得流的当前位置;
利用ftell完成对文件大小的计算:
fseek(fp,0,SEEK_END);long len = ftell(fp);fseek(fp,0,SEEK_SET);printf("%ld\n",len);fseek(fc, len-1, SEEK_SET);int ret = fputc('\0', fc);if (EOF == ret){printf("磁盘空间不足\n");fclose(fp);fclose(fc);return -1;}rewind(fc);
(3)rewind
void rewind(FILE *stream)
rewind(fp)
重置文件流到开头。实例见上。