提前读取文件一行

时间:2014-08-27 13:07:29

标签: c#

我有一个相当大的文件,大约80MB,并希望将其分成几块。 我的管道分隔文件结构是这样的:

Name|ID|Phone|Address
Al|34|3453453234|123 Main
Bo|456|44545|123 Main
Al|34|455666|5th Ave
James|007|7021023456|Green Ave

但是当你看到一个人的信息可能散布在整个文件中时所以首先LINQ编写了一个文件分类器来按ID对文件的行进行排序,所以我的文件现在看起来像这样:

Name|ID|Phone|Address
James|007|7021023456|Green Ave
Al|34|3453453234|123 Main
Al|34|455666|5th Ave
Bo|456|44545|123 Main

我想说好的让我们把它分成更小的文件,让每个文件最多包含50个人。所以关键的事情,也是我无法弄清楚的主要事情是如何编写代码,确保每个文件最多包含50个人 AND 确保每个人的记录都在相同文件中?

2 个答案:

答案 0 :(得分:1)

可能有以下几点:

// Take 50 records
var first50 = source.Take(50).ToList();

// Add all records which have the same name as the last taken record
var additional = source.TakeWhile(p => p.Name == first50.Last().Name);

需要一些角落案件处理(空文件等),但这个想法应该有用。

答案 1 :(得分:1)

也许有一些更简单但这应该有效:

var dataLines = File.ReadLines(@"C:\Temp\SplitFileTest\BigFile.txt")
    .SkipWhile(l => String.IsNullOrWhiteSpace(l)).Skip(1); //skip header
var dataIdGroups = dataLines
    .Select(l => new { Line = l.Trim(), Fields = l.Trim().Split('|') })
    .Where(x => x.Fields.Length == 4)
    .Select(x => new
    {
        Name = x.Fields[0],
        ID = x.Fields[1],
        Phone = x.Fields[2],
        Address = x.Fields[3],
        Line = x.Line
    })
    .GroupBy(x => x.ID);

var allFileLines = new List<List<string>>();
foreach (var userGroup in dataIdGroups)
{
    if (userGroup.Count() > 50 || allFileLines.Count == 0 || allFileLines.Last().Count + userGroup.Count() > 50)
        allFileLines.Add(userGroup.Select(x => x.Line).ToList());
    else
        allFileLines.Last().AddRange(userGroup.Select(x => x.Line));
}


for(int i = 0; i < allFileLines.Count; i++)
    File.WriteAllLines(
        string.Format(@"C:\Temp\SplitFileTest\UserFile_{0}.txt", i + 1), 
        allFileLines[i]);

我已经使用一些示例数据对其进行了测试,并且它从一个大文件中创建了4个文件,每个用户始终完全在一个文件中。只有当文件包含少于50行并且下一个用户确实适合该文件时,它才会混合。