O_DIRECT方式读取文件示例

简介: #include fcntl.h> #include stdio.h> #include stdlib.h> #include sys/stat.


  1. #include fcntl.h>
  2. #include stdio.h>
  3. #include stdlib.h>
  4. #include sys/stat.h>
  5. #include sys/types.h>
  6. #include sys/time.h>
  7. #include unistd.h>
  8. #include glog/logging.h>
  9. #include gflags/gflags.h>

  10. // 读文件类
  11. class CFileReader
  12. {
  13. public:
  14.     CFileReader()
  15.         : _buffer(NULL)
  16.     {
  17.     }

  18.     ~CFileReader()
  19.     {
  20.         free(_buffer);
  21.     }

  22.     bool open(const char* filepath)
  23.     {
  24.         // 以O_DIRECT方式打开文件
  25.         int fd = ::open(filepath, O_RDONLY | O_DIRECT);
  26.         if (-1 == fd)
  27.         {
  28.             LOG(ERROR) "open " filepath " error: " strerror(errno);
  29.             return false;
  30.         }

  31.         // 取得文件大小,以便一次性将文件读取出来
  32.         struct stat st;
  33.         if (-1 == fstat(fd, &st))
  34.         {
  35.             LOG(ERROR) "stat " filepath " error: " strerror(errno);
  36.             close(fd);
  37.             return false;
  38.         }

  39.         // 分配足以容纳整个文件的Buffer
  40.         // 由于以O_DIRECT方式读取,所以需要按页对齐
  41.         size_t size = st.st_size + (getpagesize() - st.st_size%getpagesize());
  42.         posix_memalign((void**)&_buffer, getpagesize(), size);
  43.         if (NULL == _buffer)
  44.         {
  45.             LOG(ERROR) "malloc failed";
  46.             close(fd);
  47.             return false;
  48.         }
  49.     
  50.         // 将整个文件读取_buffer中
  51.         int bytes_read = read(fd, _buffer, size);
  52.         if (-1 == bytes_read)
  53.         {
  54.             LOG(ERROR) "read " filepath " error: " strerror(errno);
  55.             close(fd);
  56.             free(_buffer);
  57.             _buffer = NULL;
  58.             return false;
  59.         }
  60.         else if (bytes_read != size)
  61.         {
  62.             // 两组测试输出数据:
  63.             // FileSize(212000000) => AlignSize(212000768) -> RealSize(212000000)
  64.             // FileSize(2120000000) => AlignSize(2120003584) -> RealSize(2120000000)
  65.             printf("FileSize(%d) => AlignSize(%d) -> RealSize(%d)\n", st.st_size, size, bytes_read);
  66.         }

  67.         return true;
  68.     }

  69.     // 从文件中读取一个节点数据
  70.     // offset:偏移量
  71.     // return:返回指向记录的指针
  72.     template class P>
  73.     const P* get_record(uint64_t offset) const
  74.     {
  75.         return reinterpret_castP*>(_buffer + offset);
  76.     }

  77.     // 取得文件所有的记录
  78.     template class P>
  79.     const P** get_all_record() const
  80.     {
  81.         return reinterpret_castP**>(_buffer);
  82.     }

  83. private:
  84.     char* _buffer;
  85. };

  86. // 用于计时
  87. class TimeWatcher
  88. {
  89. public:
  90.     TimeWatcher(const std::string& tip)
  91.         : _tip(tip)
  92.     {
  93.         struct timeval now;
  94.         gettimeofday(&now, NULL);

  95.         _now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
  96.     }

  97.     ~TimeWatcher()
  98.     {
  99.         struct timeval now;
  100.         gettimeofday(&now, NULL);

  101.         time_t cur_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
  102.         LOG(INFO) _tip " spend " cur_msec - _now_msec "ms";
  103.     }

  104. private:
  105.     std::string _tip;
  106.     time_t _now_msec;
  107. };

  108. struct User
  109. {
  110.     int32_t age;
  111.     int32_t hight;
  112.     int32_t weight;
  113.     char bitmap[50*4];
  114. };


  115. // 用于生成测试文件
  116. bool make_test_file(const char* filepath, int num_records)
  117. {
  118.     int fd = open(filepath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
  119.     if (-1 == fd)
  120.     {
  121.         LOG(ERROR) "open " filepath " error: " strerror(errno);
  122.         return false;
  123.     }

  124.     User user;
  125.     TimeWatcher time_watcher("write");

  126.     for (int i=0; inum_records; ++i)
  127.     {
  128.         user.age = i;
  129.         user.hight = i + i;
  130.         user.weight = i * i;

  131.         if (-1 == write(fd, &user, sizeof(user)))
  132.         {
  133.             LOG(ERROR) "write " filepath " error: " strerror(errno);
  134.             close(fd);
  135.             return false;
  136.         }
  137.     }

  138.     close(fd);
  139.     return true;
  140. }

  141. // 模拟随机读取
  142. void random_read(const CFileReader& file_reader, int num_random)
  143. {
  144.     int *index = new int[num_random];

  145.     for (int i=0; inum_random; ++i)
  146.     {
  147.         srandom(time(NULL));
  148.         index[i] = random() % num_random;
  149.     }


  150.     TimeWatcher time_watcher("randmon read");
  151.     for (int i=0; inum_random; ++i)
  152.     {
  153.         file_reader.get_recordstruct User>(index[i]);
  154.     }
  155. }

  156. // 执行测试
  157. void test()
  158. {
  159.     int num_records1 = 1000000;
  160.     int num_records2 = 10000000;
  161.     std::string file1 = "./file_1000000";
  162.     std::string file2 = "./file_10000000";

  163.     if (make_test_file(file1.c_str(), 1000000)
  164.          && make_test_file(file2.c_str(), 10000000))
  165.     {
  166.         printf("to read, press ENTER to continue ...\n");
  167.         getchar();

  168.         CFileReader file_reader1;

  169.         {
  170.             TimeWatcher time_watcher("open");
  171.             if (!file_reader1.open(file1.c_str()))
  172.             {
  173.                 return;
  174.             }
  175.         }

  176.         random_read(file_reader1, 1000000);
  177.         random_read(file_reader1, 3000000);

  178.         CFileReader file_reader2;

  179.         {
  180.             TimeWatcher time_watcher("open");
  181.             if (!file_reader2.open(file2.c_str()))
  182.             {
  183.                 return;
  184.             }
  185.         }

  186.         random_read(file_reader2, 1000000);
  187.         random_read(file_reader2, 3000000);
  188.     }
  189. }

  190. int main(int argc, char* argv[])
  191. {
  192.     test();
  193.     return 0;
  194. }


相关文章
|
7月前
|
C#
C# (File方法)对文件的操作,字节写入和读取
C# (File方法)对文件的操作,字节写入和读取
|
7月前
|
XML C# 数据格式
C#读取写入文件的三种方式
最近对文件的操作比较频繁。这里记录一下常用的几种文件读写的方式。 我这里使用窗体来做测试,例子在文末,可下载。
66 0
|
9月前
Gin 学习之接收参数和读取 reader
Gin 学习之接收参数和读取 reader
58 0
|
11月前
|
Python
Python 文件操作(创建、读取、追加、图片视频读取)
Python 文件操作(创建、读取、追加、图片视频读取)
98 0
|
12月前
|
JSON 数据格式 Python
Python中对open读取文件内容时的mode模式解析
Python中对open读取文件内容时的mode模式解析
108 0
|
移动开发 Go
GO 利用bufio包(流式操作) - 并发写文件/读文件示例
GO 利用bufio包(流式操作) - 并发写文件/读文件示例
539 0
GO 利用bufio包(流式操作) - 并发写文件/读文件示例
|
JSON JavaScript 数据格式
封装读取 data.json 文件的方法|学习笔记
快速学习封装读取 data.json 文件的方法
147 0
像素缓冲区对象(PBO)的异步Read-Back 源码解析
像素缓冲区对象(PBO)的异步Read-Back 源码解析
203 0
像素缓冲区对象(PBO)的异步Read-Back 源码解析
读取文件内容: 1.通过open函数获取文件对象 2.执行read函数 需要指定读取的字符
读取文件内容: 1.通过open函数获取文件对象 2.执行read函数 需要指定读取的字符
readline()函数:可以读取一行 分析: 1.创建一个file对象 2.使用循环读取每一行的内容 直到读取内容为空 3.将读取到的内容写
readline()函数:可以读取一行 分析: 1.创建一个file对象 2.使用循环读取每一行的内容 直到读取内容为空 3.将读取到的内容写