文件的写入
需要包含的头文件
#include <unistd.h>
相关的API函数
ssize_t write(int fd, const void *buf, size_t count);
参数说明
- int fd :文件描述符
- const void *buf :一个无类型的指针buf,是一个缓冲区
- size_t count:要写入文件的大小
可以理解为write函数就是将count大小的数据,从buf缓冲区写到fd对应的文件里去
- 返回值:成功则返回 写入的字节数,失败则返回 -1
实操演示
1. 将上节的demo1.c 复制一份并重命名为 demo2.c:
2. 同样使用man函数来查看write函数相关信息:(man 2 write)
3. 在demo2.c中修改代码并保存退出:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main()
{int fd; // file descriptionchar *buf = "mjmmjm";fd = open("./file1",O_RDWR|O_CREAT, 0600);printf("file description = %d, open successfully!\n",fd);write(fd, buf, strlen(buf)); //对于字符串常量来说,使用sizeof求出的是系统用多少字节表示一个字符型指针,必须使用strlen才可以表示字符串的有效长度close(fd); //close after writing return 0;
}
注释中提到过,这里再强调一下:
对于字符串常量来说,使用sizeof求出的是系统用多少字节表示一个字符型指针,必须使用strlen才可以表示字符串的有效长度
详见:C语言的字符串_mjmmm的博客-CSDN博客
4. 运行程序,并查看file1:
可见,成功写入!
文件的读取
需要包含的头文件
#include <unistd.h>
相关的API函数
ssize_t read(int fd, void *buf, size_t count);
参数说明
- int fd :文件描述符
- const void *buf :一个无类型的指针buf,是一个缓冲区
- size_t count:要读取文件的大小
可以理解为read函数就是从fd对应的文件中,读取count大小的数据放到buf缓冲区
- 返回值:成功则返回 读取到的字节数,失败则返回 -1
这里涉及到一个从哪里开始读的问题,答案是从光标处开始读
实操演示
1. 将demo2.c 复制一份并重命名为 demo3.c:
2. 同样可以使用 man 2 read:
3. 在demo3.c中修改代码并保存退出:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main()
{int fd; // file descriptionchar *buf = "mjmmjm";char *buf_read;fd = open("./file1",O_RDWR|O_CREAT, 0600);printf("file description = %d, open successfully!\n",fd);int count_write = write(fd, buf, strlen(buf));if(count_write != -1){printf("%d bytes data has been written",count_write);buf_read = (char *)malloc(sizeof(char)*count_write + 1); //为野指针开辟空间防止段错误,且由于malloc返回值是void类型的指针,所以需要强制类型转换成char类型的指针}else{printf("fail to write");exit(-1);}int count_read = read(fd, buf_read, count);if(count_read != -1){printf("%d bytes data has been read, context:%s\n",count_read, buf_read);}else{printf("fail to read");}close(fd); //close after reading return 0;
}
4. 删除file1(避免之前写入过,导致结果不准确),并运行代码:
可见,虽然代码的逻辑似乎没有问题,但是却一个字节都没有读到,原因就是刚刚提到的,读取文件存在一个“从哪里开始读”的问题,而由于刚刚对文件进行write操作之后,光标处于文件的末尾,所以从此时如果从光标处read,注定是无法读到任何信息的。
解决这个问题的方法有两种:
- 将光标移到头再读
- 将文件重新打开
5. 完善代码:
使用“重新打开文件”的方法解决问题:
这种方式比较好实现,但是效率不高而且思路有些反人类
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main()
{int fd; // file descriptionchar *buf = "mjmmjm";char *buf_read;fd = open("./file1",O_RDWR|O_CREAT, 0600);printf("file description = %d, open successfully!\n",fd);int count_write = write(fd, buf, strlen(buf));if(count_write != -1){printf("%d bytes data has been written\n",count_write);buf_read = (char *)malloc(sizeof(char)*count_write + 1);}else{printf("fail to write\n");exit(-1);}close(fd); //关闭文件fd = open("./file1",O_RDWR, 0600); //重新打开文件int count_read = read(fd, buf_read, count_write);if(count_read != -1){printf("%d bytes data has been read, context:%s\n",count_read, buf_read);}else{printf("fail to read\n");}close(fd); //close after reading return 0;
}
实现效果:
使用“移动光标”的方法解决问题:
关于光标的控制:
需要包含的头文件
#include <sys/types.h> #include <unistd.h>
相关的API函数
off_t lseek(int fd, off_t offset, int whence);
参数说明
- int fd :文件描述符
- off_t offset:偏移多少个字节
- int whence:光标偏移位置
其中whence可以设置为 以下3个值中的一个:
- SEEK_SET:文件开头
- SEEK_CUR:光标当前位置
- SEEK_END:文件尾
可以理解为lseek函数就是将光标移到whence+offset的位置
- 返回值:成功则 返回从文件开始的偏移了多少字节;发生错误时,返回 -1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main()
{int fd; // file descriptionchar *buf = "mjmmjm";char *buf_read;fd = open("./file1",O_RDWR|O_CREAT, 0600);printf("file description = %d, open successfully!\n",fd);int count_write = write(fd, buf, strlen(buf));if(count_write != -1){printf("%d bytes data has been written\n",count_write);buf_read = (char *)malloc(sizeof(char)*count_write + 1);}else{printf("fail to write\n");exit(-1);}lseek(fd, 0, SEEK_SET); //将光标移到最开头int count_read = read(fd, buf_read, count_write);if(count_read != -1){printf("%d bytes data has been read, context:%s\n",count_read, buf_read);}else{printf("fail to read\n");}close(fd); //close after reading return 0;
}