如何合并2个文本文件

时间:2016-06-09 12:57:11

标签: c# algorithm

我正在寻找不同的解决方案,包括那些禁止使用.NET libraries的解决方案以及我可以利用它们的所有优点的解决方案。

问题是,我有两个文本文件textFile1textFile2。它们中的每一个都包含有序整数(这是最重要的条件),如下所示:

textFile1      textFile2
0              1
2              3
4              5

我需要通过合并这两个文件来创建第三个文本文件,例如textFile3,预期结果应为:

textFile3
0
1
2
3
4
5

我的第一个想法是将这两个文本文件逐行复制到两个单独的数组中,而不是使用解决方案将两个已排序的数组合并到新的数组中 in this question. 之后,我将逐行将这些新数组的成员复制到textFile3

你有什么建议吗?也许更好的方法?请在这里写下您的所有想法,每个想法对我都有帮助。

3 个答案:

答案 0 :(得分:2)

合并两个有序序列很容易推广并实现为扩展方法,如下所示:

public static class Algorithms
{
    public static IEnumerable<T> MergeOrdered<T>(this IEnumerable<T> seq1, IEnumerable<T> seq2, IComparer<T> comparer = null)       
    {
        if (comparer == null) comparer = Comparer<T>.Default;
        using (var e1 = seq1.GetEnumerator())
        using (var e2 = seq2.GetEnumerator())
        {
            bool more1 = e1.MoveNext(), more2 = e2.MoveNext();
            while (more1 && more2)
            {
                int compare = comparer.Compare(e1.Current, e2.Current);
                yield return compare < 0 ? e1.Current : e2.Current;
                if (compare <= 0) more1 = e1.MoveNext();
                if (compare >= 0) more2 = e2.MoveNext();
            }
            for (; more1; more1 = e1.MoveNext())
                yield return e1.Current;
            for (; more2; more2 = e2.MoveNext())
                yield return e2.Current;
        }
    }
}

然后可以通过以下方式完成具体任务:

static void Merge(string inputFile1, string inputFile2, string outputFile)
{
    Func<string, IEnumerable<KeyValuePair<int, string>>> readLines = file =>
        File.ReadLines(file).Select(line => 
            new KeyValuePair<int, string>(int.Parse(line), line));
    var inputLines1 = readLines(inputFile1);
    var inputLines2 = readLines(inputFile2);
    var comparer = Comparer<KeyValuePair<int, string>>.Create(
        (a, b) => a.Key.CompareTo(b.Key));
    var outputLines = inputLines1.MergeOrdered(inputLines2, comparer)
        .Select(item => item.Value);
    File.WriteAllLines(outputFile, outputLines);
}

答案 1 :(得分:1)

它们都是排序列表并且为了避免内存消耗,打开两个文件的阅读器。从两者中读取两行,进行比较,编写已排序的结果,并根据每个文件的当前行执行操作。例如:将每个文件中的排序值视为指针,并从较小的一侧继续比较和推进直至完成。这将确保较小的内存占用空间,对于较大的文件而言比较小的文件更好。

您可以通过网络捏合算法here is oneanother that even mentions 0(1)。忽略它谈论数组的事实,你的文件是有效排序的数组,所以你不需要在内存中复制它。

答案 2 :(得分:1)

合并两个文件是合并两个数组的一个相当简单的修改。我们的想法是用读取文件的下一行来替换数组索引增量。例如,我在博客(http://blog.mischel.com/2014/10/24/merging-sorted-sequences/)中显示的标准合并算法是:

while (not end of List A and not end of List B)
    if (List A current item <= List B current item)
        output List A current item
        advance List A index
    else
        output List B current item
        advance List B index

// At this point, one of the lists is empty.
// Output remaining items from the other
while (not end of List A)
    output List A current item
    advance List A index

while (not end of List B)
    output List B current item
    advance List B index

要制作合并文件,首先要打开并阅读每个文件的第一行。但是,它有点棘手,因为你必须检查文件的结尾。 “获取下一行”有点......奇怪。

int item1;
int item2;
bool eof1 = false;
bool eof2 = false;
string temp;
var file1 = File.OpenText(textFile1);
temp = file1.ReadLine();
if (temp == null)
    eof1 = true;
else
    item1 = int.Parse(temp);

// do the same thing for file2

然后我们可以进行标准合并:

while (!eof1 && !eof2)
{
    if (item1 <= item2)
    {
        outputFile.WriteLine(item1);
        // get next item from file1
        temp = file1.ReadLine();
        if (temp == null)
            eof1 = true;
        else
            item1 = int.Parse(temp);
    }
    else
    {
        // output item2 and get next line from file2
    }
}
// and the cleanup
while (!eof1)
{
    // output item1, and get next line from file1
}
while (!eof2)
{
    // output item2, and get next file from file2
}

唯一不同的是,获取下一个项目比仅增加数组索引更为复杂。