如何逆转文件中的行顺序

时间:2013-10-21 21:18:35

标签: c++ c algorithm

我们如何尊重文件中的行顺序而不是行本身。 文件可以变得很大。

不应该假设线的长度。

输入:

this is line1
this is line2
this is line3

示例输出:

this is line3
this is line2
this is line1

我虽然使用另一个文件作为缓冲区,就像堆栈数据结构一样,但却无法真正随意使用它。

对此有何想法?

3 个答案:

答案 0 :(得分:3)

从两端开始读入文件的大块。在这些块中,交换最后一行的第一行,然后移动两个指针以跟踪您的位置。填写时写出每个块。当两个指针在中间相遇时,你就完成了。

不要尝试修改块,这会使事情变得更复杂。使用四个块,第一个读取块,第一个写入块,最后一个读取块和最后一个写入块。每个写块都完成后,写出来。当每个读取块耗尽时,请读取另一个读取块。小心不要覆盖你还没读过的东西!

它应该相当简单,只是单调乏味。如果您不需要它是最佳的,您可以向后读取块并写出一个新文件,然后将其移到现有文件的顶部。

答案 1 :(得分:1)

如果文件不适合内存,那么这是一个两遍过程。第一遍,你读取文件的块(尽可能多的行适合内存),然后以相反的顺序将它们写入临时文件。所以你有:

while not end of input
    read chunk of file into array of lines
    write lines from array to temporary file, in reverse order
end while

当你完成第一遍时,你将拥有一堆临时文件:temp1.txt,temp2.​​txt,temp3.txt ... tempN.txt。

现在打开追加的最后一个文件(tempN.txt),然后开始以相反的顺序附加文件。所以你有:

open fileN for append
fileno = N-1
while fileno > 0
    append file_fileno to fileN
    fileno--
end while

然后重命名tempN.txt并删除其他临时文件。

顺便说一句,您可以使用操作系统提供的串联实用程序执行第2步。例如,在Windows上,您可以将步骤2替换为:

copy /A file4.txt+file3.txt+file2.txt+file1.txt mynewfile.txt

其他平台上也有类似的实用程序。

但是,您可能会遇到命令行长度限制。

答案 2 :(得分:0)

可以通过两个简单的步骤完成:

第1步:撤消所有文件

第2步:反转每一行

step:0   1       2
---------------------
abc      zyx     xyz
1234 =>  4321 => 1234 
xyz      cba     abc

编辑:这是一个完整的解决方案:

#include <iostream>
#include <fstream>
#include <algorithm>
#define BUFFSIZE 4098 /*make sure this is larger then the longest line...*/
using namespace std;

bool reverse_file(const char* input, const char* output)
{
    streamsize count=0;
    streamoff size=0,pos;
    char buff[BUFFSIZE];

    ifstream fin(input);
    ofstream fout(output);

    if(fin.fail() || fout.fail()){
        return false;
    }

    fin.seekg(0, ios::end);
    size = fin.tellg();
    fin.seekg(0);
    while(!fin.eof()){  
        fin.read(buff, BUFFSIZE);
        count = fin.gcount();
        reverse(buff,buff+count);
        pos = fin.tellg();
        if(pos<0) {
            pos = size;
        }
        fout.seekp(size - pos);
        fout.write(buff,count);
    }
    return true;
}

bool reverse_file_lines(const char* input, const char* output)
{
    streamsize count=0;

    char buff[BUFFSIZE];

    ifstream fin(input);
    ofstream fout(output);

    if(fin.fail() || fout.fail()){
        return false;
    }

    while(!fin.eof()){  
        fin.getline(buff, BUFFSIZE);
    /*if BUFFSIZE is smallest then line size gcount will return 0, 
        but I didn't handle it...*/
        count = fin.gcount();
        if(buff[count-1]==0)count--;
        reverse(buff,buff+count);
        fout.write(buff,count);
        if(!fin.eof()){
            fout<<endl;
        }
    }
    return true;
}


int main()
{
    reverse_file("test.in", "test.tmp");
    reverse_file_lines("test.tmp","test.out");
    return 0;
}