我需要合并两个文件,同时还应用排序。重要的是我将任务点亮在内存使用上。我需要在c#中创建一个控制台应用程序。
输入文件1:
某些标题
A12345334
A00123445
A44566555
B55677
B55683
B66489
记录数:6
输入文件2:
某些标题
A00123465
B99423445
记录数:2
所以,我需要确保第三个文件首先包含所有“A”记录,然后是“B”记录,然后是总记录数。
输出文件:
一些标题
A12345334
A00123445
A44566555
A00123465
B99423445
B55677
B55683
B66489
记录数:8
“A”和“B”中的记录排序无关。
答案 0 :(得分:3)
由于您的源文件显示为已排序,因此您可以使用非常低的内存使用量。
只需打开两个输入文件以及一个用于写入的新文件。然后比较每个输入文件中的下一个可用行,并将首先出现的行写入输出文件。每次在输出文件中写入一行时,从它来自的输入文件中获取下一行。
继续,直到两个输入文件都完成。
答案 1 :(得分:0)
如果内存是个问题,最简单的方法可能是从两个文件中读取记录,将它们存储在SQLite或SQL Server Compact数据库中,然后执行返回已排序记录集的SELECT查询。确保在要排序的字段上有索引。
这样,您不必将记录存储在内存中,也不需要任何排序算法;数据库会将记录存储在磁盘上并为您排序。
答案 2 :(得分:0)
我建议您为此应用程序使用StreamReader
和StreamWriter
。因此,您可以使用StreamWriter
打开文件,使用StreamReader
复制文件#1的所有行,然后复制文件#2。此操作非常快,具有集成缓冲区并且非常轻量级。
如果输入文件已经按A和B排序,则可以在源阅读器之间切换以对输出进行排序。
答案 3 :(得分:0)
快速想法,假设记录已经在原始文件中排序:
可视化:
<A-data from file 2>
<A-data, followed by B-data from file 1>
<B-data from file 2>
答案 4 :(得分:0)
如果您担心内存,这是insertion sort的完美案例,并且每个文件一次读取一行。如果这不是一个问题,请将整个内容读入列表,然后调用sort将其写出来。
如果你甚至无法将整个排序列表保存在内存中,那么最好选择数据库或内存映射文件。
答案 5 :(得分:0)
假设您的输入文件已经订购:
此方法可以防止您一次只能在内存中保存2行以上的数据。
答案 6 :(得分:0)
由于你有两个排序的序列,你只需要将两个序列合并为一个序列,就像MergeSort算法的后半部分工作方式一样。
不幸的是,考虑到IEnumerable
提供的接口,它最终会有点混乱和复制糊涂,但它应该表现得相当好并且占用的内存非常小:
public class Wrapper<T>
{
public T Value { get; set; }
}
public static IEnumerable<T> Merge<T>(IEnumerable<T> first, IEnumerable<T> second, IComparer<T> comparer = null)
{
comparer = comparer ?? Comparer<T>.Default;
using (var secondIterator = second.GetEnumerator())
{
Wrapper<T> secondItem = null; //when the wrapper is null there are no more items in the second sequence
if (secondIterator.MoveNext())
secondItem = new Wrapper<T>() { Value = secondIterator.Current };
foreach (var firstItem in first)
{
if (secondItem != null)
{
while (comparer.Compare(firstItem, secondItem.Value) > 0)
{
yield return secondItem.Value;
if (secondIterator.MoveNext())
secondItem.Value = secondIterator.Current;
else
secondItem = null;
}
}
yield return firstItem;
yield return secondItem.Value;
while (secondIterator.MoveNext())
yield return secondIterator.Current;
}
}
}
一旦你拥有Merge
功能,它就非常简单:
File.WriteAllLines("output.txt",
Merge(File.ReadLines("File1.txt"), File.ReadLines("File2.txt")))
此处的文件ReadLines
和WriteAllLines
均使用IEnumerable
,并相应地对这些行进行流式处理。
答案 7 :(得分:0)
以下是合并排序2文件的更通用/样板解决方案的源代码。
public static void Merge(string inFile1, string inFile2, string outFile)
{
string line1 = null;
string line2 = null;
using (StreamReader sr1 = new StreamReader(inFile1))
{
using (StreamReader sr2 = new StreamReader(inFile2))
{
using (StreamWriter sw = new StreamWriter(outFile))
{
line1 = sr1.ReadLine();
line2 = sr2.ReadLine();
while(line1 != null && line2 != null)
{
// your comparison function here
// ex: (line1[0] < line2[0])
if(line1 < line2)
{
sw.WriteLine(line1);
line1 = sr1.ReadLine();
}
else
{
sw.WriteLine(line2);
line2 = sr2.ReadLine();
}
}
while(line1 != null)
{
sw.WriteLine(line1);
line1 = sr1.ReadLine();
}
while(line2 != null)
{
sw.WriteLine(line2);
line2 = sr2.ReadLine();
}
}
}
}
}
答案 8 :(得分:0)
public void merge_click(Object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Clear();
dt.Columns.Add("Name");
dt.Columns.Add("designation");
dt.Columns.Add("age");
dt.Columns.Add("year");
string[] lines = File.ReadAllLines(@"C:\Users\user1\Desktop\text1.txt", Encoding.UTF8);
string[] lines1 = File.ReadAllLines(@"C:\Users\user2\Desktop\text1.txt", Encoding.UTF8);
foreach (string line in lines)
{
string[] values = line.Split(',');
DataRow dr = dt.NewRow();
dr["Name"] = values[0].ToString();
dr["designation"] = values[1].ToString();
dr["age"] = values[2].ToString();
dr["year"] = values[3].ToString();
dt.Rows.Add(dr);
}
foreach (string line in lines1)
{
string[] values = line.Split(',');
DataRow dr = dt.NewRow();
dr["Name"] = values[0].ToString();
dr["designation"] = values[1].ToString();
dr["age"] = values[2].ToString();
dr["year"] = values[3].ToString();
dt.Rows.Add(dr);
}
grdstudents.DataSource = dt;
grdstudents.DataBind();
}