向后读取文件,c ++ ifstream

时间:2015-04-07 15:40:30

标签: c++ fstream

我想从一个文件向后读 - 从结尾到开头。 这有效,但不仅我想从文件中获取字符,我想在阅读时删除它们。

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

无论如何要做到这一点,没有复制内容并创建一个没有我读过的新文件?

2 个答案:

答案 0 :(得分:2)

如果不使用herehere概述的方法之一,这是不可能的。如果查看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:

  • 如果您的文件中只有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上执行此操作的答案。