向后读取文件,c++ ifstream

Reading file backwards , c++ ifstream

我想从文件中逆向读取 - 从结尾到开头。 这行得通,但我不仅想从文件中获取字符,还想在阅读时删除它们。

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;
}

有没有办法做到这一点,而不是复制内容并创建一个没有我所读内容的新文件?

如果您只想获取二进制数据并以相反的顺序呈现它,不管它的含义如何,您的代码都可以。

一些建议:

  • 然后您应该在 binary 中打开流以实现跨平台的一致性(即避免在 windows 等平台上将换行符转换为双换行符,对其进行编码如 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:

  • 如果您的文件中只有 ASCII 字符,这不是问题。
  • 如果 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.
}

这里是runnable demo

最后一点:从输入流中删除最后一个字节取决于操作系统。您应该查看 this SO question 以获得有关如何在 linux/posix 和 windows 上执行此操作的答案。

如果不使用概述的其中一种方法,这确实是不可能的 here or here。如果查看 istream_iterator,您会发现它是一个输入迭代器 (24.6.1)(1)

The class template istream_iterator is an input iterator

然后从 (24.2.1)(table 105)

Random Access -> Bidirectional -> Forward -> Input
                                          -> Output

如您所见,输入迭代器是一种限制性更强的前向迭代器,前向迭代器只能朝一个方向前进。由于这种行为,它们不是从输入流末尾开始并向后走的标准方法