目录
【1】什么是文件IO
1》概念
2》特点
3》操作
【2】函数接口
1》打开文件open()
思考:文件IO和标准IO的打开方式的对应关系
2》关闭文件 close()
3》读写文件 read write
1> 读文件 read()
2> 写文件 write()
练习:文件IO实现cp功能。cp 源文件 新文件名
4》文件定位操作 lseek
练习:向文件中第 10 位置后面写一个字符,在文件此时的位置,往后移动20个位置处,写一行字符串hello进去,求此时文件的长度。
练习: 实现“head -n 文件名”命令的功能
【1】什么是文件IO
1》概念
又称系统IO,是系统调用,是操作系统提供的接口函数。
posix中定义的一组用于输入输出的函数。
POSIX接口 (英语:Portable Operating System Interface)可移植操作系统接口
2》特点
- 没有缓冲机制,每次都会引起系统调用。
- 围绕文件描述符进行操作,非负整数(>=0),依次分配。
- 文件IO默认打开三个文件描述符,分别是0(标准输入)、1(标准输出)和2(标准错误)。
- 操作除了目录d以外任意类型的文件b c - l s p
- 可移植性相对较差
3》操作
文件文件:open
关闭文件: close
读写操作: read和write
定位操作:lseek
【2】函数接口
1》打开文件open()
man 2 open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
功能:打开文件
参数:pathname:文件路径名
flags:打开文件的方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
O_CREAT:不存在创建
O_TRUNC:存在清空
O_APPEND:追加
返回值:成功:文件描述符
失败:-1
当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname, int flags, mode_t mode);
最后权限 = mode &(~umask)
例如:指定权限为0666(8进制)
最终权限= 0666 & (~umask) = 0666 &(~0002) = 664
666 => 110 110 110
&775 111 111 101
664 110 110 100
思考:文件IO和标准IO的打开方式的对应关系
标准IO | 文件IO |
r |
O_RDONLY 只读 |
r+ |
O_RDWR 可读可写 |
w |
O_WRONLY | O_CREAT | O_TRUNC, 0777 只写,不存在创建,存在清空 |
w+ |
O_RDWR | O_CREAT | O_TRUNC, 0777 可读可写,不存在创建,存在清空 |
a |
O_WRONLY | O_CREAT | O_APPEND, 0777 只写,不存在创建,存在追加 |
a+ |
O_RDWR | O_CREAT | O_APPEND, 0777 可读可写,不存在创建,存在追加 |
2》关闭文件 close()
#include <unistd.h>
int close(int fd);
功能:关闭文件
参数:fd:文件描述符
3》读写文件 read write
1> 读文件 read()
ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数: fd 文件描述符
buf 存放位置
count 期望的个数
返回值:成功:实际读到的个数(小于期望值说明实际没这么多)
返回0:表示读到文件结尾
返回-1:表示出错,并设置errno号
fgetc -> EOF 末尾或失败
fgets -> NULL 末尾或失败
fread -> 0 末尾或失败
read -> 0末尾 -1失败
2> 写文件 write()
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd 文件描述符
buf 要写的内容
count 期望写入字节数
返回值:成功:实际写入数据的个数
失败 : -1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd;
char buf[32] = "";
//1.打开文件
fd = open("a.c", O_RDWR); //r+
if (fd < 0)
{
perror("open err ");
return -1;
}
printf("fd: %d\n", fd);
//2. 读写文件
read(fd, buf, 10); //文件中内容为:hello
printf("%s\n", buf); //hello
write(fd, "world", 5);//向文件中写 world
//3.关闭文件
close(fd);
return 0;
}
练习:文件IO实现cp功能。cp 源文件 新文件名
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd1, fd2;
if (argc != 3)
{
printf("err: %s <srcfile> <destfile>\n", argv[0]);
return -1;
}
//1.打开两个文件
fd1 = open(argv[1], O_RDONLY);
if (fd1 < 0)
{
perror("fd1 open err");
return -1;
}
fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd2 < 0)
{
perror("fd2 open err");
return -1;
}
//2.循环读源文件,只要读到就写入目标
char buf[32] = "";
ssize_t n;
while ((n = read(fd1, buf, 32)) > 0)
write(fd2, buf, n);
//while (read(fd1, buf, 1) > 0) //或者
// write(fd2, buf, 1);
//3. 关闭两个文件
close(fd1);
close(fd2);
return 0;
}
4》文件定位操作 lseek
off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符
offset: 偏移量
正数:向文件结尾位置移动
负数:向文件开始位置
whence: 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
补充:和fseek一样其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
返回值:成功:文件的当前位置
失败:-1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd;
fd = open("a.c", O_RDWR);
if (fd < 0)
{
perror("open err");
return -1;
}
//离开头后10个
lseek(fd, 10, SEEK_SET);
write(fd, "k", 1);//在该位置写个 k
off_t off = lseek(fd, 0, SEEK_END);//记录文件长度
printf("%ld\n", off);
return 0;
}
练习:向文件中第 10 位置后面写一个字符,在文件此时的位置,往后移动20个位置处,写一行字符串hello进去,求此时文件的长度。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd;
fd = open("a.c", O_RDWR);
if (fd < 0)
{
perror("open err");
return -1;
}
lseek(fd, 10, SEEK_SET);//从头向后移动10个单位
write(fd, "d", 1);
lseek(fd, 20, SEEK_CUR);//从当前位置向后移动20各单位
write(fd, "hello", 5);
off_t off = lseek(fd, 0, SEEK_END);//计算从头到尾的长度
printf("%ld\n", off);
return 0;
}
练习: 实现“head -n 文件名”命令的功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
if (argc != 3)
{
printf("err: %s -n <filename>\n", argv[0]); //./a.out -n <filename>
return -1;
}
FILE *fp = fopen(argv[2], "r");
if (fp == NULL)
{
perror("fopen err");
return -1;
}
//获取行数
int num = atoi(argv[1] + 1); // +1是为了向后偏移一个地址单位把-去掉获取到要打印的行数
char buf[32] = "";
int len = 0;
//循环读,然后数换行,打印到终端,如果是最后一行就退出
while (fgets(buf, 32, fp) != NULL)
{
if (buf[strlen(buf) - 1] == '\n') //数换行
len++;
if (len > num) //达到行数就退出
break;
fputs(buf, stdout); //打印内容到终端
}
fclose(fp);
return 0;
}
今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!