从文本文件中读取固定宽度的记录
时间:2020-03-06 15:01:50 来源:igfitidea点击:
我有一个充满记录的文本文件,其中每个记录中的每个字段都是固定宽度。我的第一种方法是仅使用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;
解决方案
不,Substring很好。那就是它的目的。
子串对我来说听起来不错。我立即想到的唯一缺点是,这意味着每次都要复制数据,但是除非我们证明它是瓶颈,否则我不会担心。子串很简单:)
我们可以使用正则表达式来一次匹配整个记录并捕获字段,但是我认为这会过分杀了。
我们可能需要注意,如果未在行尾填充空格以填充该字段,那么子字符串将无法工作,而无需花太多时间去弄清楚要读取的行数。当然,这仅适用于最后一个字段:)
使用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);
不幸的是,CLR开箱即用仅为此提供子字符串。
CodeProject上的某人使用属性定义字段创建了一个自定义解析器,我们可能想看看。
我们可以为固定格式的文件设置ODBC数据源,然后像访问其他任何数据库表一样对其进行访问。
这具有一个额外的优点,即在某人决定在中间添加一个额外字段的那个重要日子里,文件格式的特定知识不会编译到代码中。