Private Sub parse_textfile(ByVal sFilename As String)
'Instead of reading all lines at the beginning of the sub, I chose to use a StremReader
'this time and read one line at the time. The lines are passed on to the sub parse_line,
'where they are parsed and the contents dealt with.
Dim f As New StreamReader(sFilename)
Do
parse_line(f.ReadLine())
Loop Until f.EndOfStream
f.Close()
End Sub
Private Sub parse_line(ByVal sLine As String)
'Expecting [f1] [f2] [f3] [f4] [f5] (opt_1)? <opt_2>?
'The usual way to do this would be to split at the spaces, but since space is allowed
'within names, this is not possible.
Dim i, j As Integer 'Used to store indeces in various places
Dim fields() As String 'Used to store field-content.
Dim f_opt_1 As String = ""
Dim f_opt_2 As String = "" 'Used to store content from optional fields.
Dim sLinecopy As String = sLine 'Copy of the line that can be modified.
Dim sSavedata As New StringBuilder 'Used to store data on the way.
'1) Locate and seperate out <opt_2>
If sLinecopy.EndsWith(">") Then
i = sLinecopy.LastIndexOf("<")
If i > 0 Then
f_opt_2 = sLinecopy.Substring(i + 1).TrimEnd(">"c) 'Get the contents of <opt_2>
sLinecopy = sLine.Remove(i - 1) 'Strip <opt_2> and trailing space away.
End If
End If
'2) Locate and seperate out (opt_1)
If sLinecopy.EndsWith(")") Then
i = sLinecopy.LastIndexOf("(")
If i > 0 Then
f_opt_1 = sLinecopy.Substring(i + 1).TrimEnd(")"c) 'Get the content of (opt_1)
sLinecopy = sLine.Remove(i - 1) 'Strip (opt_1) and trailing space away.
End If
End If
'3) The current line being parsed is now [f1] [f2] [f3] [f4] [f5].
' The code-line below will split the current contents into fields (hopefully 5).
' The code-line relies on no fields having '|' in them or it will fail
' and write out the current line being parsed as illegal.
' If you encounter problems (ie. fields having '|' in them) try using '[' or ']'.
fields = sLinecopy.TrimStart("["c).TrimEnd("]"c).Replace("] [", "|").Split("|"c)
'-----------------------------------------------------------------------------
'All field-data is now retrieved, and it's time to start parsing the fields.
'Does the line contain the right number of fields.
If fields.Length <> 5 Then
Console.WriteLine(String.Format("Illegal line: '{0}'.", sLine))
Exit Sub
End If
'---------------------
'Parse the first field [hh:mm:ss.t{1,3}]
Try
Dim time As DateTime = DateTime.Parse(fields(0).Substring(0, 8))
Dim thousands As Integer = Integer.Parse(fields(0).Substring(9, fields(0).Length - 9))
'-> Field 1 format here
sSavedata.Append(String.Format("Time:'{0}'+Thousands:'{1}'|", _
time.ToLongTimeString, thousands.ToString))
Catch ex As ArgumentOutOfRangeException
Catch ex As FormatException
Console.WriteLine(String.Format("Illegal field 1: '{0}' in line '{1}'.", fields(0), sLine))
Exit Sub
End Try
'---------------------
'Parse the second field [@player], [@player:companion {id}] or [monster {id}:id]
Try
If fields(1).StartsWith("@") Then
If fields(1).Contains(":") Then
'The second field is the name of a companion.
i = fields(1).IndexOf(":")
j = fields(1).IndexOf("{")
'-> Field 2 format for companion here
sSavedata.Append(String.Format("Companion:'{0}'", fields(1).Substring(i + 1, j - i - 2)))
Else
'The second field is the name of a player.
'-> Field 2 format for player here
sSavedata.Append(String.Format("Player:'{0}'", fields(1).Substring(1, fields(1).Length - 1)))
End If
Else
'The second field is the name of a monster.
i = fields(1).IndexOf("{")
'-> Field 2 format for monster here
sSavedata.Append(String.Format("Monster:'{0}'", fields(1).Substring(0, i - 1)))
End If
Catch ex As ArgumentOutOfRangeException
Console.WriteLine(String.Format("Illegal field 2: '{0}' in line '{1}'.", fields(1), sLine))
Exit Sub
End Try
'---------------------
'Parse the third field [@player], [@player:companion {id}] or [monster {id}:id]
Try
If fields(2).StartsWith("@") Then
If fields(2).Contains(":") Then
'The third field is the name of a companion.
i = fields(2).IndexOf(":")
j = fields(2).IndexOf("{")
'-> Field 3 format for companion here
sSavedata.Append(String.Format("|Companion:'{0}'", fields(2).Substring(i + 1, j - i - 2)))
Else
'The third field is the name of a player.
'-> Field 3 format for player here
sSavedata.Append(String.Format("|Player:'{0}'", fields(2).Substring(1, fields(2).Length - 1)))
End If
Else
'The third field is the name of a monster.
i = fields(2).IndexOf("{")
'-> Field 3 format for monster here
sSavedata.Append(String.Format("|Monster:'{0}'", fields(2).Substring(0, i - 1)))
End If
Catch ex As ArgumentOutOfRangeException
Console.WriteLine(String.Format("Illegal field 3: '{0}' in line '{1}'.", fields(2), sLine))
Exit Sub
End Try
'---------------------
'Parse the fourth field [Effect {id}] or []
Try
If fields(3) <> "" Then
'The fourth field is the name of an effect.
i = fields(3).IndexOf("{")
'-> Field 4 format for effect here
sSavedata.Append(String.Format("|Effect:'{0}'", fields(3).Substring(0, i - 1)))
End If
Catch ex As ArgumentOutOfRangeException
Console.WriteLine(String.Format("Illegal field 4: '{0}' in line '{1}'.", fields(3), sLine))
Exit Sub
End Try
'---------------------
'Parse the fifth field [Event {id}: Ability {id}]
Try
'The fifth field is the name of an event followed by an ability.
i = fields(4).IndexOf("{")
'-> Field 5 format for event here
sSavedata.Append(String.Format("|Event:'{0}',", fields(4).Substring(0, i - 1)))
i = fields(4).IndexOf(":")
j = fields(4).LastIndexOf("{")
'-> Field 5 format for ability here
sSavedata.Append(String.Format("Ability:'{0}'", fields(4).Substring(i + 2, j - i - 3)))
Catch ex As ArgumentOutOfRangeException
Console.WriteLine(String.Format("Illegal field 5: '{0}' in line '{1}'.", fields(4), sLine))
Exit Sub
End Try
'---------------------
'Parse the optional field in ()s (), (Amount) or (Amount Descriptor {id})
Try
If f_opt_1 <> "" Then
Dim Amount As Integer
i = f_opt_1.IndexOf(" ")
If i > 0 Then
'Optional field 1 contains (Amount Descriptor {id})
Amount = Integer.Parse(f_opt_1.Substring(0, i))
j = f_opt_1.LastIndexOf("{")
'-> Field () format for (amount+descriptor) here
sSavedata.Append(String.Format("|({0},", Amount.ToString))
sSavedata.Append(String.Format("'{0}')", f_opt_1.Substring(i + 1, j - i - 2)))
Else
'Optional field 1 contains (Amount)
Amount = Integer.Parse(f_opt_1)
'-> Field () format for (amount) here
sSavedata.Append(String.Format("|({0})", Amount.ToString))
End If
End If
Catch ex As ArgumentOutOfRangeException
Catch ex As FormatException
Console.WriteLine(String.Format("Illegal optional field 1: '{0}' in line '{1}'.", f_opt_1, sLine))
Exit Sub
End Try
'---------------------
'Parse the optional field in <>s (), (Amount) or (Amount Descriptor {id})
Try
If f_opt_2 <> "" Then
Dim Amount As Integer
'Optional field 2 contains <Amount>
Amount = Integer.Parse(f_opt_2)
'-> Field <> format for <amount> here
sSavedata.Append(String.Format("|<{0}>", Amount.ToString))
End If
Catch ex As FormatException
Console.WriteLine(String.Format("Illegal optional field 2: '{0}' in line '{1}'.", f_opt_1, sLine))
Exit Sub
End Try
'The contents of the current line (as formatted by the append methods) is now stored in sSavedata.
'You can use this to save to a file, write in a textbox or whatever you prefer.
'This sub just writes it to the console window.
Console.WriteLine(sSavedata.ToString)
End Sub