2014-12-04 82 views
0

我有一個輸入文件包括在位置格式的記錄(前柱First Name是在位置1至10)有沒有辦法解析Visual Basic中的位置文件?

像這樣:
John Doe [email protected]

這顯然過於簡化。我真的有超過25列,所以使用Mid是可能的,但過於複雜。我想我可以寫一個能解析它的類,但是我想確保這些不是一個更好的方式,然後再浪費時間。

+0

什麼是分隔符?它是Tab還是總是n個空格?您可以嘗試使用CSV Helper將其分解出來。 https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations – TyCobb 2014-12-04 04:16:15

+0

@TyCobb:沒有分隔符,這就是爲什麼它很難。否則它將是一個簡單的'String.Parse()'。但它是位置格式。所以,列總是有固定的大小。所有列都有固定數量的職位。 – 2014-12-04 04:25:01

+0

那實際上並沒有那麼壞。比任何東西都更單調。給我幾個。我會寫一個幾年前爲此做的一個小例子。 – TyCobb 2014-12-04 04:31:43

回答

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 
+0

可以使用字符串作爲輸入嗎? – 2014-12-04 05:03:38

+0

@ MDTech.us_MAN http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser%28v=vs.110%29.aspx – TyCobb 2014-12-04 05:04:47

+0

@TyCobb:哦,對。我沒有時間開始閱讀該課程的文檔。 – 2014-12-04 05:06:55

1

瑞恩的答案比你想要的更合適(不知道這個類是否存在)。

但是,因爲我已經寫的這個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  [email protected]", 
       "Ty  Cobb  [email protected]" 
      } 

     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  [email protected]", 
     "Ty  Cobb  [email protected]", 
    }; 

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

當然。我現在要檢查Ryan的答案。 – 2014-12-04 05:01:36

+0

好吧,TyCobb,我也覺得它有點乾淨。 – 2014-12-04 05:03:03

+0

@ MDTech.us_MAN它應該是你真正想要使用的答案。我不知道VB有一個類。 – TyCobb 2014-12-04 05:03:17

相關問題