将分隔转换为固定宽度的最佳方法

转换它的最佳方法是什么:

FirstName,LastName,Title,BirthDate,HireDate,City,Region Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA Andrew,Fuller,Vice President Sales,1952-02-19,1992-08-14,Tacoma,WA Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL 

对此:

 FirstName LastName Title BirthDate HireDate City Region ---------- -------------------- ------------------------------ ----------- ---------- --------------- --------------- Nancy Davolio Sales Representative 1948-12-08 1992-05-01 Seattle WA Andrew Fuller Vice President, Sales 1952-02-19 1992-08-14 Tacoma WA Janet Leverling Sales Representative 1963-08-30 1992-04-01 Kirkland WA Margaret Peacock Sales Representative 1937-09-19 1993-05-03 Redmond WA Steven Buchanan Sales Manager 1955-03-04 1993-10-17 London NULL Michael Suyama Sales Representative 1963-07-02 1993-10-17 London NULL Robert King Sales Representative 1960-05-29 1994-01-02 London NULL Laura Callahan Inside Sales Coordinator 1958-01-09 1994-03-05 Seattle WA Anne Dodsworth Sales Representative 1966-01-27 1994-11-15 London NULL 

你有两个问题。 单独考虑它们,您将更容易找到一个好的解决方案。

  1. 将CSV格式的输入数据解析为有用的格式。

  2. 以某种方式呈现您的数据

不要编写自己的CSV解析器。 规则有点棘手,但格式众所周知。 从长远来看,做错了会很糟糕。 您可以调用.NET框架中的现有CSV库,但我对它们了解不多。 但是,这个问题非常适合C#中的新dynamic特性。 这是一个看起来很有希望的: http : //tonikielo.blogspot.com/2010/01/c-40-dynamic-linq-to-csvhe.html

我假设打印数据是一个微不足道的问题,你不需要我们的帮助。 如果没有,您需要提供更多信息,例如您希望如何决定列的宽度。

我创建了一个自定义类来保存信息,然后为CSV文件中的每一行做一个循环,在逗号上拆分并填充自定义对象。 然后将它们全部放入列表或IEnumrable中并将其抛入转发器/ datagrid。

 public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string Title { get; set; } public DateTime BirthDate { get; set; } public DateTime HireDate { get; set; } public string City { get; set; } public string Region { get; set; } } public void Parse(string csv) { string[] lines = csv.Split( Environment.NewLine.ToCharArray() ); List persons = new List(); foreach (string line in lines) { string[] values = line.Split( ',' ); Person p = new Person(); p.FirstName = values[ 0 ]; p.LastName = values[ 1 ]; persons.Add( p ); //.... etc etc } } 

这符合您的要求,并使用LINQ(因为您的问题被标记为LINQ),但不一定是最好的

 class Program { static void Main(string[] args) { List inputs = new List { "FirstName,LastName,Title,BirthDate,HireDate,City,Region", "Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA", "Andrew,Fuller,Vice President Sales,1952-02-19,1992-08-14,Tacoma,WA", "Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA", "Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA", "Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL", "Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL", "Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL", "Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA", "Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL" }; // TODO: These widths would presumably be configurable List widths = new List { 12, 22, 32, 13, 12, 17, 8 }; List outputs = inputs.Select(s => ToFixedWidths(s, ',', widths)).ToList(); outputs.ForEach(s => System.Diagnostics.Debug.WriteLine(s)); Console.ReadLine(); } private static string ToFixedWidths(string s, char separator, List widths) { List split = s.Split(separator).ToList(); // TODO: Error handling - what if there are more/less separators in // string s than we have width values? return string.Join(String.Empty, split.Select((ss, i) => ss.PadRight(widths[i], ' ')).ToArray()); } } 

在一个生产场景中,虽然我希望看到这些数据被读入一个合适的Person类,正如Matt在他的回答中所推荐的那样。

我知道这样做的最简单方法是在PowerShell中

 PS> Import-Csv。\ x.csv | 格式表-AutoSize 

FirstName LastName Title BirthDate HireDate City Region
——— ——– —– ——— ——– —- ——
Nancy Davolio销售代表1948-12-08 1992-05-01西雅图华盛顿
Andrew Fuller销售副总裁1952-02-19 1992-08-14 Tacoma WA
Janet Leverling销售代表1963-08-30 1992-04-01 Kirkland WA

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace StringParsingWithLinq { internal class Program { private static void Main(string[] args) { var inputs = new List { "FirstName,LastName,Title,BirthDate,HireDate,City,Region", "Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA", "Andrew,Fuller,\"Vice President, Sales\",1952-02-19,1992-08-14,Tacoma,WA", "Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA", "Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA", "Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL", "Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL", "Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL", "Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA", "Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL" }; Console.Write(FixedWidthHelper.ReadLines(inputs) .ToFixedLengthString()); Console.ReadLine(); } #region Nested type: FixedWidthHelper public class FixedWidthHelper { private readonly Regex _csvRegex = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"); private readonly List _data = new List(); private List _fieldLen; public static FixedWidthHelper ReadLines(List lines) { var fw = new FixedWidthHelper(); lines.ForEach(fw.AddDelimitedLine); return fw; } private void AddDelimitedLine(string line) { string[] fields = _csvRegex.Split(line); if (_fieldLen == null) _fieldLen = new List(fields.Select(f => f.Length)); for (int i = 0; i < fields.Length; i++) { if (fields[i].Length > _fieldLen[i]) _fieldLen[i] = fields[i].Length; } _data.Add(fields); } public string ToFixedLengthString() { var sb = new StringBuilder(); foreach (var list in _data) { for (int i = 0; i < list.Length; i++) { sb.Append(list[i].PadRight(_fieldLen[i] + 1, ' ')); } sb.AppendLine(); } return sb.ToString(); } } #endregion } } 

替代文字

我只是为了这个目的写了tablify 。 安装时

 [sudo -H] pip3 install tablify 

 tablify input.dat 

会给你

 FirstName , LastName , Title , BirthDate , HireDate , City , Region Nancy , Davolio , Sales Representative , 1948-12-08 , 1992-05-01 , Seattle , WA Andrew , Fuller , Vice President Sales , 1952-02-19 , 1992-08-14 , Tacoma , WA Janet , Leverling , Sales Representative , 1963-08-30 , 1992-04-01 , Kirkland , WA Margaret , Peacock , Sales Representative , 1937-09-19 , 1993-05-03 , Redmond , WA Steven , Buchanan , Sales Manager , 1955-03-04 , 1993-10-17 , London , NULL Michael , Suyama , Sales Representative , 1963-07-02 , 1993-10-17 , London , NULL Robert , King , Sales Representative , 1960-05-29 , 1994-01-02 , London , NULL Laura , Callahan , Inside Sales Coordinator , 1958-01-09 , 1994-03-05 , Seattle , WA Anne , Dodsworth , Sales Representative , 1966-01-27 , 1994-11-15 , London , NULL 

从那里,应该很容易根据您的需要调整文件。