我正在尝试在循环中逐行读取带有 std::ifstream 的文件。在同一个循环中,我试图找到两个标签,它们包含一个我想作为一个整体阅读的块。
我想,我可以用 seekg 跟踪块的开始和结束位置,并在找到两个位置后使用 read(*,end-start) 读取块。
但是,tellg 返回流位置,但由于文件已在文本模式下打开 [以便我能够调用 getline] 并使用 \r\n 作为行尾,ifstream 的参数“字符数”- read-method 是指从 \r\n 转换为 \n 后的数字,因此我读取的字符比我预期的要多 n 个字符,其中 n 是两个标签之间的行数。
显然,有很多解决方法,但我正在寻找一个很好且直观的解决方案。有什么建议么?
EDIT1@130507:我的目标是继续使用 std lib 流,优先考虑内存而不是速度,我需要解析和处理这两个部分,即周围部分和标签之间的块。
我希望有一些可用的东西,比如在已经打开的文本模式流中切换到二进制模式,或者有一些(基类)raw-read-method 不能像 read 那样进行字符转换,或者一些映射器方法允许在字符翻译之前和之后流 indizes 之间的映射,但到目前为止找不到任何东西。
这是一些代码:
std::ifstream testDataFileStream;
testDataFileStream.open(testDataFileName, std::ios_base::in);
testDataFileStream.unsetf(std::ios::skipws); // No white space skipping
if (testDataFileStream) {
std::string line;
while (getline(testDataFileStream, line))
if (line == "starttag")
break;
if (line == "starttag")
{
std::ifstream::pos_type cmdStartPos = testDataFileStream.tellg();
std::ifstream::pos_type cmdEndPos;
while (getline(testDataFileStream, line))
if (line == "endtag")
break;
else
cmdEndPos = testDataFileStream.tellg();
if (line == "endtag")
{
std::streamsize nofBytesToRead = cmdEndPos - cmdStartPos;
// now, one possible workaround follows, however, it's obviously quite lame
testDataFileStream.close();
testDataFileStream.open(testDataFileName, std::ios_base::in | std::ios::binary);
testDataFileStream.seekg(cmdStartPos);
std::string cmdsString;
cmdsString.resize(nofBytesToRead+1);
testDataFileStream.read(&cmdsString[0], nofBytesToRead);
} else {}
} else {}
testDataFileStream.close();
} else {}
测试文件可能如下所示:
some text
more text
starttag
much stuff on many lines
endtag
even more text