我们如何才能尊重文件中的行顺序而不是行本身。文件可能会变得很大。
不应假设线的长度。
输入:
this is line1
this is line2
this is line3
示例输出:
this is line3
this is line2
this is line1
我虽然使用另一个文件作为缓冲区,例如堆栈数据结构,但实际上无法使用它。
对此有什么想法吗?
从两端开始读入文件的大块。在这些块内,将第一行换成最后一行,然后移动两个指针以跟踪您所在的位置。填写时写下每个块。当两个指针在中间相遇时,你就完成了。
不要试图修改块,这会使事情变得更复杂。使用四个块,第一个读取块、第一个写入块、最后一个读取块和最后一个写入块。当每个写入块完成时,将其写出。当每个读取块用尽时,读取另一个块。请注意不要覆盖您尚未阅读的任何内容!
它应该相当简单,只是乏味。如果您不需要它是最佳的,您可以向后读取块并写出一个新文件,然后将其移动到现有文件的顶部。
如果文件不适合内存,那么这是一个两遍过程。第一遍,您读取文件的块(尽可能多的行将适合内存),然后将它们以相反的顺序写入临时文件。所以你有了:
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
其他平台上有类似的实用程序。
不过,您可能会遇到命令行长度限制。
它可以通过两个简单的步骤完成:
第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;
}