webqq网页版广州优化网站排名
linux高级编程——文件IO
- 标准IO:stdio.h
标准IO:stdio.h
IO也就是输入input和输出output;
I: 键盘是标准输入设备,默认输入就是指键盘 /dev/input;
O: 显示器是标准输出设备,默认输出就是指显示器;
stdio是属于C语言标准库,那么它存在哪呢?
stdio.h存放的路径是:/usr/include/stdio.h路径下;
按照常理来说标准输入的实现是放在stdio.c当中,但是在系统当中这个实现文件并不是以.c的形式提供的,而是将stdio.c的文件编译了一下(链接),产生libc.so文件但是该文件当中是没有main函数的,因为该函数的实现是要被调用的所以该文件当中不会有main函数。该文件的后缀名在编译之后变成了.so这个表示这是一个动态库文件。因为系统认为标准C库当中的printf()和scanf()之类的函数被调用的频次比较高,所以该动态库放在linux操作系统当中放着,当要使用到标准输入和输出的相关函数的时候需要向操作系统发生申请。不把它放在a.out当中,可以节省开销,减少代码的冗余。
了解了标准IO那么我们应该怎么样去操作文件呢?
要想了解文件的读写操作就先要去了解流的概念:
流: FILE*
数据从文件当中流入和流出所体现出来的字节流叫做流。
流的分类:
二进制流: 2001 \n
二进制数据的流
文本流:
ASCII码数据的流 \n \t
FILE 结构定义的对象 FILE * 称之为流对象,也叫文件流指针。
文件操作的步骤:
1、打开文件 FILE;
2、io操作,读写操作;
3、关闭文件;
文件读写的相关函数:
**FILE *fopen(const char pathname, const char mode);
fopen()函数打开名为路径名指向的字符串的文件,并将流与之关联
形参:pathname为文件名,mode为打开文件的方式是读还是写;文件打开的方式又可以分为:
w:如果文件已经存在且文件当中有内容则在该模式下再打开文件是会先清空文件,如果文件不存在则会先创建文件然后再打开,具有读写的权限;
w+:在该模式下打开文件后清空而且带创建功能;
r:该模式下表示再打开文件是只具有读的权限;
r+:在该模式下打开文件后不清空文件的内容,可以读取旧的内容也可以写进新的内容;
a和a+:均有写的权限但是如果文件中有内容会接着旧的内容继续写,如果文件不存在则会创建文件然后打开。
*int fgetc(FILE stream);
fgetc()从流中读取下一个字符,并将其作为无符号char强制转换为int,或在文件末尾返回EOF,或错误。
返回值:在文件末尾或出现错误时,将读取的字符作为无符号char强制转换为int或EOF。
应用举例:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE* fp = fopen("1.txt", "r"); if (NULL == fp){printf("fopen error\n");}while(1){int ret = fgetc(fp);if (EOF == ret){break;}printf("%c\n", ret);}fclose(fp);return 0;
}
上述程序打开了1.txt文件并读取里面的内容然后打印。因为fgetc一次只能读取一个字符所以采用了循环读取的方式,fgetc()适合读取小文件在读取大文件时效率比较低。
*int fputc(int c, FILE stream);
fputc()函数是能将转换为无符号char的字符c写入流。
返回值:在出错时将写为无符号char的字符转换为int或EOF。
应用举例:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE *fp = fopen("1.txt", "w");if (NULL == fp){printf("fopen error\n");return 1;}int ret = fputc('h', fp);if (-1 == ret){printf("fputs error\n");return 1;}fputc('e', fp);fputc('l', fp);fputc('l', fp);fputc('o', fp);fclose(fp);return 0;
}
上述程序是把hello 写入了打开的1.txt文件当中。
**char *fgets(char s, int size, FILE stream);
fgets()从流中最多读取一个小于大小的字符,并将其存储到s指向的缓冲区中在EOF或换行符后停止。如果读取换行符,则将其存储到缓冲区中。终止符’\0’,存储在缓冲区中最后一个字符之后。
形参当中的s为读取缓冲区该缓冲区是本地内存当中的一段空间在读取大文件时通常缓冲区的大小设置在1k到4k之间,读取的过程是将文件的内容先读取到缓冲区然后再将缓冲区的内容读取到指定文件当中。
返回值:读取成功时返回s,出错时返回NULL,或者在没有读取字符的情况下发生文件结束时返回NULL。
应用举例:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE* fp = fopen("/etc/passwd", "r");if (NULL == fp || NULL == fp2){printf("fopen error\n");return 1;}char buf[1024] = { 0 };while(1){char * s = fgets(buf, 1024, fp);if (NULL == s){break;}printf("%s\n", s);}fclose(fp);return 0;
}
上述程序把/etc/passwd文件的内容读取后并打印,char buf[1024] = { 0 };这就是把文件中的内容读取到缓冲区这一个过程是通过fgets(buf, 1024, fp);实现的,然后接收并打印返回值。
**int fputs(const char s, FILE stream);
参数:
const char *s表示要写入的内容;
FILE *stream表示要写入的目标流文件;
fputs()将字符串s写入流,而不将’\0’写入。
返回值:成功写入时返回非负数,错误时返回EOF。
应用举例:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE* fp = fopen("1.txt", "w");if (NULL == fp){printf("fopen error\n");return 1;}char data[] = "hello world!";int ret = fputs(data, fp);if (EOF == ret){printf("fputs error\n");return 1;}fclose(fp);return 0;
}
上述程序通过fputs(data, fp);将data字符数组中的内容将hello world!字符串写进了1.txt文件当中。
通过fgets()和fputs()函数实现拷贝的功能:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE* fp = fopen("/etc/passwd", "r");FILE* fp2 = fopen("2.txt", "w");if (NULL == fp || NULL == fp2){printf("fopen error\n");return 1;}char buf[1024] = { 0 };while(1){char * s = fgets(buf, 1024, fp);if (NULL == s){break;}int ret = fputs(s, fp2);if(EOF == ret){printf("fputs error\n");return 1;}}fclose(fp);fclose(fp2);return 0;
}
上述程序把/etc/passwd文件当中的内容读取到缓冲区然后将缓冲区的内容写入2.txt文件当中,从而实现了拷贝的效果但是在拷贝照片文件时会发生照片的大小被缩小的问题,原因是:fgets()在读取时遇到\n就停止了在照片的二进制文件当中会存在\n所以在读取时不能将文件中的内容完整地读取而导致读取内容所占的字节数缩小。
**size_t fread(void ptr, size_t size, size_t nmemb, FILE stream);
函数fread()从流指向的流中读取nmemb个数据项(nmenb是可以指定的),每个数据项的长度为字节,并将其存储在由ptr给出的位置。
返回值:返回读取或写入的项目数。此数字等于传输的字节数仅当大小为1时才使用。如果发生错误,或者到达文件末尾,则返回值是一个零。
参数:
void *ptr表示读取到的数据存储的地方;
size_t size:表示读取每个项目是所占的字节数;
size_t nmemb:读取个数;
FILE *stream:表示从哪里读数据;
应用举例:
#include <stdio.h>
#include <string.h>typedef struct
{char name[50];int age;char phone[15];
}PER;int main(int argc, const char *argv[])
{FILE* fp = fopen("1.txt", "r");if (NULL == fp){printf("fopen error\n");}PER per;bzero(&per, sizeof(PER));//在读取前将per变量清0;size_t ret = fread(&per, sizeof(PER), 1, fp);printf("name : %s age : %d phone : %s\n", per.name, per.age, per.phone);//如果能正常打印就说明读取成功;if (ret != 1){printf("fread error\n");}fclose(fp);return 0;
}
size_t fwrite(const void ptr, size_t size, size_t nmemb, FILEstream);
函数fwrite()将nmemb个数据项(每个大小为字节长)写入流指向的流中,并获取它们从ptr给出的位置。
返回值同fread;
简单的应用举例:
#include <stdio.h>
#include <string.h>typedef struct
{char name[50];int age;char phone[15];
}PER;int main(int argc, const char *argv[])
{FILE* fp = fopen("1.txt", "w");if (NULL == fp){printf("fopen error\n");return 1;}PER per;strcpy(per.name, "xuan");per.age = 18;strcpy(per.phone, "11223344556677");size_t ret = fwrite(&per, sizeof(PER), 1, fp);if (ret != 1){printf("fwrite error\n");return 1;}fclose(fp);return 0;
}
上述程序通过fwrite(&per, sizeof(PER), 1, fp);就能写入一个per大小的结构体变量per的内容到1.txt间当中。
今天先到这明天再更新!