我想从一个文件向后读 - 从结尾到开头。 这有效,但不仅我想从文件中获取字符,我想在阅读时删除它们。
std::fstream fileA;
fileA.seekg(-1, fileA.end);
int size = fileA.tellg();
for (i = 1; i <= size; i++)
{
fileA.seekg(-i, fileA.end);
fileA.get(ch);
std::cout << ch;
}
无论如何要做到这一点,没有复制内容并创建一个没有我读过的新文件?
答案 0 :(得分:2)
如果不使用here或here概述的方法之一,这是不可能的。如果查看istream_iterator,您会看到它是一个输入迭代器(24.6.1)(1)
类模板istream_iterator是输入迭代器
然后从(24.2.1)(表105)
Random Access -> Bidirectional -> Forward -> Input
-> Output
正如您所看到的,输入迭代器是一个限制性更强的前向迭代器,而前向迭代器只能朝一个方向前进。由于这种行为,它不是在输入流结束时开始并向后走的标准方法
答案 1 :(得分:1)
如果您只想以相反的顺序呈现二进制数据,无论其含义如何,您的代码都可以。
一些建议:
然后,您应该在binary
中打开流以确保整个平台的一致性(即,避免在平台上将双行换行转换为换行符,例如将其编码为0x0d,0x0a
的窗口)。
您还可以考虑在循环中使用与当前位置相对的位置,向后导航,而不是总是走到最后并从末尾的绝对位置重新设置自己。
这里是经过微调的代码:
ifstream fileA("test.txt", ios::binary); // binary data because binary revert
fileA.seekg(-1, ios::end); // position on last char to be read
char ch;
for (; fileA.get(ch); fileA.seekg(-2, ios::cur)) // try to read and rewind.
std::cout << ch;
但是,您的代码无法读取正确的UTF8编码文件,因为多字节序列将受到机械上的尊重,并且其还原版本无效UTF8:
u
读取了一个字符(u & 0xC0) == 0x80
,则必须阅读所有内容前面的字符,直到此条件为假,并以正确的顺序输出字节组(在2和8之间)。 如何做到这一点:
... // If UTF-8 must be processed correctly
fileA.seekg(-1, ios::end);
char ch, buft[9]{},*p;
bool mb=false;
for (; fileA.get(ch); fileA.seekg(-2, ios::cur))
{
if (mb) { // if we are already processing a multibyte sequence
if ((ch & 0xC0) == 0x80 && p!=buft) // still another byte ?
*--p=ch;
else {
cout <<ch<<p; // if no other output the current leading char followed by the multibyte encoding that we've identified
mb=false; // and multibyte processing is then finished
}
}
else if ((ch & 0xC0) == 0x80) { // if a new multibyte sequence is identified
mb =true; // start its processing
buft[7]=ch;
p=buft+7;
}
else std::cout << ch; // normal chars ar procesed as before.
}
最后一点:从输入流中删除最后一个字节取决于操作系统。您应该查看this SO question以获得有关如何在linux / posix和windows上执行此操作的答案。