记录C++文件读取若干问题(1)

文章讲述了在C++中如何以不同模式打开文件,特别是处理二进制数据时需要注意的数据组织和存储方式。通过对比两种向vector中存储二进制数据的方法,强调了直接resize并使用.data()的效率。同时,讨论了tellg()和seekg()在文件指针管理和计算文件大小中的作用,以及在不同C++标准下seekg()的行为变化和使用注意事项。
摘要由CSDN通过智能技术生成

文件打开及数据存储方式

文件打开方式:

member constantstands foraccess
std::ios::ininput
std::ios::outoutput
std::ios::binarybinary指令以二进制方式执行,而非文本
std::ios::ateat end在文件尾打开
std::ios::appappend所有的输出操作在文件尾
std::ios::truncate丢弃打开前的内容

读取一个文件首先需要知道文件的组织方式,是文本还是二进制,否则后续读取会出问题。

以二进制方式读取时, 需要知道数据的组织方式,数据描述是什么。有多少数据、数据类型是什么、怎么排布的等,一般数据集都有附带的数据描述。

从二进制文件中读取数据存储到vector中,一开始的做法是先用malloc分配预定大小给指针,然后将数据构造进vector。

size_t dataSize = number*sizeof(float);
float* tmp = (float*)malloc(dataSize);
fin.seekg(offset, std::ios::beg).read((char*)tmp, dataSize);
pbsdf->M = vector<float>(tmp, tmp + number);

后来发现可以直接将数据写入vector,改成以下形式,免去了vector的复制操作:

struct pbsdf{
    std::vector<float> M;
}
pbsdf->M.resize(number);
fin.seekg(offset, std::ios::beg).read((char*)pbsdf->M.data(), number * sizeof(float));

对于string类型也可以如法炮制。

文件指针及tellg、seekg函数

文件操作中读取指针的位置十分重要,可以使用tellg()、seekg()函数来获取当前读取位置、偏移读取指针。

使用上述函数能够简单地计算文件的大小:

std::streampos curPos = fin.tellg();
fin.seekg(0, std::ios::end);
float filesize = fin.tellg() / (1024.0f*1024.0f); // 956623530 / (1024*1024)
printf("Loading tensor data from \"%s\" .. (%lf MB, %i field%s)\n",
	filePath.string().c_str(), filesize, n_fields, n_fields > 1 ? "s" : "");
fin.seekg(curPos, std::ios::beg);

seekg函数使用时有一个注意点,在C++98标准中,如果在调用seekg函数前ifstream的eofbit没有被清除,那么调用会失败。在C++11标准以后行为发生变化,如果在调用seekg前设置了eofbit,那么seekg会清除eofbit。

//C++98
//If the eofbit flag is set before the call, 
//the function fails (sets failbit and returns).
//如果文件已经结束,再次调用seekg前要先clear
fin.clear();
fin.seekg(0, std::ios::beg);

//C++11
//The function clears the eofbit flag, if set before the call.

实际写代码时是如下的连续调用:

fin.seekg(offset, std::ios::beg).read((char*)pbsdf->M.data(), number * sizeof(float));

此时在C++17标准下seekg好像并没有清除eofbit,读取依然失败,数据不对。可能不能连续调用,需要分离一步步调用才可以。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值