代码之家  ›  专栏  ›  技术社区  ›  Nap

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

  •  1
  • Nap  · 技术社区  · 14 年前

    我正在尝试将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 回复  |  直到 14 年前
        1
  •  3
  •   Darin Dimitrov    14 年前

    你可以看一下 FileHelpers 图书馆 methods

        2
  •  3
  •   Matthias    14 年前

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

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

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

        3
  •  2
  •   Jon Skeet    14 年前

    我不知道有什么内在的方法可以做到这一点,但是使用属性对我来说听起来是一种很好的方法。然后可以编写代码,通过反射设置相关属性。除非字符串中有间隙,否则我会将其表示为相对顺序和长度,而不是起始位置-然后您可以找到所有属性,按它们的顺序排序(不需要连续-顺序为0、10、20、30,40使添加额外属性(如果需要)和以这种方式计算拆分变得更容易。

        4
  •  1
  •   Morfildur    14 年前

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

    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);
    [...]
    
        5
  •  1
  •   Hans Passant    14 年前

    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将是更典型的用法。