文件系统接口
打开文件
打开或创建一个文件可以调用下面的open 函数接口:
- int open(const char *pathname, int oflag, int mode);
参数:
pathname - 打开或创建的文件名;
oflag - 指定打开文件的方式,当前支持的打开方式有:
mode - 与POSIX 标准接口像兼容的参数(目前没有意义,传入0即可)。
返回值:
打开成功时返回打开文件的描述符序号,否则返回负数。可以参考 @@以下@@ 代码,看看如何去打开一个文件。
- #include <rtthread.h>
- #include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */
- /* 假设文件操作是在一个线程中完成*/
- void file_thread()
- {
- int fd, size;
- char s[] = "RT-Thread Programmer!\n", buffer[80];
- /* 打开/text.txt 作写入,如果该文件不存在则建立该文件*/
- fd = open("/text.txt", O_WRONLY | O_CREAT);
- if (fd >= 0)
- {
- write(fd, s, sizeof(s));
- close(fd);
- }
- /* 打开/text.txt 准备作读取动作*/
- fd = open("/text.txt", O_RDONLY);
- if (fd >= 0)
- {
- size=read(fd, buffer, sizeof(buffer));
- close(fd);
- }
- rt_kprintf("%s", buffer);
- }
关闭文件
当使用完文件后若不再需要使用则可使用close()函数接口关闭该文件,而close()会让数据写回磁盘,并释放该文件所占用的资源。关闭文件的函数接口如下:
- int close(int fd);
- 参数:
fd - open()函数所返回的文件描述字。
- 返回值:无
读取数据
读取数据可使用下面的函数接口:
- ssize_t read(int fd, void *buf, size_t count);
- 参数:
fd - 文件描述词; buf - 内存指针; count - 预读取文件的字节数。
- 返回值:
实际读取到的字节数。read()函数接口会把参数fd 所指的文件的count 个字节传送到buf 指针所指的内存中。返回值为实际读取到的字节数,有两种情况会返回0 值,一是读取数据已到达文件结尾,二是无可读取的数据(例如设定count为0),此外,文件的读写位置会随读取到的字节移动。
写入数据
写入数据可使用下面的函数接口:
- size_t write(int fd, const void *buf, size_t count);
- 参数:
fd - 文件描述词; buf - 内存指针; count - 预写入文件的字节数。
- 返回值: 实际写入的字节数。
write()函数接口会把buf 指针所指向的内存中count 个字节写入到参数fd 所指的文件内。返回值为实际写入文件的字节数,返回值为0 时表示写入出错,错误代码存入当前线程的errno中,此外,文件的读写位置会写入的字节移动。
可以参考 @@以下@@ 代码,看看一个完整的文件读写流程:
- /*
- * 代码清单:文件读写例子
- * 这个例子演示了如何读写一个文件,特别是写的时候应该如何操作。
- */
- #include <rtthread.h>
- #include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */
- #define TEST_FN "/test.dat"
- /* 测试用的数据和缓冲 */
- static char test_data[120], buffer[120];
- /* 文件读写测试 */
- void readwrite(const char* filename)
- {
- int fd;
- int index, length;
- /* 只写 & 创建 打开 */
- fd = open(TEST_FN, O_WRONLY | O_CREAT | O_TRUNC, 0);
- if (fd < 0)
- {
- rt_kprintf("open file for write failed\n");
- return;
- }
- /* 准备写入数据 */
- for (index = 0; index < sizeof(test_data); index ++)
- {
- test_data[index] = index + 27;
- }
- /* 写入数据 */
- length = write(fd, test_data, sizeof(test_data));
- if (length != sizeof(test_data))
- {
- rt_kprintf("write data failed\n");
- close(fd);
- return;
- }
- /* 关闭文件 */
- close(fd);
- /* 只写并在末尾添加打开 */
- fd = open(TEST_FN, O_WRONLY | O_CREAT | O_APPEND, 0);
- if (fd < 0)
- {
- rt_kprintf("open file for append write failed\n");
- return;
- }
- length = write(fd, test_data, sizeof(test_data));
- if (length != sizeof(test_data))
- {
- rt_kprintf("append write data failed\n");
- close(fd);
- return;
- }
- /* 关闭文件 */
- close(fd);
- /* 只读打开进行数据校验 */
- fd = open(TEST_FN, O_RDONLY, 0);
- if (fd < 0)
- {
- rt_kprintf("check: open file for read failed\n");
- return;
- }
- /* 读取数据(应该为第一次写入的数据) */
- length = read(fd, buffer, sizeof(buffer));
- if (length != sizeof(buffer))
- {
- rt_kprintf("check: read file failed\n");
- close(fd);
- return;
- }
- /* 检查数据是否正确 */
- for (index = 0; index < sizeof(test_data); index ++)
- {
- if (test_data[index] != buffer[index])
- {
- rt_kprintf("check: check data failed at %d\n", index);
- close(fd);
- return;
- }
- }
- /* 读取数据(应该为第二次写入的数据) */
- length = read(fd, buffer, sizeof(buffer));
- if (length != sizeof(buffer))
- {
- rt_kprintf("check: read file failed\n");
- close(fd);
- return;
- }
- /* 检查数据是否正确 */
- for (index = 0; index < sizeof(test_data); index ++)
- {
- if (test_data[index] != buffer[index])
- {
- rt_kprintf("check: check data failed at %d\n", index);
- close(fd);
- return;
- }
- }
- /* 检查数据完毕,关闭文件 */
- close(fd);
- /* 打印结果 */
- rt_kprintf("read/write done.\n");
- }
- #ifdef RT_USING_FINSH
- #include <finsh.h>
- /* 输出函数到finsh shell 命令行中 */
- FINSH_FUNCTION_EXPORT(readwrite, perform file read and write test);
- #endif
更改名称
更改文件的名称可使用下面的函数接口:
- int rename(const char *oldpath, const char *newpath);
参数: oldpath - 需更改的文件名; newpath - 更改成的文件名。
返回值: 无
rename()会将参数oldpath 所指定的文件名称改为参数newpath 所指的文件名称。若newpath 所指定的文件已经存在,则该文件将会被覆盖。可以参考 @@以下@@ 代码,如何进行文件名改名。
- #include <dfs_posix.h>
- void file_thread(void* parameter)
- {
- rt_kprintf("%s => %s ", "/text1.txt", "/text2.txt");
- if(rename("/text1.txt", "/text2.txt") <0 )
- rt_kprintf("[error!]\n");
- else
- rt_kprintf("[ok!]\n");
- }
这个示例函数会把文件’/text1.txt’改名成’/text2.txt’。
取得状态
获取文件状态可使用下面的stat 函数接口:
- int stat(const char *file_name, struct stat *buf);
stat()函数用来将参数file_name 所指向的文件状态,复制到buf 指针所指的结构中(struct stat)。
- 参数: file_name - 文件名; buf - 结构指针,指向获取文件状态的结构。
返回值: 无 可以参考 @@以下@@ 代码了解如何使用stat 函数。
- void file_thread(void* parameter)
- {
- struct stat buf;
- stat("/text.txt", &buf);
- rt_kprintf("text.txt file size = %d\n", buf.st_size);
- }