文件IO
- 系统调用(不带缓冲的IO操作)
- 库函数(默认带用户缓冲的IO操作)
一、非缓冲IO
- 系统调用:即为不带缓冲的IO
1.打开文件open
2.读取文件read
NAME
read - read from a file descriptor
SYNOPSIS
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
DESCRIPTION
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
On files that support seeking, the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. If the file offset is at or past the end of file, no bytes are read, and read() returns zero.
If count is zero, read() may detect the errors described below. In the absence of any errors, or if read() does not check for errors, a read() with a count of 0 returns zero and has no other effects.
According to POSIX.1, if count is greater than SSIZE_MAX, the result is implementation-defined; see NOTES for the upper limit on Linux.
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. See also NOTES.
On error, -1 is returned, and errno is set appropriately. In this case, it is left unspecified whether the file position (if any) changes.
- fd:文件描述符
- buf:一块内存的首地址,用于存放读取的数据
- count:读取的字节数
- 返回值:读取到的字节数,0表示文件读取结束
3.写入文件write
4.关闭文件close
5.创建文件create
二、案例使用
1.文件读操作
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
int fd;
if (argc < 2) {
fprintf(stderr, "Usage : %s file\n", argv[0]);
exit(1);
}
if ((fd = open(argv[1], O_RDONLY)) == -1) {
perror("open");
fprintf(stderr, "%d\n", errno);
exit(1);
}
while (1) {
char buff[512] = {0};//buff用于存放读出内容
ssize_t num;
if ((num = read(fd, buff, sizeof(buff))) > 0) {//0表示读到文件末尾 -1表示出错
printf("%s", buff);
} else {
break;
}
}
close(fd);
return 0;
}
由于文件较大char buff[512]
字节无法一次性读完,两次buff读的中间出现会一些特殊的符号(数组的结束位置\0
被覆盖)。
为了解决上述问题,可以通过临时将buff[]
数组的最后一个元素赋值为\0
将其结束,从而解决buff[]
数组后一个位置被覆盖的问题(有可能越界赋值)。
2.文件拷贝操作
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
int fd1, fd2;
if (argc < 3) {
fprintf(stderr, "Usage : %s file1 file2\n", argv[0]);
exit(1);
}
if ((fd1 = open(argv[1], O_RDONLY)) == -1) {
perror("open1");
fprintf(stderr, "%d\n", errno);
exit(1);
}
if ((fd2 = open(argv[2], O_RDWR | O_CREAT, 0660)) == -1) {
perror("open2");
fprintf(stderr, "%d\n", errno);
exit(1);
}
//文件拷贝操作
while (1) {
char buff[512] = {0};//buff用于存放读出内容
buff[512] = '\0';
ssize_t num1;
ssize_t num2;
if ((num1 = read(fd1, buff, sizeof(buff))) > 0) {//0表示读到文件末尾 -1表示出错
//将读出的文件buff写入目标文件, 如果写入失败则直接退出循环
if ((num2 = write(fd2, buff, num1)) < 0) break;
} else {
break;
}
}
close(fd1);
close(fd2);
return 0;
}
文件拷贝成功。
三、缓冲IO
- 库函数:即为默认带用户缓冲的IO操作(标准IO/用户缓冲IO)
1.打开文件fopen
2.读取文件fread
3.写入文件fwrite
4.关闭文件fclose
四、案例使用
1.文件拷贝
#include "head.h"
int main(int argc, char *argv[]) {
int opt;
char rname[50] = {50}, wname[50] = {0};
FILE *r, *w;
//文件打开
while ((opt = getopt(argc, argv, "r:w:")) != -1) {
switch (opt) {
case 'r' :
strcpy(rname, optarg);
break;
case 'w' :
strcpy(wname, optarg);
break;
default:
fprintf(stderr, "Usage : %s -r file1 -w file2\n", argv[0]);
break;
}
}
if (!strlen(rname) || !strlen(wname)) {//判定 -r -w的参数是否为空
fprintf(stderr, "Usage : %s -r file1 -w file2\n", argv[0]);
exit(1);
}
if ((r = fopen(rname, "r")) == NULL) {//判定以r形式的文件是否打开成功
perror("fopen1");
exit(1);
}
if ((w = fopen(wname, "w")) == NULL) {//判定以w形式的文件是否打开成功
perror("fopen2");
exit(1);
}
//文件读取 写入
ssize_t num;
while (1) {
char buff[1024] = {0};
if ((num = fread(buff, 1, sizeof(buff), r)) > 0) {
fwrite(buff, 1, num, w);
} else {
break;
}
}
fclose(r);
fclose(w);
return 0;
}