简体   繁体   English

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

[英]Split multiple csv files by value from one csv file with c#

I need to open a csv file. 我需要打开一个csv文件。 Than I need filter each data and generate an output for each value of them. 比我需要过滤每个数据并为它们的每个值生成一个输出。

◘ Example ◘例子

•Input file = "full list.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

Output will be = 输出将是=

• file1 = "full list_Venezia.csv" •file1 =“完整list_Venezia.csv”

NAME        CITY
Mark        Venezia
Nicolas     Venezia
Steve       Venezia

• file2 = "full list_New York.csv" •file2 =“完整list_New York.csv”

NAME        CITY
John        New York
Emily       New York
Amelia      New York

• file3 = "full list_San Miguel" •file3 =“完整列表_San Miguel”

NAME        CITY
Lisa        San Miguel
Bill        San Miguel

I'm using c# with ConsoleApplication on Visual Studio and I started to read the input file in this method: 我在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();

Is there an algorithm that allows me to filter the data I need? 有没有可以过滤所需数据的算法?

You have written most of the good parts yourself, and now you need to fill the blanks. 您已经自己编写了大部分好的部分,现在您需要填补空白。 Breaking down the steps 分解步骤

  • Read the CSV to a Collection 读取CSV到集合
  • Group Collection based on City 基于城市的团体收藏
  • Write the each group to separate file 将每个组写入单独的文件

The first step is of course is to read the input file 第一步当然是读取输入文件

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()});
}

I have assumed your DatiOutput looks like following as it was not given. 我假设您的DatiOutput看起来像以下,因为没有给出。

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

Then next step is to Group the collection based on City and then write them to file. 然后,下一步是根据城市对集合进行分组,然后将其写入文件。 You can use LINQ to group the collection based on City. 您可以使用LINQ根据城市对集合进行分组。

listOutput.GroupBy(c=>c.City)

Once your have the result, you can now create file name with corresponding city name appended, and add the data to it. 得到结果后,您现在可以创建文件名称并附加相应的城市名称,然后将数据添加到其中。

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}");
        }
    }
}

You would have the desired result 您将获得理想的结果

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}")));
}

The key part your example was missing was GroupBy - this allows you to group the data you have read in to groups based on a certain criteria (in our case City). 您的示例缺少的关键部分是GroupBy这使您可以根据特定条件(在本例中为City)将已读入的数据分组。

Group by is a powerful LINQ extension that allows you to filter data. 分组依据是功能强大的LINQ扩展,可让您过滤数据。 The example above reads in all the data, skips the header, uses select to transform each line into an instance of an anonymous type to contain the name and city. 上面的示例读取所有数据,跳过标题,使用select将每一行转换为匿名类型的实例,以包含名称和城市。 GroupBy is then used to group these instances by city. 然后使用GroupBy按城市对这些实例进行分组。 Then for each group the data is written to a new file. 然后,对于每个组,将数据写入新文件。

I would take @TVOHMs answer to slightly cleaner direction by keeping the same codestyle on the whole solution. 我会通过在整个解决方案上保持相同的代码风格,将@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

Here's a non-LINQy approach using a Dictionary to keep a reference to each output file based on the city name as the Key (there's nothing wrong with LINQ, though!): 这是一种非LINQy的方法,该方法使用Dictionary来以城市名称作为Key来保持对每个输出文件的引用(但是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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM