一、文件IO
文件IO:系统调用
Linux内核专门为应用层提供的文件操作方法。
二、文件IO基本操作
打开文件和关闭文件
打开文件 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);
功能:打开文件并获得一个文件描述符
参数:
pathname:要打开的文件的文件名
flags:打开方式
O_RDONLY : 只读方式
O_WRONLY:只写方式
O_RDWR: 可读可写
O_CREAT: 创建文件
O_TRUNC: 清空文件
O_APPEND: 追加写
标准IO: 文件IO:
"r" O_RDONLY
"r+" O_RDWR
"w" O_WRONLY | O_CREAT | O_TRUNC, 0664
"w+" O_RDWR | O_CREAT | O_TRUNC, 0664
"a" O_WRONLY | O_APPEND | O_CREAT, 0664
"a+" O_RDWR | O_APPEND | O_CREAT,0664
mode:文件读写执行操作权限(当flag中有O_CREAT标志时,必须要增加mode操作限)
eg:
rwxrwxrwx
111 111 111 --->0777
rw-rw-r--
110 110 100 --->0664
(mode & ~umask)
111 111 111 110 110 100
& 111 111 101 & 111 111 101
111 111 101 ----》0775 110 110 100----》0664
返回值:
成功:文件描述符
失败:-1
文件描述符:
操作系统中已打开文件的标识符。
小的、非负的整形数据
范围:0-1023 (总共1024个)
分配原则:最小未被使用原则
文件描述符泄露:已打开的文件,使用完时,未及时关闭。
操作系统已经打开的三个文件占用了0、1、2这三个文件描述符:
标准IO: 文件IO
FILE * int
stdin ---->标准输入设备 -----》0
stdout ---->标准输出设备-----》1
stderr ---->标准出错设备-----》 2
关闭文件 close
包含的头文件:
#include <unistd.h>
函数用法:
int close(int fd);
功能:关闭文件
#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 = open("1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);
if(-1 == fd)
{
printf("open error\n");
}
printf("fd = %d\n", fd);
close(fd);
return 0;
}
读写文件
ssize_t write(int fd, const void *buf, size_t count);
功能:向文件中写入数据
参数:
fd:文件描述符
buf:要写入的数据的首地址
count:要写入的字节数
返回值:
成功:实际写入的字节数
失败:-1
ssize_t read(int fd, void *buf, size_t count);
功能:从文件中读取数据
参数:
fd:文件描述符
buf:存储数据的空间首地址
count:希望读取的字节数
返回值:
成功:实际读到的字节数
失败:-1
读到文件末尾:0
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
write(1, "hello world", 11);
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
int fd = open("1.txt", O_RDONLY);
if (fd < 0)
{
printf("open error\n");
return -1;
}
char buff[1024] = {0};
ssize_t cnt = read(fd, buff, sizeof(buff));
printf("cnt = %ld\n", cnt);
printf("buff = %s\n", buff);
close(fd);
return 0;
}
文件的拷贝
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
if (argc < 2)
{
printf("Usage : ./a.out <filename>\n");
return -1;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
printf("open error\n");
return -1;
}
char buff[1024] = {0};
while (1)
{
ssize_t cnt = read(fd, buff, sizeof(buff));
if (0 == cnt)
{
break;
}
else if (-1 == cnt)
{
printf("read error\n");
break;
}
write(1, buff, cnt);
}
close(fd);
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
int fd = open("/usr/include/stdio.h", O_RDONLY);
int fp = open("stdio.h", O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (-1 == fd || -1 == fp)
{
perror("open failed");
return -1;
}
char buff[1024] = {0};
ssize_t bytes_read = 0;
ssize_t bytes_written = 0;
while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
{
bytes_written = write(fp, buff, bytes_read);
if (bytes_written == -1 || bytes_written != bytes_read)
{
printf("write failed\n");
close(fd);
close(fp);
return -1;
}
}
if (bytes_read == -1)
{
printf("read failed\n");
close(fd);
close(fp);
return -1;
}
close(fd);
close(fp);
return 0;
}
文件定位
lseek:
off_t lseek(int fd, off_t offset, int whence);
功能:文件读写位置定位
参数:
fd:文件描述符
offset:偏移量(字节)
whence:要偏移的相对位置
SEEK_SET:文件开头位置
SEEK_CUR:文件当前读写位置
SEEK_END:文件末尾
返回值:
成功:返回当前读写位置到文件开头的偏移量
失败:-1
求文件大小:
off_t len = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET); //文件读写位置复位
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
int fd = open("./1.txt", O_WRONLY | O_TRUNC | O_CREAT, 0664);
if (fd < 0)
{
printf("open error\n");
return -1;
}
off_t offset = lseek(fd, 10, SEEK_SET);
printf("offset = %ld\n", offset);
write(fd, "A", 1);
offset = lseek(fd, 0, SEEK_CUR);
printf("offset = %ld\n", offset);
offset = lseek(fd, 0, SEEK_SET);
printf("offset = %ld\n", offset);
offset = lseek(fd, 0, SEEK_END);
printf("offset = %ld\n", offset);
lseek(fd, 0, SEEK_SET); //文件读写位置复位
close(fd);
return 0;
}
三、标准IO与文件IO的区别
标准IO:
1. 属于C库函数,移植性强
2. 标准IO是系统调用的一次封装,增加了缓冲区,目的是提高数据读写的效率
3. 标准IO主要用在对普通文件的操作
文件IO:
1. 属于系统调用,只能用于Linux操作系统,移植性弱
2. 文件IO无缓冲区
3. 文件IO主要应用在对硬件的操作的,也可以操作普通文件
底层原理
缓冲区:
1. 行缓冲 1k(1024字节) -----》人机交互界面、终端
缓冲区被刷新的方法:
1. 程序结束,自动刷新缓冲区
2. 遇到\n刷新
3. fflush()强制刷新
4. 缓冲区满刷新
2. 全缓冲 4k(4096字节) -----》文件缓冲区
缓冲区被刷新的方法:
1.程序结束,自动刷新缓冲区
2. fflush()强制刷新
3. 文件关闭刷新
4. 缓冲区满刷新
3. 无缓冲 0k --------》出错信息对应的设备
stderr---》无缓冲