【c++】使用Handle实现大文件的读取,需要了解的细节

背景说明:想要读取二进制文件,该文件的字节数上亿。

string或者CString类型的文件路径要转化为LPCSTR型

LPCTSTR即const char
(1)当需要const char
而传入了CString时, C++编译器自动调用 CString重载的操作符 LPCTSTR()来进行隐式的类型转换。
(2)当需要CString , 而传入了 const char* 时(其实 char* 也可以),C++编译器则自动调用CString的构造函数来构造临时的 CString对象。
因此,CString 和 LPCTSTR 基本可以通用。

如何快速获取大文件的字节长度

HANDLE fileHandle = CreateFile(filePath, GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING, 0,0);
int size = GetFileSize(fileHandle , NULL);
//函数参数具体说明见他人博客,此处不过多介绍

如何求结构体类型或其他类型的字节长

int length = sizeof(Road);//我定义的Road结构体
int RoadCount = size / length; //文件写入时,我是以Road结构体为单位写入的,故可以用文件总字节长除以单个Road结构体字节长,求出Road数目。

注意:如果想求vector数组的长度,是不能用sizeof(vector)的,只能用vector.size()。这是由于vector是从堆上分配内存,sizeof(vector)的值取决于vector内部存放的元素的数据类型,与编译器相关,而与元素的数量无关。
因此,在写入二进制文件和读取二进制文件时以X为单位写入或读取,X的类型不能是vector或者不能包含vector。
只能将vector(RoadPoint) coordArr转化成 RoadPoint coordArr[MAXSIZE]。其中RoadPoint是我自己封装的一个结构体如下。

struct RoadPoint
{
	double x;
	double y;
};

代码中的其他结构体如下,只需了解Road和RoadPoint的关系即可看懂后续代码:

struct RoadPoint
{
	double x;
	double y;
};
struct RoadAttribute
{
	char ID[MAXSUBSTRSIZE];
	char Kind_num[5];//注意后续使用判断是位 kindum == '1'
	int Width;
	char PathName[MAXSUBSTRSIZE];
	char SnodeID[MAXSUBSTRSIZE];
	char EnodeID[MAXSUBSTRSIZE];
	char Length[10];
	int RPonitNum;

};

struct Road
{
	struct RoadAttribute RoadAttr;
	RoadPoint coordArr[MAXSIZE];

};

函数功能、返回值意义详细说明(见注释)

	//设置文件路径,CreateFile参数中文件路径的类型为LPCSTR
	//CString转到LPCSTR直接赋值即可
	CString fileroad= (CString)Path + "target.jpg";
	LPCSTR m_road =fileroad; 
	//定义文件映射句柄
	HANDLE fileHandle = CreateFile(m_road, GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING, 0,0);

	//获取文件大小
	int size = GetFileSize(fileHandle, NULL);
	//求出道路总数
	int RoadCount=size/sizeof(Road);

	//定义文件内存映射句柄
	HANDLE handle = CreateFileMapping(fileHandle, NULL, PAGE_READONLY, 0, 0,NULL);
	if(handle == 0)
	{
		printf("CreateFileMapping err\n");
		return ;
	}
	
	//可以把LPVOID理解成一个指针,lp文件的内容要超过50M,不然会程序崩溃
	LPVOID lp =  MapViewOfFile(handle, FILE_MAP_READ, 0, 0 ,0);
	if(lp == NULL)
	{
		DWORD err = GetLastError();
		printf("MapViewOfFile err=%d", err);
		return ;
	}

	//tarDataP是Road* 类型的,已经将其定义为类成员,故不在此处声明
	//分配内存
	tarDataP =(Road *) malloc(size);
	if(tarDataP == NULL)
	{
		printf("malloc err");
		return ;
	}
	//可以直接对LP操作,这里的拷贝只是为了增加时间,避免finish - start为0
	//将字节长度size的lp拷贝到tarDataP中,这里tarDataP和lp是指针
	memcpy_s(tarDataP,size,lp,size);
	//malloc的空间需要手动释放free(tarDataP);释放时间可以修改,可以在完成自己想要进行的功能后释放,也可以在析构函数中释放。
	//此处由于本程序的tarDataP要作为类内成员的值进行后续操作,不在此处释放。

	//释放lp,关闭文件映射句柄
	UnmapViewOfFile(lp);
	CloseHandle(hanle);
	CloseHandle(fileHandle);
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++本身不提供直接读取xlsx文件和创建MDB文件的功能,但可以使用第三方库来实现这个功能。下面是一种可能的实现方式: 1. 读取xlsx文件:可以使用开源的库,如libxlsxwriter或者SimpleXlsxWriter,这些库提供了读取和写入xlsx文件的功能。你可以选择其中一个库,根据其提供的API来读取xlsx文件中的数据。 2. 创建MDB文件:要创建MDB文件,你可以使用Microsoft Access或者ODBC(Open Database Connectivity)来操作数据库。首先,你需要安装Microsoft Access,并创建一个新的MDB文件。然后,你可以使用ODBC来连接到这个MDB文件,并执行SQL语句来创建表格和插入数据。 以下是一个简单的示例代码,使用libxlsxwriter库读取xlsx文件使用ODBC连接到MDB文件: ```cpp #include <iostream> #include <xlsxwriter.h> #include <windows.h> #include <sql.h> #include <sqlext.h> int main() { // 读取xlsx文件 lxw_workbook *workbook = workbook_new("input.xlsx"); lxw_worksheet *worksheet = workbook_get_worksheet(workbook, 0); // 连接到MDB文件 SQLHENV env; SQLHDBC dbc; SQLHSTMT stmt; SQLRETURN ret; SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); SQLDriverConnect(dbc, NULL, (SQLCHAR*)"DRIVER={Microsoft Access Driver (*.mdb)};DBQ=output.mdb", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); // 创建表格 SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); ret = SQLExecDirect(stmt, (SQLCHAR*)"CREATE TABLE MyTable (ID INT, Name VARCHAR(255))", SQL_NTS); // 插入数据 for (int row = 0; row < worksheet->num_rows; row++) { std::string id = lxw_rowcol_to_cell(row, 0); std::string name = lxw_rowcol_to_cell(row, 1); std::string query = "INSERT INTO MyTable (ID, Name) VALUES (" + id + ", '" + name + "')"; ret = SQLExecDirect(stmt, (SQLCHAR*)query.c_str(), SQL_NTS); } // 释放资源 SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLDisconnect(dbc); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); workbook_close(workbook); return 0; } ``` 请注意,这只是一个简单的示例代码,实际使用时可能需要根据具体情况进行修改和完善。另外,你需要根据你的系统环境和ODBC驱动程序的安装情况来配置ODBC连接字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值