我有一个输入文件,其中包含位置格式的记录(例如,列First Name
位于1到10位)
John Doe john@example.com
这显然过于简单了。我真的有超过25列,所以使用Mid
是可能的,但过于复杂。我想我可以编写一个可以解析它的类,但我想确保在浪费时间之前这些不是更好的方法。
答案 0 :(得分:3)
Microsoft.VisualBasic.FileIO.TextFieldParser类可以解析固定宽度格式。基本用法是创建类的实例,设置属性以指示格式是固定宽度,调用方法以指定每列的宽度,然后启动循环以一次读取一条记录的数据。这是an example from MSDN。在此示例中,文件有4列,宽度为5,宽度为10,宽度为11,最后一列为无限长度(-1)。
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\TestFolder\test.log")
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.FixedWidth
Reader.SetFieldWidths(5, 10, 11, -1)
Dim currentRow As String()
While Not Reader.EndOfData
Try
currentRow = Reader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
MsgBox(currentField)
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
End Using
答案 1 :(得分:1)
Ryan的答案更合适(不知道上课存在)你需要什么。
然而,由于我已经写了这个C#版本,我将在此发布,因为它可能会在将来为其他人派上用场
基本上,创建一些委托来处理每列的实际操作。然后循环遍历每个部分的行和Substring
。正如评论中指出的那样,Substring
并不是非常优化,但是,很容易理解这一点并改变实际读取列的方式。
VB.NET版本
Public Class Person
Public Property FirstName As String
Public Property LastName As String
Public Property Email As String
End Class
Public Class ColumnHandler
Public Property Process As Action(Of Person, String)
Public Property Length As Integer
Public Sub New(processAction As Action(Of Person, String), columnLength As Integer)
Process = processAction
Length = columnLength
End Sub
End Class
Module Module1
Sub Main()
Dim columnHandlers() As ColumnHandler =
{
New ColumnHandler(Sub(p, s) p.FirstName = s, 10),
New ColumnHandler(Sub(p, s) p.LastName = s, 10),
New ColumnHandler(Sub(p, s) p.Email = s, 16)
}
Dim fileLines() As String =
{
"John Doe john@example.com",
"Ty Cobb anon@example.com"
}
Dim people As New List(Of Person)
For Each line As String In fileLines
Dim currentPosition As Integer = 0
Dim person As New Person()
For Each columnHandler As ColumnHandler In columnHandlers
columnHandler.Process.Invoke(person, line.Substring(currentPosition, columnHandler.Length).Trim())
currentPosition += columnHandler.Length
Next
people.Add(person)
Next
Console.WriteLine(people.Count.ToString())
Console.WriteLine(people(1).LastName)
Console.ReadLine()
End Sub
End Module
C#版(因为我显然不知道如何阅读问号或标题)
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
void Main()
{
var columnHandlers = new[]
{
new {Process = new Action<Person, string>((p, s) => p.FirstName = s), Length = 10},
new {Process = new Action<Person, string>((p, s) => p.LastName = s), Length = 10},
new {Process = new Action<Person, string>((p, s) => p.Email = s), Length = 16},
};
//Replace this with a stream or however you were going to get/read the lines
var fileLines = new[]
{
"John Doe john@example.com",
"Ty Cobb anon@example.com",
};
var people = new List<Person>();
foreach (var line in fileLines)
{
var currentPosition = 0;
var person = new Person();
foreach (var columnHandler in columnHandlers)
{
columnHandler.Process(person, line.Substring(currentPosition, columnHandler.Length).Trim());
currentPosition += columnHandler.Length;
}
people.Add(person);
}
Console.WriteLine(people.Count.ToString());
Console.WriteLine(people[1].LastName);
}