文件系统接口

打开文件

打开或创建一个文件可以调用下面的open 函数接口:

  1. int open(const char *pathname, int oflag, int mode);

参数:

  • pathname - 打开或创建的文件名;

  • oflag - 指定打开文件的方式,当前支持的打开方式有:

文件打开方式

  • mode - 与POSIX 标准接口像兼容的参数(目前没有意义,传入0即可)。

  • 返回值:

打开成功时返回打开文件的描述符序号,否则返回负数。可以参考 @@以下@@ 代码,看看如何去打开一个文件。

  1. #include <rtthread.h>
  2. #include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */
  3.  
  4. /* 假设文件操作是在一个线程中完成*/
  5. void file_thread()
  6. {
  7. int fd, size;
  8. char s[] = "RT-Thread Programmer!\n", buffer[80];
  9.  
  10. /* 打开/text.txt 作写入,如果该文件不存在则建立该文件*/
  11. fd = open("/text.txt", O_WRONLY | O_CREAT);
  12. if (fd >= 0)
  13. {
  14. write(fd, s, sizeof(s));
  15. close(fd);
  16. }
  17.  
  18. /* 打开/text.txt 准备作读取动作*/
  19. fd = open("/text.txt", O_RDONLY);
  20. if (fd >= 0)
  21. {
  22. size=read(fd, buffer, sizeof(buffer));
  23. close(fd);
  24. }
  25.  
  26. rt_kprintf("%s", buffer);
  27. }

关闭文件

当使用完文件后若不再需要使用则可使用close()函数接口关闭该文件,而close()会让数据写回磁盘,并释放该文件所占用的资源。关闭文件的函数接口如下:

  1. int close(int fd);
  • 参数:

fd - open()函数所返回的文件描述字。

  • 返回值:无

读取数据

读取数据可使用下面的函数接口:

  1. ssize_t read(int fd, void *buf, size_t count);
  • 参数:

fd - 文件描述词; buf - 内存指针; count - 预读取文件的字节数。

  • 返回值:

实际读取到的字节数。read()函数接口会把参数fd 所指的文件的count 个字节传送到buf 指针所指的内存中。返回值为实际读取到的字节数,有两种情况会返回0 值,一是读取数据已到达文件结尾,二是无可读取的数据(例如设定count为0),此外,文件的读写位置会随读取到的字节移动。

写入数据

写入数据可使用下面的函数接口:

  1. size_t write(int fd, const void *buf, size_t count);
  • 参数:

fd - 文件描述词; buf - 内存指针; count - 预写入文件的字节数。

  • 返回值: 实际写入的字节数。

write()函数接口会把buf 指针所指向的内存中count 个字节写入到参数fd 所指的文件内。返回值为实际写入文件的字节数,返回值为0 时表示写入出错,错误代码存入当前线程的errno中,此外,文件的读写位置会写入的字节移动。

可以参考 @@以下@@ 代码,看看一个完整的文件读写流程:

  1. /*
  2. * 代码清单:文件读写例子
  3. * 这个例子演示了如何读写一个文件,特别是写的时候应该如何操作。
  4. */
  5.  
  6. #include <rtthread.h>
  7. #include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */
  8.  
  9. #define TEST_FN "/test.dat"
  10.  
  11. /* 测试用的数据和缓冲 */
  12. static char test_data[120], buffer[120];
  13.  
  14. /* 文件读写测试 */
  15. void readwrite(const char* filename)
  16. {
  17. int fd;
  18. int index, length;
  19.  
  20. /* 只写 & 创建 打开 */
  21. fd = open(TEST_FN, O_WRONLY | O_CREAT | O_TRUNC, 0);
  22. if (fd < 0)
  23. {
  24. rt_kprintf("open file for write failed\n");
  25. return;
  26. }
  27.  
  28. /* 准备写入数据 */
  29. for (index = 0; index < sizeof(test_data); index ++)
  30. {
  31. test_data[index] = index + 27;
  32. }
  33.  
  34. /* 写入数据 */
  35. length = write(fd, test_data, sizeof(test_data));
  36. if (length != sizeof(test_data))
  37. {
  38. rt_kprintf("write data failed\n");
  39. close(fd);
  40. return;
  41. }
  42.  
  43. /* 关闭文件 */
  44. close(fd);
  45.  
  46. /* 只写并在末尾添加打开 */
  47. fd = open(TEST_FN, O_WRONLY | O_CREAT | O_APPEND, 0);
  48. if (fd < 0)
  49. {
  50. rt_kprintf("open file for append write failed\n");
  51. return;
  52. }
  53.  
  54. length = write(fd, test_data, sizeof(test_data));
  55. if (length != sizeof(test_data))
  56. {
  57. rt_kprintf("append write data failed\n");
  58. close(fd);
  59. return;
  60. }
  61. /* 关闭文件 */
  62. close(fd);
  63.  
  64. /* 只读打开进行数据校验 */
  65. fd = open(TEST_FN, O_RDONLY, 0);
  66. if (fd < 0)
  67. {
  68. rt_kprintf("check: open file for read failed\n");
  69. return;
  70. }
  71.  
  72. /* 读取数据(应该为第一次写入的数据) */
  73. length = read(fd, buffer, sizeof(buffer));
  74. if (length != sizeof(buffer))
  75. {
  76. rt_kprintf("check: read file failed\n");
  77. close(fd);
  78. return;
  79. }
  80.  
  81. /* 检查数据是否正确 */
  82. for (index = 0; index < sizeof(test_data); index ++)
  83. {
  84. if (test_data[index] != buffer[index])
  85. {
  86. rt_kprintf("check: check data failed at %d\n", index);
  87. close(fd);
  88. return;
  89. }
  90. }
  91.  
  92. /* 读取数据(应该为第二次写入的数据) */
  93. length = read(fd, buffer, sizeof(buffer));
  94. if (length != sizeof(buffer))
  95. {
  96. rt_kprintf("check: read file failed\n");
  97. close(fd);
  98. return;
  99. }
  100.  
  101. /* 检查数据是否正确 */
  102. for (index = 0; index < sizeof(test_data); index ++)
  103. {
  104. if (test_data[index] != buffer[index])
  105. {
  106. rt_kprintf("check: check data failed at %d\n", index);
  107. close(fd);
  108. return;
  109. }
  110. }
  111.  
  112. /* 检查数据完毕,关闭文件 */
  113. close(fd);
  114. /* 打印结果 */
  115. rt_kprintf("read/write done.\n");
  116. }
  117.  
  118. #ifdef RT_USING_FINSH
  119. #include <finsh.h>
  120. /* 输出函数到finsh shell 命令行中 */
  121. FINSH_FUNCTION_EXPORT(readwrite, perform file read and write test);
  122. #endif

更改名称

更改文件的名称可使用下面的函数接口:

  1. int rename(const char *oldpath, const char *newpath);
  • 参数: oldpath - 需更改的文件名; newpath - 更改成的文件名。

  • 返回值: 无

rename()会将参数oldpath 所指定的文件名称改为参数newpath 所指的文件名称。若newpath 所指定的文件已经存在,则该文件将会被覆盖。可以参考 @@以下@@ 代码,如何进行文件名改名。

  1. #include <dfs_posix.h>
  2.  
  3. void file_thread(void* parameter)
  4. {
  5. rt_kprintf("%s => %s ", "/text1.txt", "/text2.txt");
  6.  
  7. if(rename("/text1.txt", "/text2.txt") <0 )
  8. rt_kprintf("[error!]\n");
  9. else
  10. rt_kprintf("[ok!]\n");
  11. }

这个示例函数会把文件’/text1.txt’改名成’/text2.txt’。

取得状态

获取文件状态可使用下面的stat 函数接口:

  1. int stat(const char *file_name, struct stat *buf);

stat()函数用来将参数file_name 所指向的文件状态,复制到buf 指针所指的结构中(struct stat)。

  • 参数: file_name - 文件名; buf - 结构指针,指向获取文件状态的结构。
    返回值: 无 可以参考 @@以下@@ 代码了解如何使用stat 函数。
  1. void file_thread(void* parameter)
  2. {
  3. struct stat buf;
  4. stat("/text.txt", &buf);
  5. rt_kprintf("text.txt file size = %d\n", buf.st_size);
  6. }