c++文件读取流程如下:
ifstream ifs(srcFile, ifstream::binary);
if(ifs.is_open())
{
ifs.seekg(0, ifs.end);
long filesize = ifs.tellg();
ifs.seekg (0);
char* fileBuffer = new char[filesize]; //分配内存缓冲区
ifs.read(fileBuffer, filesize); //读取文件内容到缓冲区
ifs.close();
//do sth. with fileBuffer
delete []fileBuffer; //release memory
}
整个流程中内存的分配和读没什么问题。如果需要对fileBuffer的内容做些字符串处理相关的工作,因std::string操作比较方便,通常会先把fileBuffer转化为std::string,然后再删掉fileBuffer,如下
char* fileBuffer = new char[filesize]; //分配内存缓冲区
ifs.read(fileBuffer, filesize); //读取文件内容到缓冲区
ifs.close();
std::string strBuffer(fileBuffer);
delete []fileBuffer; //release memory
//do sth. with strBuffer...
这么做其实也没什么问题,风险无非有两个,一是忘了delete []fileBuffer,二是内存缓冲区可能在创建strBuffer时翻了一倍,虽然std::string在设计时考虑到了copy on write,但风险依然是存在的。
为了解决上面若有若无的风险,需要使用c++程序设计中常用的模式RAII即“资源获取就是初始化”,用对象来管理资源,如下:
std::string strBuffer(filesize, 0);//分配内存缓冲区
char* fileBuffer = &*strBuffer.begin(); //获取分配内存缓冲区的首地址
ifs.read(fileBuffer, filesize); //读取内容到缓冲区
ifs.close();
//do sth. with strBuffer or fileBuffer...
另外,C++11后调整了std::string,收紧了相关权限,比如:
常量字符串必须是const只读的
char* str = "this is test string"; //wrong
const char* str = "this is a test string"; //right
const char* 对象不能赋值给 char*
std::string str = "this is test string";
char* szStr = str.c_str(); //wrong
char* szStr = str.data(); //wrong
const char* szStr = str.c_str(); //right
const char* szStr = str.data(); //right
如果需要把std::string赋值给char*,即取得std::string对象的可读写首地址,需要转变思路
先获取首元素,然后对其取地址
std::string str = "this is a string";
char* szStr = &*str.begin();
char* szStr = &str[0];
这样对szStr的操作也对str生效了。