ループ内で std::ifstream を 1 行ずつ使用してファイルを読み込もうとしています。同じループで、全体として読み取りたいブロックを囲む 2 つのタグを見つけようとしています。
私は、seekg を使用してブロックの開始位置と終了位置を追跡し、両方の位置を見つけた後、 read(*,end-start) を使用してブロックを読み取ることができると考えました。
ただし、tellg はストリーム位置を返しますが、ファイルがテキスト モードで開かれているため [getline を呼び出すことができるように]、行末として \r\n を使用しているため、ifstream のパラメータ「文字数」- read-method は、\r\n から \n への変換後の数値を参照するため、予想よりも正確に n 文字多く読み取っています。ここで、n は 2 つのタグ間の行数です。
明らかに、多くの回避策がありますが、私は素晴らしく直感的な解決策を探しています。助言がありますか?
EDIT1@130507: 私の目標は、std lib ストリームを維持し、速度よりもメモリを優先することです。タグ間の周囲の部分とブロックの両方の部分を解析して処理する必要があります。
すでに開いているテキストモードストリームでバイナリモードに切り替えるか、読み取りのような文字変換を行わない (ベースクラスの) raw-read-method や、それを可能にするいくつかのマッパーメソッドを使用するなど、何か利用可能なものがあることを願っていました。ストリーム間のマップは、文字変換の前後に表示されますが、これまでのところ何も見つかりませんでした。
ここにいくつかのコードがあります:
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