2013-10-29 38 views
0

有谁知道如何分割该文件如何分割由固定宽度C#中的文本行

1 TESTAAA  SERNUM A DESCRIPTION 
2 TESTBBB  ANOTHR ANOTHER DESCRIPTION 
3 TESTXXX  BLAHBL 

每列都有一个固定的宽度和我打算用正则表达式来做到这一点,但我不知道知道如何做到这一点。

具有

{id} {firsttext} {serialhere} {description} 
4 22   6   30+ 

有人建议用这样的图案({4})({22})({6})(+)?然后用split('')分割它,但用户表示这不适用于没有价值的列,但即使如此,他也没有做任何示例。

我也听说过TextFieldParser,但它有一些关于性能的问题。

谁能告诉我如何按固定宽度分割?

谢谢。

+0

尝试此Bing搜索以查看是否有任何工作f或者你http://www.bing.com/search?q = split + line + into + fixed + width + fields + c%23&qs = n&form = QBRE&pq = splitting + line + into + fixed + width + fields + c%23&sc = 0-0&sp = -1&sk =&cvid = 35a6d68b13594e22b05fd63428fe963b –

+2

Something像。(。{4})(。{22})(。{6})(。+)?'应该可以正常工作。你有什么尝试过,没有奏效? –

+1

以上建议以正则表达式为例 列表 result = new List (Regex.Split(target,@“(。{4})(。{22})(。{6})(。 +)?“,RegexOptions.Singleline)); – Marko

回答

4

没有看到任何理由不,我可能会只使用Substring

话虽如此,正则表达式也应该工作。

以下示例在显示的输入(而不是您提供的数字)上工作,并假定序列号是必填字段,但可能不占用其整个长度+说明是可选的。如果这些假设不正确,请按照该原则进行调整。

string input = @"1 TESTAAA  SERNUM A DESCRIPTION 
2 TESTBBB  ANOTHR ANOTHER DESCRIPTION 
3 TESTXXX  BLAHBL"; 

var split = input.Split('\n').Select(s => new { 
     Id = s.Substring(0, 2), 
     FirstText = s.Substring(2, 13), 
     Serial = s.Substring(15, Math.Min(s.Length-15, 10)), 
     Description = s.Length > 25 ? s.Substring(25) : String.Empty 
}); 

或具有更明显的命名和序列长度稍微清晰的例子的说明例子:

int idStart = 0; 
int idLength = 2; 
int firstTextStart = idStart + idLength; 
int firstTextLength = 13; 
int serialStart = firstTextStart + firstTextLength; 
int serialLength = 10; 
int descriptionStart = serialStart + serialLength; 

var verboseSplit = input.Split('\n').Select(s => new { 
    Id = s.Substring(idStart, idLength), 
    FirstText = s.Substring(firstTextStart, firstTextLength), 
    Serial = s.Length > descriptionStart 
       ? s.Substring(serialStart, serialLength) 
       : s.Substring(serialStart) 
    Description = s.Length > descriptionStart 
        ? s.Substring(descriptionStart) 
        : String.Empty 
}); 

输出从任:

Id FirstText  Serial  Description 
1 TESTAAA  SERNUM  A DESCRIPTION 

2 TESTBBB  ANOTHR  ANOTHER DESCRIPTION 

3 TESTXXX  BLAHBL 
2

根据您的样品试试这个,每个项目之间有一个单一的白色空间

{id} {firsttext} {serialhere} {description} 
4 22   6   30+ 

string target = "1 TESTAAA    SERNUM A DESCRIPTION"; 
List<string> result = new List<string>(Regex.Split(target, @"(.{4})(.{1})(.{22})(.{1})(.{6})(.{1})(.+)?", RegexOptions.Singleline)); 
+0

对不起,迟到!但我尝试了你的建议,但它分成9个部分! –

1

这种功能方法如何?

开始与这些阵列:

var lines = new [] 
{ 
    "1 TESTAAA  SERNUM A DESCRIPTION", 
    "2 TESTBBB  ANOTHR ANOTHER DESCRIPTION", 
    "3 TESTXXX  BLAHBL", 
}; 

var splits = new [] { 2, 13, 10, }; 

我使用的是splits从你的问题不同,因为每个样本行字段的长度简化版,匹配您的分裂。

现在定义一个递归函数来完成每一行的分裂:

Func<string, IEnumerable<int>, IEnumerable<string>> f = null; 
f = 
    (t, ns) => 
    { 
     if (ns.Any()) 
     { 
      var n = ns.First(); 
      var i = System.Math.Min(n, t.Length); 
      var t0 = t.Substring(0, i); 
      var t1 = t.Substring(i); 
      return new [] { t0.Trim(), }.Concat(f(t1, ns.Skip(1))); 
     } 
     else 
      return new [] { t.Trim(), }; 
    }; 

最后,我们可以写一个相当琐碎LINQ查询把它放在一起:

var query = 
    from line in lines 
    let fields = f(line, splits).ToArray() 
    select new 
    { 
     id = fields[0], 
     firsttext = fields[1], 
     serialhere = fields[2], 
     description = fields[3], 
    }; 

结果我得到是:

Results