将字符串解析为多个可变长度字符串(C#)

时间:2010-06-10 10:59:12

标签: c# split structure variable-length

我目前正在尝试将VB6程序转换为C#。在结构中广泛使用字符串拆分。例如,

Dim Sample AS String
Sample = "John Doe        New York  Test Comment"

Public Type Struct1
    Name As String * 15
    Address As String * 10
    Comment As String * 20
End Type

Dim dataStruct As Struct1

Set dataStruct = Sample

设置dataStruct后,它会自动将值拆分为3结构成员。在C#中有一个特殊的功能吗?我知道如何做到这一点的唯一方法是通过描述字符串的长度和起始位置的属性/注释。还有其他建议吗?

5 个答案:

答案 0 :(得分:3)

您可以查看FileHelpersmethods来执行此操作。

答案 1 :(得分:3)

您可以尝试使用隐式运算符:

class Program
{
    static void Main(string[] args)
    {
        string sample = "John Doe        New York  Test Comment";
        MyClass c = sample;
    }
}

public class MyClass
{
    public string Name;
    public string Address;
    public string Comment;

    public MyClass(string value)
    {
        //parsing of value and assigning to Name, Adress, Comment comes here
    }

    public static implicit operator MyClass(string value)
    {
        return new MyClass(value);
    }
}

对于字符串值的解析,您可以使用正则表达式。

答案 2 :(得分:2)

我不知道有任何内置方法可以做到这一点,但使用属性听起来像是对我这样做的好方法。然后,您可以编写代码以通过反射设置相关属性。除非你在字符串中有间隙,否则我会把它表示为相对排序和长度而不是起始位置 - 然后你可以找到所有的属性,按它们的排序排序(不应该要求连续排序 - 排序0,10,20,30,40可以在必要时添加额外的属性,并以此方式进行拆分。

答案 3 :(得分:1)

您可以使用运算符重载来模拟赋值行为。这样,目标类还定义了部件的大小,因此每个类必须知道输入的外观。它比VB示例多一点。

示例(语法可能不正确,我很少使用运算符重载):

class DataItem
{
  public String Name {get;set;}
  public String Address {get;set;}
  public String Comment {get;set;}

  public static implicit operator DataItem(string value)
  {
    DataItem item = new DataItem();
    item.Name = string.Substring(0, 10).Trim();
    item.Address = string.Substring(10, 25).Trim();
    item.Comment = string.Substring(25, 45).Trim();
    return item;
  }
}

[...]
DataItem item = sampleString;
[...]

更具可读性的替代方案是隐式创建者模式:

class DataItem
{
  public String Name {get;set;}
  public String Address {get;set;}
  public String Comment {get;set;}

  public static DataItem FromString(String string)
  {
    DataItem item = new DataItem();
    item.Name = string.Substring(0, 10).Trim();
    item.Address = string.Substring(10, 25).Trim();
    item.Comment = string.Substring(25, 45).Trim();
    return item;
  }
}

[...]
DataItem item = DataItem.FromString(sampleString);
[...]

答案 4 :(得分:1)

如果没有P / Invoke marshaller,这样的结构映射技巧是行不通的。结构的内部组织是不可发现的。 JIT编译器很容易利用这一点,如果为结构产生较小的内存大小,它会交换成员。只有[StructLayout]才能确定它。

Microsoft.VisualBasic命名空间中有另一个好东西,这使得这很容易。 TextFieldParser类可以通过一次调用轻松转换这样的字符串。例如:

using System;
using System.IO;
using Microsoft.VisualBasic.FileIO;  // NOTE: add reference to Microsoft.VisualBasic

class Program {
    static void Main(string[] args) {
        var strm = new StringReader("John Doe        New York  Test Comment");
        var parse = new TextFieldParser(strm);
        parse.TextFieldType = FieldType.FixedWidth;
        parse.SetFieldWidths(16, 10, 12);
        foreach (var field in parse.ReadFields())
            Console.WriteLine(field.Trim());
        Console.ReadLine();
    }
}

请注意,您发布的原始字符串与结构声明不匹配,我不得不修改字段宽度。另请注意,TextFieldParser接受任何流,它不必是存储在StringReader中的字符串。读取文件的StreamReader将是更典型的用途。