2010-06-10 77 views
1

我正在尝试将VB6程序转换为C#。有大量的字符串拆分成结构。例如,将字符串解析为多个可变长度字符串(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#中执行此操作。我知道如何做到这一点的唯一方法是通过描述字符串长度和起始位置的Attributes/Annotation。任何其他建议?

回答

3

你可以看看FileHelpers这个库有methods这样做。

+0

谢谢。这段代码正是我所需要的。 – Nap 2010-06-11 00:50:53

2

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

+0

我可能需要放置开始和结束,因为我跳过一些值 – Nap 2010-06-11 00:52:05

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); 
[...] 
+0

您可能意指'公共静态隐式运算符DataItem(字符串值)',因此您可以说'DataItem item =“...”';您无法在C#中更改赋值运算符。 – Ruben 2010-06-10 11:24:27

+0

谢谢,纠正它(我认为) – dbemerlin 2010-06-10 11:30:02

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

为了解析字符串值,你可以使用正则表达式。

1

像这样的结构映射技巧如果没有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将是更典型的用法。

+0

这很好,但我需要将每个字段放在指定的记录。但它是一个有趣的visualbasic功能。给予upvote – Nap 2010-06-11 00:55:02