按固定宽度将字符串拆分为子字符串

Sim*_*mon 7 c# winforms

我有这样的数据......

   1 TESTAAA      SERNUM    A DESCRIPTION
   2 TESTBBB      ANOTHR    ANOTHER DESCRIPTION
   3 TESTXXX      BLAHBL
Run Code Online (Sandbox Code Playgroud)

我的问题是,将这些数据分成较小的子串的最有效方法是什么,因为会有数百行.此外,一些行将缺少最后一列.我试图做正则表达式,但是我用于宽度的模式没有成功.上面的数据应分解为这些字段(下面列出的每列的长度)

{id} {firsttext} {serialhere} {description}
 4    22          6            30+
Run Code Online (Sandbox Code Playgroud)

任何人都可以伸出援助之手或建议一个良好的正则表达式匹配模式来提取信息吗?

谢谢,西蒙

Hew*_*lff 7

试试以下正则表达式:

(.{4})(.{22})(.{6})(.+)?
Run Code Online (Sandbox Code Playgroud)

如果值总是非空的并且用空格分隔(也就是说,它们不会相互碰撞),那么尝试一些更简单的东西

line.Split(" ")
Run Code Online (Sandbox Code Playgroud)


Ree*_*sey 6

我实际上建议直接通过String.Substring编写一个方法.这可能会更有效地为您提供确切的所需宽度.

这可能会起作用(虽然它未经测试,并且故意不剥离字符串填充):

public static string[] SplitFixedWidth(string original, bool spaceBetweenItems, params int[] widths)
{
    string[] results = new string[widths.Length];
    int current = 0;

    for (int i = 0; i < widths.Length; ++i)
    {
        if (current < original.Length)
        {
            int len = Math.Min(original.Length - current, widths[i]);
            results[i] = original.Substring(current, len);
            current += widths[i] + (spaceBetweenItems ? 1 : 0);
        }
        else results[i] = string.Empty;
    }

    return results;
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,如果您Stream直接从文本文件或文本文件中读取它,使用TextFieldParser将允许您直接读取数据作为固定宽度数据.


Ste*_*art 6

查看MSDN上的此链接:

http://msdn.microsoft.com/en-us/library/zezabash.aspx

基本上,TextFieldParser班级确实做了这样的事情.它也是读取分隔数据(如CSV文件)的好方法.无论出于何种原因,微软都选择将它置于Microsoft.VisualBasic.FileIO命名空间之下,这很烦人,因为它与VB没有任何关系.

例如,您可以像这样使用它:

TextFieldParser parser = new TextFieldParser(new StringReader(fixedWidthData));
parser.TextFieldType = FieldType.FixedWidth;
parser.SetFieldWidths(4, 22, 6, -1);
while (!parser.EndOfData)
{
    string[] row = parser.ReadFields();
}
Run Code Online (Sandbox Code Playgroud)