学习系统,你学习的就是人家的函数。
各种函数,而且这些函数是人家系统封装好的,你只需要学会调用就可以了。那么学习系统的方法就是学习函数
① 明白函数的功能
② 函数的参数:每一个参数所代表的含义,以及你实现这个功能需不需要使用这个参数
③ 函数的返回值:这个函数成功与否全部取决他的返回值
FILE指针
系统为打开文件建立的结构体 打开的时候 返回这个结构体的指针
当文件关闭的时候 会释放这个结构体
FILE *
struct _iobuf
{
char *_ptr;//当前缓冲区内容指针
int _cnt;//缓冲区还有多少个字符
char *_base;//缓冲区的起始地址
int _flag;//文件流的状态,是否错误或者结束
int _file;//文件描述符
int _charbuf;//双字节缓冲,缓冲2个字节
int _bufsiz;//缓冲区大小
char *_tmpfname;//临时文件名
};
typedef struct _iobuf FILE;
文件是存储在外部介质(硬盘、u盘)数据的集合
在linux下文件的类型共分为7类:
普通文件 - (regular file)
目录文件 d (directory file)
字符设备文件 c (char file)
块设备文件 b (block file)
管道文件 p (pipe file)
链接文件 l (link file)
套接字文件 s (socket file)
标准的文件描述符:每个程序在执行的时候 会默认的打开三个文件描述符
0: 标准输入 stdin 默认就是键盘 有缓存
1: 标准输出 stdout 默认就是显示器 有缓存
2: 标准错误 stderr 默认就是显示器 没有缓存
面试题:2>&1 将标准错误重新定向到标准输出
>:表示重定向 假如重定向到文件里,会把文件里原有的内容清空
>>:表示重定向 假如重定向到文件里,会在文件的末尾追加内容
linux的比较重要的思想:一切皆文件
缓冲区的特点及作用:
什么是缓存?缓存就是一块内存(缓冲区),是用来暂时存储一些文件信息的
特点:读或者写的操作下,先将内容写到缓冲区,当满足了一定的条件之后 (遇到\n、fflush、return、exit、缓冲区满等),再将缓冲区里的内容写入到文件里
作用:cpu的处理速度很快,假如要操作数据,比如直接从硬盘里读数据会浪费cpu的资源。 缓冲区的作用就是为了协调低速的输入设备和高速的cpu的
缓冲区相关文件操作:
(1)文件的打开:fopen
函数的功能:打开一个文件
函数的头文件:stdio.h
函数的原型: FILE *fopen(const char *path, const char *mode);
函数的参数:const char *path:要打开的文件(文件路径)
const char *mode:打开文件的方式
r: 只读的方式打开。文件必须要存在(如果文件不存在,将报错)
r+:读写的方式打开。文件必须要存在
w:只写的方式打开。假如文件不存在,则创建;假如文件存在,则清空文件内容
w+:读写的方式打开。假如文件不存在,则创建;假如文件存在,则清空文件内容
a:追加写。假如文件不存在,则新建;假如文件存在,则追加写在文件的末尾
a+:读写和追加的方式。假如文件不存在,则创建
假如文件存在且要读,光标在文件头;假如文件存在且要写,光标在文件尾
函数的返回值:成功返回:文件流指针(返回一个地址)
失败返回:NULL
(2)文件的关闭:fclose
函数的功能:关闭一个文件
函数的头文件:stdio.h
函数的原型: int fclose(FILE *stream);
函数的参数:FILE *stream:文件的流指针
函数的返回值:成功返回:0
失败返回:非零(比如:-1)
文件打开或者关闭的时候要注意的事项:
1:文件存在不存在要清楚
2:你下一步要进行的操作
3:打开成功不成功
4:异常退出的情况下 文件要关闭
(3)单字符读写:getchar putchar fputc fgetc
int getchar(void):从键盘获取一个字符
int putchar(int c):向屏幕输出一个字符
int fputc(int c, FILE *stream): 向文件写入一个字符(c:要写入的字符;stream:文件指针(要有可写权限)) 成功返回:字符c 失败返回:EOF
int fgetc(FILE *stream): 从文件里读取一个字符(成功返回:读出的字符;失败返回: EOF)
int feof(FILE *stream):判断文件的读写指针是否到文件尾
假如到文件尾 会返回1
假如没有到文件尾 会返回0
1 #include<stdio.h>//对一块程序注释掉:#if 0....程序块.....#endif
2 #include<unistd.h>
3 FILE *fp;
4 int main()
5 {
6 fp=fopen("./test.c","w+");
7 if(fp==NULL)
8 {
9 perror("fopen");
10 }
11
12 putchar('a');
13 printf("getchar:%c\n",getchar());
14 printf("\n");
15
16 fputc('b',stdout);
17 printf("fgetc:%c\n",fgetc(stdin));
18 printf("\n");
19 sleep(2); //睡眠2秒
20 fclose(fp);
21 return 0;
22 }
(4)字符串读写:fgets fputs
char *fgets(char *s, int size, FILE *stream):从stream里取一串大小为 size 的字符串放到 s 里
函数的返回值:成功返回:返回读取到的字符串
失败返回:NULL
int fputs(const char *s, FILE *stream):写一串字符串 s 到stream里
函数的返回值:成功返回:0
失败返回:-1
1 #include<stdio.h>
2 #include<unistd.h>
3 FILE *fp;
4 int main()
5 {
6 fp=fopen("./test1.c","w+");
7 if(fp==NULL)
8 {
9 perror("fopen");
10 return -1;
11 }
12
13 fputs("hello!",fp);
14 rewind(fp);
15 char buf[10];
16 printf("fgets:%s\n",fgets(buf,4,fp));
17 printf("\n");
18
19 sleep(2); //睡眠2秒
20 fclose(fp);
21 return 0;
22 }//fgets:hel
(5)块读写:fread fwrite
①:函数的功能:按块读
函数的头文件:stdio.h
函数的原型: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
函数的参数:void *ptr:读到的数据存放的位置
size_t size:每次读取的大小
size_t nmemb:读取的次数
FILE *stream:文件的流指针
函数的返回值:成功返回:成功读取的块数(即读取的次数)
失败返回:0
②:函数的功能:按块写(将缓冲区里的内容写入到你指定的文件里)
函数的头文件:stdio.h
函数的原型: size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
函数的参数:const void *ptr:你要写的内容
size_t size:你要写的内容的大小
size_t nmemb:你要写的次数
FILE *stream:文件的流指针
函数的返回值:成功返回:成功写入的块数
失败返回:0
1 #include<stdio.h>
2 #include<unistd.h>
3 FILE *fp;
4 int main()
5 {
6 fp=fopen("./test1.c","w+");
7 if(fp==NULL)
8 {
9 perror("fopen");
10 return -1;
11 }
12 printf("fwrite:%ld\n",fwrite("hello!",5,2,fp));
13 rewind(fp);
14 char buf[100];
15
16 printf("fread:%ld\n",fread(buf,5,2,fp));
17 printf("buf:%s\n",buf);
18 printf("\n");
19
20 sleep(2); //睡眠2秒
21 fclose(fp);
22 return 0;
23 }//fwrite:2 fread:2 buf:hello!
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<string.h>
4 FILE *fp;
5 int main()
6 {
7 fp=fopen("./test1.c","w+");
8 if(fp==NULL)
9 {
10 perror("fopen");
11 return -1;
12 }
13 printf("fwrite:%ld\n",fwrite("hello!",5,2,fp));
14 rewind(fp);
15 char buf[100];
16
17 memset(buf,0,sizeof(buf));
18 printf("fread:%ld\n",fread(buf,5,2,fp));
19 printf("buf:%s\n",buf);
20
21 sleep(2); //睡眠2秒
22 fclose(fp);
23 return 0;
24 }//fwrite:2 fread:2 buf:hello!
(6)格式化读写:fscanf fprintf
int fscanf(FILE *stream, const char *format, ...):格式化的从一个流里读取内容
fscanf(fp,"%s",buf)
含义:从fp执行的文件里按照%s的方式获取,将获取到的内容存放到buf里
char buf[20];
int num;
fscanf(fp,"%s %d",buf,&num)
int fprintf(FILE *stream, const char *format, ...):格式化的向一个流里写入内容
fprintf(fp,"%s","hello world");
1 #include<stdio.h>
2 #include<unistd.h>
3 // #include<string.h>
4 FILE *fp;
5 int main()
6 {
7 fp=fopen("./test1.c","w+");
8 if(fp==NULL)
9 {
10 perror("fopen");
11 return -1;
12 }
13 fprintf(fp,"%c\n",getchar());
14 rewind(fp);
15 char buf[100];
16
17 fscanf(fp,"%c\n",buf);
18 // memset(buf,0,sizeof(buf));
19 printf("buf:%s\n",buf);
20
21 sleep(2); //睡眠2秒
22 fclose(fp);
23 return 0;
24 }//输入w,输出buf:w
(7)文件指针定位:rewind fseek ftell
①:rewind
函数的功能:重新将读写指针放到文件头
函数的头文件:stdio.h
函数的原型:void rewind(FILE *stream);
函数的参数:FILE *stream:文件的流指针
函数的返回值:无
②:fseek
函数的功能:将读写指针定位到指定的位置
函数的头文件:stdio.h
函数的原型:int fseek(FILE *stream, long offset, int whence);
函数的参数:FILE *stream:文件的流指针
long offset:偏移量(正数时,向右偏移;负数时,向左偏移)
int whence:参考位置
参考位置:
SEEK_SET:文件开头
SEEK_CUR:当前位置(current 当前的)
SEEK_END:文件的末尾(end 结尾)
函数的返回值:成功返回:0
失败返回:-1
③:ftell
函数的功能:返回当前文件读写指针的位置,常用来计算文件的大小
函数的头文件:stdio.h
函数的原型:long ftell(FILE *stream);
函数的参数:FILE *stream:文件的流指针
函数的返回值:返回指针的位置
(8)输出错误:perror
perror():输出错误的信息
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<string.h>
4 FILE *fp;
5 int main()
6 {
7 fp=fopen("./test1.c","w+");
8 if(fp==NULL)
9 {
10 perror("fopen");
11 return -1;
12 }
13
14 fprintf(fp,"%c",getchar());
15 fseek(fp,0,SEEK_END);
16 printf("ftell:%ld\n",ftell(fp));
17 char buf[100];
18
19 memset(buf,0,sizeof(buf));
20 fscanf(fp,"%c",buf);
21 printf("buf:%s\n",buf);
22
23 sleep(2); //睡眠2秒
24 fclose(fp);
25 return 0;
26 }//输入w,输出ftell:1 buf:
非缓冲区文件操作
fd,即file descriptor,文件描述符。linux下,所有的操作都是对文件进行操作,而对文件的操作是利用文件描述符(file descriptor)来实现的。每个文件进程控制块中都有一份文件描述符表(可以把它看成是一个数组,里面的元素是指向file结构体指针类型),这个数组的下标就是文件描述符。在源代码中,一般用fd作为文件描述符的标识。
(1)文件的打开:open
函数的功能:打开一个文件
函数的头文件:#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数的原型: int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
函数的参数:const char *pathname:打开文件
int flags:打开的方式
mode_t mode:权限 (一般是配合O_CREAT使用的。它实际得到的权限是减去掩码的值。查看掩码:umask,值为0002;修改掩码的值:umask 0000)
打开方式:
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
O_CREAT:假如文件不存在则新建
O_APPEND:追加
比如要以只写的方式打开文件 并且假如文件不存在,则新建:O_WRONLY|O_CREAT
函数的返回值:成功返回:文件的描述符
失败返回:-1
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<fcntl.h>
5
6 int main()
7 {
8 int fd;
9 fd=open("test3.c",O_RDONLY|O_CREAT);
10 printf("fd:%d\n",fd);
11 return 0;
12 }//fd:3
----r-s--- 1 ldw ldw 0 6月 23 22:06 test3.c
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<fcntl.h>
5
6 int main()
7 {
8 int fd;
9 fd=open("test2.c",O_RDONLY|O_CREAT,0777);
10 printf("fd:%d\n",fd);
11 return 0;
12 }//fd:3
-rwxrwxr-x 1 ldw ldw 0 6月 23 22:00 test2.c
第9行第三个参数:
111 111 101
rwx rwx r-x
7 7 5
(2)文件的关闭:close
函数的功能:关闭一个文件
函数的头文件:#include <unistd.h>
函数的原型:int close(int fd);
函数的参数:fd:文件的描述符
函数的返回值:成功返回:0
失败返回:-1
(3)文件的读写:read write
① read
函数的功能:从打开的文件里读取内容
函数的头文件:#include <unistd.h>
函数的原型:ssize_t read(int fd, void *buf, size_t count);
函数的参数:int fd:打开的文件的描述符
void *buf:读取到的内容存放的位置
size_t count:要读取的字节数
函数的返回值:成功返回:读到的字节数
失败返回:-1
② write
函数的功能:向一个已打开的文件写入内容
函数的头文件:#include <unistd.h>
函数的原型:ssize_t write(int fd, const void *buf, size_t count);
函数的参数:int fd:打开的文件的描述符
const void *buf:要写入的内容
size_t count:要写入的字节数
函数的返回值:成功返回:成功写入的字节数
失败返回:-1
(4)指针定位:lseek
函数的功能:重新定位文件的读写指针的位置
函数的头文件:#include <sys/types.h>
#include <unistd.h>
函数的原型:off_t lseek(int fd, off_t offset, int whence);
函数的参数:int fd:打开的文件的描述符
off_t offset:偏移量 可正可负
int whence:参考位置(SEEK_SET :文件的开头;SEEK_CUR:当前的位置;SEEK_END:文件的末尾)
函数的返回值:成功返回:指针距离文件头的距离
失败返回:-1
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<fcntl.h>
5 #include<unistd.h>
6
7 int main()
8 {
9 int fd;
10 char buf[10];
11 fd=open("test4.c",O_RDWR|O_CREAT,0777);
12 printf("fd:%d\n",fd);
13
14 printf("write:%ld\n",write(fd,"hello",5));
15 lseek(fd,0,SEEK_SET);
16 sleep(1);
17
18 printf("read:%ld\n",read(fd,buf,5));
19 printf("buf:%s\n",buf);
20 sleep(2);
21 close(fd);
22 return 0;
23 }//fd:3 write:5 read:5 buf:hello