Разбор строки в строку переменной длины (C #) - PullRequest
1 голос
/ 10 июня 2010

В настоящее время я пытаюсь преобразовать программу 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 ]

3 голосов
/ 10 июня 2010

Вы можете попробовать использовать неявный оператор:

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 голосов
/ 10 июня 2010

Вы можете взглянуть на библиотеку FileHelpers , в которой есть методы для этого.

2 голосов
/ 10 июня 2010

Я не знаю ни одного встроенного способа сделать это, но использование атрибута звучит как хороший способ сделать это для меня. Затем вы можете написать код для установки соответствующих свойств с помощью отражения. Если у вас нет пробелов в строке, я бы выразил это как относительный порядок и длину, а не как начальную позицию - тогда вы можете просто найти все атрибуты, отсортировав их по порядку (что не обязательно должно быть последовательным - порядок 0, 10, 20, 30, 40 упрощает добавление дополнительного свойства при необходимости) и обрабатывает разбиение таким образом.

1 голос
/ 10 июня 2010

Подобные трюки с отображением структуры не могут работать без маршаллера 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, который читает файл, будет более типичным использованием.

1 голос
/ 10 июня 2010

Вы можете использовать перегрузку операторов для эмуляции поведения присваивания. Таким образом, целевой класс также определяет размер частей, поэтому каждый класс должен знать, как должны выглядеть входные данные. Это немного больше кода, чем пример 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);
[...]
...