使用c#从一个csv文件中按值拆分多个csv文件

时间:2018-12-30 13:38:04

标签: c# console-application

我需要打开一个csv文件。比我需要过滤每个数据并为其生成每个值的输出。

◘示例

•输入文件=“ full list.csv”

NAME        CITY
Mark        Venezia
John        New York
Lisa        San Miguel
Emily       New York
Amelia      New York
Nicolas     Venezia
Bill        San Miguel
Steve       Venezia

输出将为=

•file1 =“完整list_Venezia.csv”

NAME        CITY
Mark        Venezia
Nicolas     Venezia
Steve       Venezia

•file2 =“完整列表_New York.csv”

NAME        CITY
John        New York
Emily       New York
Amelia      New York

•file3 =“完整列表_圣米格尔”

NAME        CITY
Lisa        San Miguel
Bill        San Miguel

我在Visual Studio上将C#与ConsoleApplication一起使用,并开始以这种方法读取输入文件:

string inputFile = "full list.csv";
string outputFile;
string line;
string titles = File.ReadLines(inputFile).First();
System.IO.StreamReader file = new System.IO.StreamReader(inputFile);
while ((line = file.ReadLine()) != null)
{
}
file.Close();

System.IO.StreamWriter fileOut = new System.IO.StreamWriter(outputFile);
foreach (DatiOutput objOut in listOutput)
{
}
fileOut.Close();

有没有可以过滤所需数据的算法?

4 个答案:

答案 0 :(得分:1)

您已经亲自编写了大部分优秀文章,现在您需要填补空白。 分解步骤

  • 将CSV读取到集合
  • 基于城市的团体收藏
  • 写 每组要分开的文件

当然第一步是读取输入文件

var listOutput = new List<DatiOutput>();
while ((line = file.ReadLine()) != null)
{
    var data = line.Split(new []{";"},StringSplitOptions.RemoveEmptyEntries);
    if(!data[0].Trim().Equals("NAME"))
        listOutput.Add(new DatiOutput{ Name = data[0].Trim(), City = data[1].Trim()});
}

我认为您的DatiOutput看起来很像,因为它没有给出。

public class DatiOutput 
{
public string City{get;set;}
public string Name{get;set;}
}

然后下一步是根据城市对集合进行分组,然后将其写入文件。您可以使用LINQ根据城市对集合进行分组。

listOutput.GroupBy(c=>c.City)

获得结果后,您现在可以创建带有相应城市名称的文件名,并将数据添加到其中。

foreach (var objOut in listOutput.GroupBy(c=>c.City))
{
    var filePath = $"{Path.Combine(Path.GetDirectoryName(inputFile),Path.GetFileNameWithoutExtension(inputFile))}_{objOut.First().City}.csv";

    using(System.IO.StreamWriter fileOut = new System.IO.StreamWriter(File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)))
    {
        fileOut.WriteLine($"NAME;CITY");
        foreach(var items in objOut)
        {
            fileOut.WriteLine($"{items.Name};{items.City}");
        }
    }
}

您将获得理想的结果

答案 1 :(得分:1)

foreach (var g in File.ReadAllLines("full list.csv")
    .Skip(1)
    .Select(l => new {
        Name = l.Substring(0, l.IndexOf(',')),
        City = l.Substring(l.IndexOf(',') + 1) })
    .GroupBy(l => l.City))
{
    File.WriteAllLines($"full list_{g.Key}.csv", new[] { "NAME,CITY" }
        .Concat(g.Select(l => $"{l.Name},{l.City}")));
}

您的示例缺少的关键部分是GroupBy-这使您可以根据特定条件(在我们的示例中为City)将已读入的数据分组到组中。

分组依据是功能强大的LINQ扩展名,可用于过滤数据。上面的示例读取所有数据,跳过标题,使用select将每一行转换为anonymous type的实例,以包含名称和城市。然后,GroupBy用于按城市对这些实例进行分组。然后将每个组的数据写入一个新文件。

答案 2 :(得分:1)

我会通过在整个解决方案中保持相同的代码样式,来使@TVOHMs回答更清晰的方向。

File.ReadAllLines("full list.csv")         // Read the input file
    .Skip(1)                               // Skip the header row
    .Select(row => row.Split(','))         // Split each row to array of city and name
    .GroupBy(row => row[1], row => row[0]) // Group by cities, selecting names
    .ToList()                              // To list, so .ForEach is possible
    .ForEach(group => File.WriteAllLines($"full list_{group.Key}.csv", group)); // Create file for each group and write the names

答案 3 :(得分:1)

这是一种使用字典的非LINQy方法,以城市名称作为键来保留对每个输出文件的引用(但是LINQ并没有错!):

string[] values;
string header;
string line, city, outputFileName;
string inputFile = "full list.csv";
Dictionary<string, System.IO.StreamWriter> outputFiles = new Dictionary<string, System.IO.StreamWriter>();
using (System.IO.StreamReader file = new System.IO.StreamReader(inputFile))
{
    header = file.ReadLine();
    while ((line = file.ReadLine()) != null)
    {
        values = line.Split(",".ToCharArray());
        city = values[1];
        if (!outputFiles.ContainsKey(city))
        {
            outputFileName = "full list_" + city + ".csv";
            outputFiles.Add(city, new System.IO.StreamWriter(outputFileName));
            outputFiles[city].WriteLine(header);
        }
        outputFiles[city].WriteLine(line);
    }
}   
foreach(System.IO.StreamWriter outputFile in outputFiles.Values)
{
    outputFile.Close();
}