IO进程 day02
- 5. 标准IO
- 5.6. 标准IO函数接口(下)
- 5.6.1. fread/fwrite
- 5.6.2. 文件指针偏移函数
- rewind
- ftell
- fseek
- 6. 文件IO
- 6.1. 概念
- 6.2. 文件IO的特点
- 6.3. 文件IO的函数接口
- 6.3.1. open/close
- 6.3.2. read/write
- 6.3.3. lseek
- 标准IO和文件IO的区别
5. 标准IO
5.6. 标准IO函数接口(下)
5.6.1. fread/fwrite
fread
#include <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
失败返回-1
fwrite
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:向指定的文件中写内容
参数:
ptr:向文件中写的内容的首地址
size:写入的元素内容的字节大小,一次写多少个字节
nmemd:写入的元素个数
stream:流指针,指向目标文件
返回值:
成功返回写入的元素个数
失败返回-1
练习
将一个int类型的数组写到文件中保存,并且读出来
#include <stdio.h>int main(int argc, char const *argv[])
{FILE *fp = NULL;int arr[5] = {1, 2, 3, 4, 5};int str[5] = {};// 打开文件fp = fopen("./file1.c", "w+");if (fp == NULL){perror("open err");return EOF;}// 写入文件fwrite(arr, sizeof(int), 5, fp);// 移动文件指针fseek(fp, 0, SEEK_SET);// 读文件fread(str, sizeof(int), 5, fp);for (int i = 0; i < 5; i++)printf("%-4d", str[i]);// 关闭文件fclose(fp);fp = NULL;return 0;
}
5.6.2. 文件指针偏移函数
rewind
#incldue <stdio.h>
void rewind (FILE *stream)
功能:将文件指针移动到文件开头
参数:流指针,指向打开的文件
ftell
#include <stdio.h>
long ftell(FILE *stream);
功能:计算文件指针当前所在位置,相对于文件开头
参数:流指针,指向打开的文件
返回值:成功返回文件指针所在位置,失败返回-1,并更新errno
fseek
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:将文件指针偏移到指定位置
参数:
stream:流指针,指向目标文件
offset:偏移量:
+5向后偏移5个字节
-5向前偏移5个字节
whence:相对位置
SEEK_SET:文件开头
SEEK_CUR:文件指针当前位置
SEEK_END:文件结尾
返回值:成功返回0,失败返回-1,更新errno
6. 文件IO
6.1. 概念
内核向上提供的输入输出函数接口,叫做系统调用函数接口。基于内核,内核不同,系统调用函数接口不同,文件IO不同操作系统函数接口不通用。可移植性较差。
6.2. 文件IO的特点
1. 没有缓存机制,每次调用都引起系统调用
2. 围绕文件描述符进行操作,文件描述符都是非负整数,依次进行分配
3. 文件IO默认打开三个文件描述符,0(标准输入),1(标准输出),2(标准出错)
4. 文件IO可以操作除了目录文件之外的任意类型的文件
6.3. 文件IO的函数接口
posix 规范 Linux发展的标准
6.3.1. open/close
open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
功能:打开文件
参数:
pathname:文件路径名
flags:打开文件方式
返回值:成功返回文件描述符,失败返回-1;
文件打开方式 | 对应权限 |
---|---|
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 可读可写 |
O_CREAT | 创建 |
O_TRUNC | 清空 |
O_APPEND | 追加 |
注意
当参数中出现O_CREAT(创建)时,函数定义变为
int open(const char *pathname, int flags, mode_t mode);
mode:创建文件的权限,权限的算法:mode &~umask
umask:文件权限掩码,值为0002
权限掩码可修改:
查看权限掩码:umask 修改文件权限掩码:umask 0000
修改后的权限掩码可以与mode保持一致
fopen和open的不同的打开方式
r:O_RDONLY
r+ : O_RDWR
w : O_WRONLY | O_CREAT | O_TRUNC,0666
w+ :O_RDWR | O_CREAT | O_TRUNC,0666
a : O_WRONLY | O_APPEND | O_CREAT,0666
a+ : O_RDWR | O_APPEND | O_CREAT,0666
close
#include <unistd.h>int close(int fd);
功能:关闭文件
6.3.2. read/write
read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:读文件
参数:
fd:文件描述符
buf:存放内容的首地址
count:期待读取到的字符个数
返回值:
成功返回实际读取到的字符个数,读到文件结尾返回0
失败返回-1,并更新errno
注意
read读文件时count是多少就读多少,不会自动补‘\0’,遇到\n也不会自动停止,会继续读取下一行的内容。所以需要预留一个\0的位置
使用技巧
- 通过返回值作为实际读到的字符个数
char buf[32];
ssize_t ret = read(fd, buf, 31);
buf[ret] = '\0';
- 每次读取到的内容放到数组之前先清空数组
write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:写文件
参数:
fd:文件描述符
buf:写入内容的首地址
count:期待写入到的字符个数
返回值:
成功返回实际写入的字符个数
失败返回-1,并更新errno
读多少写多少
ssize_t ret = read(fd1,buf,64);
write(fd2,buf,ret);
练习
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define N 32int main(int argc, char const *argv[])
{int fd1 = -1;int fd2 = -1;char buf[N] = {};ssize_t ret = 0;// 命令行传参判错if (argc != 3){perror("argc err");return -1;}// 以只读的方式打开文件fd1fd1 = open(argv[1], O_RDONLY);if (fd1 == -1){perror("open fd1 err");return -1;}// 以只写的方式打开fd2fd2 = open(argv[2], O_WRONLY);if (fd2 == -1){perror("open fd2 err");return -1;}// 读多少写多少while (ret = read(fd1, buf, sizeof(buf)))ret = write(fd2, buf, ret);close(fd1);close(fd2);return 0;
}
6.3.3. lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:将文件指针偏移到指定位置
参数:
fd:文件描述符
offset:偏移量: +:向后 -:向前
whence:相对位置
SEEK_SET:文件开头
SEEK_CUR:当前位置
SEEK_END:文件结尾
返回值:
成功基于文件开头返回当前位置
失败返回-1,更新errno
标准IO和文件IO的区别
标准IO | 文件IO | |
---|---|---|
概念 | C库定义的用于输入输出的函数 | 系统中定义的用于输入输出的函数 |
特点 | 1. 有缓冲机制 2. 围绕流进行操作,FILE* 3. 默认打开三个流:stdout/stdin/stderr | 1. 无缓冲机制 2. 围绕文件标识符进行操作,非负整数 3. 默认分配三个文件标识符,0,1,2 4. 可以操作除目录文件外所有文件 |
函数 | 打开关闭文件:fopen/fclose 读写:fgetc/fputc;fgets/fputs;fread/fwrite 定位:fseek/rewind/ftell 时间:time/loacltime 其他:fflush/fprintf/perror | 开关文件:open/close 读写操作:read/write 定位:lseek |