#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <glog/logging.h>
#include <gflags/gflags.h> // 读文件类
class CFileReader
{
public:
CFileReader()
: _buffer(NULL)
{
} ~CFileReader()
{
free(_buffer);
} bool open(const char* filepath)
{
// 以O_DIRECT方式打开文件
int fd = ::open(filepath, O_RDONLY | O_DIRECT);
if (-1 == fd)
{
LOG(ERROR) << "open " << filepath << " error: " << strerror(errno);
return false;
} // 取得文件大小,以便一次性将文件读取出来
struct stat st;
if (-1 == fstat(fd, &st))
{
LOG(ERROR) << "stat " << filepath << " error: " << strerror(errno);
close(fd);
return false;
} // 分配足以容纳整个文件的Buffer
// 由于以O_DIRECT方式读取,所以需要按页对齐
size_t size = st.st_size + (getpagesize() - st.st_size%getpagesize());
posix_memalign((void**)&_buffer, getpagesize(), size);
if (NULL == _buffer)
{
LOG(ERROR) << "malloc failed";
close(fd);
return false;
} // 将整个文件读取_buffer中
int bytes_read = read(fd, _buffer, size);
if (-1 == bytes_read)
{
LOG(ERROR) << "read " << filepath << " error: " << strerror(errno);
close(fd);
free(_buffer);
_buffer = NULL;
return false;
}
else if (bytes_read != size)
{
// 两组测试输出数据:
// FileSize(212000000) => AlignSize(212000768) -> RealSize(212000000)
// FileSize(2120000000) => AlignSize(2120003584) -> RealSize(2120000000)
printf("FileSize(%d) => AlignSize(%d) -> RealSize(%d)\n", st.st_size, size, bytes_read);
} return true;
} // 从文件中读取一个节点数据
// offset:偏移量
// return:返回指向记录的指针
template <class P>
const P* get_record(uint64_t offset) const
{
return reinterpret_cast<P*>(_buffer + offset);
} // 取得文件所有的记录
template <class P>
const P** get_all_record() const
{
return reinterpret_cast<P**>(_buffer);
} private:
char* _buffer;
}; // 用于计时
class TimeWatcher
{
public:
TimeWatcher(const std::string& tip)
: _tip(tip)
{
struct timeval now;
gettimeofday(&now, NULL); _now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
} ~TimeWatcher()
{
struct timeval now;
gettimeofday(&now, NULL); time_t cur_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
LOG(INFO) << _tip << " spend " << cur_msec - _now_msec << "ms";
} private:
std::string _tip;
time_t _now_msec;
}; struct User
{
int32_t age;
int32_t hight;
int32_t weight;
char bitmap[50*4];
}; // 用于生成测试文件
bool make_test_file(const char* filepath, int num_records)
{
int fd = open(filepath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (-1 == fd)
{
LOG(ERROR) << "open " << filepath << " error: " << strerror(errno);
return false;
} User user;
TimeWatcher time_watcher("write"); for (int i=0; i<num_records; ++i)
{
user.age = i;
user.hight = i + i;
user.weight = i * i; if (-1 == write(fd, &user, sizeof(user)))
{
LOG(ERROR) << "write " << filepath << " error: " << strerror(errno);
close(fd);
return false;
}
} close(fd);
return true;
} // 模拟随机读取
void random_read(const CFileReader& file_reader, int num_random)
{
int *index = new int[num_random]; for (int i=0; i<num_random; ++i)
{
srandom(time(NULL));
index[i] = random() % num_random;
} TimeWatcher time_watcher("randmon read");
for (int i=0; i<num_random; ++i)
{
file_reader.get_record<struct User>(index[i]);
}
} // 执行测试
void test()
{
int num_records1 = 1000000;
int num_records2 = 10000000;
std::string file1 = "./file_1000000";
std::string file2 = "./file_10000000"; if (make_test_file(file1.c_str(), 1000000)
&& make_test_file(file2.c_str(), 10000000))
{
printf("to read, press ENTER to continue ...\n");
getchar(); CFileReader file_reader1; {
TimeWatcher time_watcher("open");
if (!file_reader1.open(file1.c_str()))
{
return;
}
} random_read(file_reader1, 1000000);
random_read(file_reader1, 3000000); CFileReader file_reader2; {
TimeWatcher time_watcher("open");
if (!file_reader2.open(file2.c_str()))
{
return;
}
} random_read(file_reader2, 1000000);
random_read(file_reader2, 3000000);
}
} int main(int argc, char* argv[])
{
test();
return 0;
}

O_DIRECT方式读取文件示例的更多相关文章

  1. c++ 二进制方式读取文件 读取特殊类型数据

    #include <iostream> #include <fstream> using namespace std; /* 二进制方式进行读写文件,可以读写 各种各样数据类型 ...

  2. [JAVA 多种方式读取文件]

    package com.file; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream ...

  3. 文件结束符和C\C++读取文件方式

    http://www.cnblogs.com/cvbnm/articles/2003056.html 约定编译器为 gcc2/x86: 所以 char, unsigned char 为 8 位, in ...

  4. 精通awk系列(3):铺垫知识:读取文件的几种方式

    回到: Linux系列文章 Shell系列文章 Awk系列文章 读取文件的几种方式 读取文件有如下几种常见的方式: 下面使用Shell的read命令来演示前4种读取文件的方式(第五种按字节数读取的方式 ...

  5. 在Spring Boot快捷地读取文件内容的若干种方式

    引言: 在Spring Boot构建的项目中,在某些情况下,需要自行去读取项目中的某些文件内容,那该如何以一种轻快简单的方式读取文件内容呢?  基于ApplicationContext读取 在Spri ...

  6. C#中StreamReader类读取文件使用示例

    C#中StreamReader类读取文件使用示例 1.需要导入的命名空间是:System.IO; 2.操作的是字符,所以打开的是文本文件. 常用属性:   CurrentEncoding:对象正在使用 ...

  7. python中读取文件的read、readline、readlines方法区别

    #读取文件所有内容,返回字符串对象,python默认以文本方式读取文件,遇到结束符读取结束. fr = open('lenses.txt')read = fr.read()print(type(rea ...

  8. Win10系列:JavaScript写入和读取文件

    正如上面的内容中所提到的,文件保存选取器用于保存文件,通过Windows.Storage.Pickers命名空间中的FileSavePicker类的pickSaveFileAsync函数可以向指定的文 ...

  9. FileReader读取文件详解

    FileReader是一种异步文件读取机制,结合input:file可以很方便的读取本地文件. input:file 在介绍FileReader之前,先简单介绍input的file类型. <in ...

随机推荐

  1. WebApi 返值的实体值前缀加了个下划线

    发现MODEL类中加了个可以被序列化的标记,把它去除即可. [Serializable]

  2. HDU5336题解

    解题思路 这题思路并不难,主要问题是,不太好编码实现(可能是本人练习不够吧),因为有个时间在里面,而且每个小水滴都同时流动,感觉好复杂的样子.比赛时,我首先想到的是DFS+时间流做参数,由于比赛时神经 ...

  3. 【BZOJ】1913: [Apio2010]signaling 信号覆盖(计算几何+计数)

    题目 传送门:QWQ 分析 人类智慧题,不会做...... 详细题解1      详细题解2 总体思路是考虑四边形 讨论凹四边形凸四边形,最后加一个单调性优化省掉个$ O(n) $ 代码 代码感觉好短 ...

  4. cocos2dx中快速完成一段可播放动画

    版本:cocos2dx 2.2.6 IDE: VS2012 语言:C++98 CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteF ...

  5. select to object 查询方法

    (1)Select() (2)Where() (3)OrderBy()

  6. C# 提取方法重构

    引用:https://msdn.microsoft.com/zh-CN/library/0s21cwxk.aspx “提取方法”是一项重构操作,提供了一种从现有成员中的代码段创建新方法的便捷方式. 使 ...

  7. 呕心沥血Android studio使用JNI实例

    发现网上很多JNI的使用教程,也很详细,不过有的地方有些缺漏,导致很多小问题难以解决的,今天就来总结一下. 准备工作:下载NDK. 简单的说,要用到C/C++,就要用NDK.直接百度搜索然后去官网下载 ...

  8. BDE View not exists

     Table does not exist. [Microsoft][ODBC SQL Server Driver][SQL Server]对象名 'vw1' 无效. 

  9. UNITY所谓的异步加载几乎全部是协程,不是线程;MAP3加载时解压非常慢

    实践证明,以下东西都是协程,并非线程(thread): 1,WWW 2,AssetBundle.LoadFromFileAsync 3,LoadSceneAsync 其它未经测试 此问题的提出是由于一 ...

  10. 前端开发之JavaScript基础篇四

    主要内容: 1.定时器 2.正则表达式入门 3.元字符 4.正则表达式实战运用 一.定时器 javaScript里主要使用两种定时器,分别是:setInterval()和setTimeout(). 1 ...