【问题标题】:Parsing String into multiple variable length String (C#)将字符串解析为多个可变长度字符串(C#)
【发布时间】:2010-06-10 10:59:12
【问题描述】:

我目前正在尝试将 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# 中是否有特殊功能可以执行此操作。我知道如何做到这一点的唯一方法是通过描述字符串长度和起始位置的属性/注释。还有什么建议吗?

【问题讨论】:

    标签: c# split structure variable-length


    【解决方案1】:

    您可以查看 FileHelpers 库,其中有 methods 用于执行此操作。

    【讨论】:

      【解决方案2】:

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

      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】:

        我不知道有任何内置方法可以做到这一点,但使用属性对我来说听起来是个不错的方法。然后,您可以编写代码以通过反射设置相关属性。除非字符串中有空格,否则我会将其表示为相对排序和长度而不是起始位置 - 然后你可以找到所有属性,按它们的顺序排序(不应该要求是连续的 - 排序0, 10, 20, 30, 40 可以更容易地在必要时添加额外的属性)并以这种方式计算拆分。

        【讨论】:

        • 我可能需要放置开始和结束,因为我跳过了一些值
        【解决方案4】:

        您可以使用运算符重载来模拟赋值行为。这样,目标类还定义了部件的大小,因此每个类都必须知道输入的外观。它比 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);
        [...]
        

        【讨论】:

        • 你的意思可能是public static implicit operator DataItem(string value),所以你可以说DataItem item = "...";你无法在 C# 中更改赋值运算符。
        【解决方案5】:

        如果没有 P/Invoke 编组器,这样的结构映射技巧就无法工作。结构的内部组织是不可发现的。 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 将是更典型的用途。

        【讨论】:

        • 这很好,但我需要将每个字段放置到指定的记录中。但这是一个有趣的视觉基础功能。放弃投票
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-19
        • 2019-07-24
        • 2013-12-12
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        相关资源
        最近更新 更多