20

我有一个充满记录的文本文件,其中每条记录中的每个字段都是固定宽度。我的第一种方法是简单地使用 string.Substring() 解析每条记录。有没有更好的办法?

例如,格式可以描述为:

<Field1(8)><Field2(16)><Field3(12)>

一个包含两条记录的示例文件可能如下所示:

SomeData0000000000123456SomeMoreData
Data2   0000000000555555MoreData    

我只是想确保我没有忽略比 Substring() 更优雅的方式。


更新: 我最终使用了 Killersponge 建议的正则表达式:

private readonly Regex reLot = new Regex(REGEX_LOT, RegexOptions.Compiled);
const string REGEX_LOT = "^(?<Field1>.{6})" +
                        "(?<Field2>.{16})" +
                        "(?<Field3>.{12})";

然后我使用以下内容访问这些字段:

Match match = reLot.Match(record);
string field1 = match.Groups["Field1"].Value;
4

7 回答 7

30

使用FileHelpers

例子:

[FixedLengthRecord()] 
public class MyData
{ 
  [FieldFixedLength(8)] 
  public string someData; 

  [FieldFixedLength(16)] 
  public int SomeNumber; 

  [FieldFixedLength(12)] 
  [FieldTrim(TrimMode.Right)]
  public string someMoreData;
}

然后,就这么简单:

var engine = new FileHelperEngine<MyData>(); 

// To Read Use: 
var res = engine.ReadFile("FileIn.txt"); 

// To Write Use: 
engine.WriteFile("FileOut.txt", res); 
于 2008-10-02T15:14:29.670 回答
7

子字符串对我来说听起来不错。我能立即想到的唯一缺点是它意味着每次都复制数据,但在你证明这是一个瓶颈之前,我不会担心这一点。子字符串很简单:)

可以使用正则表达式一次匹配整条记录并捕获字段,但我认为这太过分了。

于 2008-10-02T14:55:40.183 回答
7

为什么要重新发明轮子?按照 Visual Basic 的此操作指南使用 .NET 的TextFieldParser类:如何从固定宽度的文本文件中读取

于 2012-09-23T04:50:10.907 回答
2

您可能需要注意,如果行尾没有用空格填充以填充该字段,那么您的子字符串将无法正常工作,而无需稍加摆弄即可计算出还有多少行要读取。这当然只适用于最后一个字段:)

于 2008-10-02T15:00:14.913 回答
1

不幸的是,CLR 开箱即用只为此提供子字符串。

CodeProject 的某个人使用属性来定义字段制作了一个自定义解析器,你可能想看看。

于 2008-10-02T15:17:36.510 回答
0

不,子字符串很好。这就是它的用途。

于 2008-10-02T14:55:27.377 回答
0

您可以为固定格式文件设置 ODBC 数据源,然后像访问任何其他数据库表一样访问它。这还有一个额外的好处,即在某人决定在中间添加一个额外字段的那一天,文件格式的特定知识不会编译到您的代码中。

于 2008-10-02T19:26:55.023 回答