Ken H.
asked on
Select Data From String array Using LINQ or Alternatives?
I need to write a conditional statement that pulls data from a log file and places it in table rows. What I need to get are all the lines that are not blank which reside between the following two lines in the log file (but only if the first line exists) and place them in a specific column (PrefIP) in the table.
[SYSTEM\CurrentControlSet\ Services\S WSvc\Param eters\Pref erredFiler IPAddresse s]
[SYSTEM\CurrentControlSet\ Services\S WSvc\Param eters\Prot ocols]
[SYSTEM\CurrentControlSet\
[SYSTEM\CurrentControlSet\
Dim Table1 As DataTable
Table1 = New DataTable("SnapDrive")
Dim Version As DataColumn = New DataColumn("Version")
Version.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(Version)
Dim PrefIP As DataColumn = New DataColumn("Preferred IP")
PrefIP.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(PrefIP)
Dim ServiceAcct As DataColumn = New DataColumn("Service Account")
ServiceAcct.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(ServiceAcct)
Dim sdVersionInfo As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDriveVersionInfo.log")
Dim sdRegistryData As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDrive_RegistryInfo.log")
Dim sdVersion As String = sdVersionInfo(16).Substring(93) 'These two lines are fine as they are located in static positions
Dim sdService As String = sdRegistryData(20).Substring(26)
Dim prefFlrIp = From q In versionInfoData Where q.Contains("Addresses") Select q.Split(" ")(1).Replace("[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]", String.Empty).Trim
Dim Row1 As DataRow
Try
Row1 = Table1.NewRow()
Row1.Item(Version) = sdVersion
Row1.Item(PrefIP) = If(prefFlrIp.Count > 0, prefFlrIp.First, "Not Set")
Row1.Item(ServiceAcct) = sdService
Table1.Rows.Add(Row1)
Catch ex As Exception
End Try
gridSnapDriveProperties.DataSource = Table1
gridSnapDriveProperties.DataBind()
End Sub
where do you declare versionInfoData? Is it the same as sdVersionInfo?
I have assumed they are one and the same. Here is a suggestion (a bit verbose and hopefully gets your result).
Dim ReqCK = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]"
Dim LastOC = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]"
Dim prefFlrIp As New List(Of String)
If versionInfoData.Contains(ReqCK) Then
Dim NewArray As New List(Of String)
For Each x In versionInfoData
If x = ReqCK Then Continue For
If x = LastOC Then Exit For
NewArray.Add(x)
Next
If NewArray.Count > 0 Then
prefFlrIp = (From q In NewArray Where q.Contains("Addresses") Select q.Split(" ")(1)).ToList
End If
End If
PS. You will need to assign a value to prefFlrIP in case ReqCK is not in your file.
Didn't we dix this question in https://www.experts-exchange.com/questions/27422267/Expression-Help.html ?
The text between the lines was extracted. The only thing you had to add is .trim() on the text and then to split it using the enter char to ne able to use it in the linq instruction.
The text between the lines was extracted. The only thing you had to add is .trim() on the text and then to split it using the enter char to ne able to use it in the linq instruction.
ASKER
nepaluz - that code doesn't seem to be returning a value. Would you please review my code below for correctness?
djon - the code from that posts works when the encoding is UTF ... the log files are not UTF .... i don't actually know what they are, but I'm hoping to find a way to do this short of opening and saving the file as a new file with utf8 encoding and then reading from that file. I could not get that code to give me a value with the logs original formatting either.
djon - the code from that posts works when the encoding is UTF ... the log files are not UTF .... i don't actually know what they are, but I'm hoping to find a way to do this short of opening and saving the file as a new file with utf8 encoding and then reading from that file. I could not get that code to give me a value with the logs original formatting either.
Dim Table1 As DataTable
Table1 = New DataTable("SnapDrive")
Dim Version As DataColumn = New DataColumn("Version")
Version.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(Version)
Dim PrefIP As DataColumn = New DataColumn("Preferred IP")
PrefIP.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(PrefIP)
Dim ServiceAcct As DataColumn = New DataColumn("Service Account")
ServiceAcct.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(ServiceAcct)
Dim sdVersionInfo As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDriveVersionInfo.log")
Dim sdRegistryData As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDrive_RegistryInfo.log")
Dim ReqCK = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]"
Dim LastOC = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]"
Dim prefFlrIp As New List(Of String)
If sdRegistryData.Contains(ReqCK) Then
Dim NewArray As New List(Of String)
For Each x In sdRegistryData
If x = ReqCK Then Continue For
If x = LastOC Then Exit For
NewArray.Add(x)
Next
If NewArray.Count > 0 Then
prefFlrIp = (From q In NewArray Where q.Contains("Addresses") Select q.Split(" ")(1)).ToList
End If
End If
Dim sdVersion As String = sdVersionInfo(16).Substring(93)
Dim sdService As String = sdRegistryData(20).Substring(26)
Dim Row1 As DataRow
Try
Row1 = Table1.NewRow()
Row1.Item(Version) = sdVersion
Row1.Item(PrefIP) = If(prefFlrIp.Count > 0, prefFlrIp.FirstOrDefault, "Not Set")
Row1.Item(ServiceAcct) = sdService
Table1.Rows.Add(Row1)
Catch ex As Exception
End Try
Dim lineString As String = ""
For Each line As String In sdRegistryData
lineString &= line.ToString
lineString &= vbCrLf
txtOut.Text = lineString
Next
gridSnapDriveProperties.DataSource = Table1
gridSnapDriveProperties.DataBind()
End Sub
As this post, you can use powershell to automate encoding changing without knowing the incoming one.
http://superuser.com/questions/27060/batch-convert-files-for-encoding-or-line-ending/113682#113682
http://superuser.com/questions/27060/batch-convert-files-for-encoding-or-line-ending/113682#113682
Your code looks OK. First port of call is make sure that the file contains all the data then place a line break in the code to find out what is in NewArray.
ASKER
Nothing is in NewArray. It seems like the program thinks the string for ReqCK does not exist in the file, but it most certainly does.
I have another piece of code that reads the file into a textbox and both strings are present. Here is the output:
djon - I will take a look at that tonight. Thanks!
I have another piece of code that reads the file into a textbox and both strings are present. Here is the output:
djon - I will take a look at that tonight. Thanks!
[SYSTEM\CurrentControlSet\Services\SWSvc]
Type 0x00000010 (16)
Start 0x00000002 (2)
ErrorControl 0x00000001 (1)
ImagePath "C:\Program Files\NetApp\SnapDrive\SWSvc.exe"
DisplayName SnapDrive
DependOnService0000001 (1) RPCSS
ObjectName NEWIMAGENT\snapx
Description Manages and Monitors NetApp's SnapDrive
[SYSTEM\CurrentControlSet\Services\SWSvc\Licenses]
LPSM
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters]
WebServiceTCPPortNo 808
SupportedIBMProductIDs Nseries
SupportedSCSIVendors NETAPP;IBM
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\DFMConfigParams]
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\DFMConfigParams\ServerConfig]
Port 0x00000000 (0)
ServerName
AdminUserNamex00000000
Protocol 0x00000000 (0)
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\HyperVConfig]
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\HyperVConfig\ParentConfig]
ParentHostName
TcpPort 0x00000328 (808)
Enable_Passthrough0328 (808) 0x00000000 (0)
IP
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]
FAS250-NI1 10.10.1.201
FAS250-NI2 10.10.1.203
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols\#!Default#!SSProtocol]
Position 0x00000000 (0)
Type 0x00000001 (1)
UserName
Port 0x00000000 (0)
[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\VMwareEsx]
tracelevel 0x00000003 (3)
DbgLogFiles 0x00000064 (100)
DbgLogSize 0x01400103 (20971779)
OK, I have run the code and see what you are saying. Here is one that will populate the NewArray. However, the onlyoccurance of Addresses is in the required start string thus you still have nothing! Here goes, first declare sdRegistryData as:
Let me know how this works.
Dim sdRegistryData = (From j In File.ReadAllLines(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "SnapDrive_RegistryInfo.log")) Where Not String.IsNullOrEmpty(j.Trim) Select j.Trim).ToList
I have added a Boolean check to start populating the NewArray to the routine, so you have:Dim ReqCK = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]"
Dim LastOC = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]"
Dim prefFlrIp As New List(Of String)
If sdRegistryData.Contains(ReqCK) Then
Dim NewArray As New List(Of String), StartLog As Boolean = False
For Each x In sdRegistryData
If StartLog Then NewArray.Add(x)
If x = ReqCK Then StartLog = True
If x = LastOC Then Exit For
Next
If NewArray.Count > 0 Then
prefFlrIp = (From q In NewArray Where q.Contains("Addresses") Select q.Split(" ")(1)).ToList
End If
End If
Should be self explanatory, but what the code does is it will only start populating NewArray ONLY when it finds the required string and will exit the loop as soon as the end string is found. Additionally, I have introduced a check in populating sdRegistryData by removing ALL blank lines and triming all the strings so as to be able to find a match for the required strings.Let me know how this works.
Hmmm, I left the path in the declaration of sdRegistryData as mine, you will have to change it back to:
Dim sdRegistryData = (From j In File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDrive_RegistryInfo.log") Where Not String.IsNullOrEmpty(j.Trim) Select j.Trim).ToList
There is still a problem with this line :
prefFlrIp = (From q In NewArray Where q.Contains("Addresses") Select q.Split(" ")(1)).ToList
The NewArray variable contains these lines :
FAS250-NI1 10.10.1.201
FAS250-NI2 10.10.1.203
q in the LINQ represents a line and none of these contains Addresses.
I would presume that this line works better :
prefFlrIp = (From q In NewArray Select q.Split(" ")(1)).ToList
prefFlrIp = (From q In NewArray Where q.Contains("Addresses") Select q.Split(" ")(1)).ToList
The NewArray variable contains these lines :
FAS250-NI1 10.10.1.201
FAS250-NI2 10.10.1.203
q in the LINQ represents a line and none of these contains Addresses.
I would presume that this line works better :
prefFlrIp = (From q In NewArray Select q.Split(" ")(1)).ToList
Like I mentioned in my last suggestion, "the only occurance of Addresses is in the required start string thus you still have nothing!". And yes, if it is the IP addresses that newimagent is looking to get, then the code will pick those up and
prefFlrIp = (From q In NewArray Select q.Split(" ")(1)).ToList
will get BOTH IPs into the list (with 10.10.1.201 being taken as the first)
ASKER
You are right that was incorrect, but prefFlrIp = (From q In NewArray Select q.Split(" ")(1)).ToList does not return any value either.
Ideally though, I would like to get everthing on the lines between the two registry strings, so I would like to get both lines in full returned as below:
FAS250-NI1 10.10.1.201
FAS250-NI2 10.10.1.203
Ideally though, I would like to get everthing on the lines between the two registry strings, so I would like to get both lines in full returned as below:
FAS250-NI1 10.10.1.201
FAS250-NI2 10.10.1.203
Then NewArray should already contained these lines.
If not, I presume it is still an encoding problem.
If not, I presume it is still an encoding problem.
OK, I had to re-jig the code, this one does work (and no, its NOT an encoding issue)
prefFlrIp = (From q In NewArray Select q.Split(" ").Last).ToList
Can you also change the loop toFor Each x In sdRegistryData
If x = LastOC Then Exit For
If StartLog Then NewArray.Add(x)
If x = ReqCK Then StartLog = True
Next
To get the lines in FULL, do a plain:
prefFlrIp = (From q In NewArray Select q).ToList
or even better, declare NewArray outside the If statement and it will contain both lines.
ASKER
This still does not return a value. I've set breakpoints and there is no value in prefFlrIp.
Dim ReqCK = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]"
Dim LastOC = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]"
Dim prefFlrIp As New List(Of String)
If sdRegistryData.Contains(ReqCK) Then
Dim NewArray As New List(Of String), StartLog As Boolean = False
For Each x In sdRegistryData
If x = LastOC Then Exit For
If StartLog Then NewArray.Add(x)
If x = ReqCK Then StartLog = True
Next
If NewArray.Count > 0 Then
prefFlrIp = (From q In NewArray Select q).ToList
End If
End If
Dim sdVersion As String = sdVersionInfo(16).Substring(93)
Dim sdService As String = sdRegistryData(20).Substring(26)
Dim Row1 As DataRow
Try
Row1 = Table1.NewRow()
Row1.Item(Version) = sdVersion
Row1.Item(PrefIP) = If(prefFlrIp.Count > 0, prefFlrIp.First, "Not Set")
Row1.Item(ServiceAcct) = sdService
Table1.Rows.Add(Row1)
Catch ex As Exception
ASKER
I must be missing something. Its as though that code is being skipped over.
ASKER
I've attached my full code for this sub .... I have no idea why it's skipping the for loop, or why i'm not retrieving the data. Can you look at this and see if I'm somehow missing something?
Public Sub SnapDrive()
If Directory.Exists(txtPath.Text & "\SnapDriveInfo\") Then
Dim Table1 As DataTable
Table1 = New DataTable("SnapDrive")
Dim Version As DataColumn = New DataColumn("Version")
Version.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(Version)
Dim PrefIP As DataColumn = New DataColumn("Preferred IP")
PrefIP.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(PrefIP)
Dim ServiceAcct As DataColumn = New DataColumn("Service Account")
ServiceAcct.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(ServiceAcct)
Dim TBD1 As DataColumn = New DataColumn("TBD1")
TBD1.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(TBD1)
Dim TBD2 As DataColumn = New DataColumn("TBD2")
TBD2.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(TBD2)
Dim TBD3 As DataColumn = New DataColumn("TBD3")
TBD3.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(TBD3)
Dim TBD4 As DataColumn = New DataColumn("TBD4")
TBD4.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(TBD4)
Dim TBD5 As DataColumn = New DataColumn("TBD5")
TBD5.DataType = System.Type.GetType("System.String")
Table1.Columns.Add(TBD5)
Dim sdVersionInfo As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDriveVersionInfo.log")
Dim sdRegistryData As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDrive_RegistryInfo.log")
Dim ReqCK = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\PreferredFilerIPAddresses]"
Dim LastOC = "[SYSTEM\CurrentControlSet\Services\SWSvc\Parameters\Protocols]"
Dim prefFlrIp As New List(Of String)
If sdRegistryData.Contains(ReqCK) Then
Dim NewArray As New List(Of String), StartLog As Boolean = False
For Each x In sdRegistryData
If x = LastOC Then Exit For
If StartLog Then NewArray.Add(x)
If x = ReqCK Then StartLog = True
Next
If NewArray.Count > 0 Then
prefFlrIp = (From q In NewArray Select q).ToList
End If
End If
Dim sdVersion As String = sdVersionInfo(16).Substring(93)
Dim sdService As String = sdRegistryData(20).Substring(26)
Dim Row1 As DataRow
Try
Row1 = Table1.NewRow()
Row1.Item(Version) = sdVersion
Row1.Item(PrefIP) = If(prefFlrIp.Count > 0, prefFlrIp.First, "Not Set")
Row1.Item(ServiceAcct) = sdService
Table1.Rows.Add(Row1)
Catch ex As Exception
End Try
Dim lineString As String = ""
For Each line As String In sdRegistryData
lineString &= line.ToString
lineString &= vbCrLf
txtOut.Text = lineString
Next
gridSnapDriveProperties.DataSource = Table1
gridSnapDriveProperties.DataBind()
Else
End If
End Sub
nepaluz : From the past question, I had an encoding problem using the poster's file.
Could you test it using :
http://filedb.experts-exchange.com/incoming/2011/10_w44/518002/SnapDrive-RegistryInfo.log
Could you test it using :
http://filedb.experts-exchange.com/incoming/2011/10_w44/518002/SnapDrive-RegistryInfo.log
ASKER
So a couple of things. To put it to the right path I had to modify this line:
Dim sdRegistryData = (From j In File.ReadAllLines(txtPath. Text & "\SnapDriveInfo\SnapDrive_ RegistryIn fo.log") Where Not String.IsNullOrEmpty(j.Tri m) Select j.Trim).ToList
This line does collect data, and it looks like the statement removes all empty strings from the array, but when I step through this it only removes the first line in the file so the area between the two registry keys looks like:
"[SYSTEM\CurrentControlSet \Services\ SWSvc\Para meters\Pre ferredFile rIPAddress es]"
" "
" "
" "
FAS250-NI1 10.10.1.201
" "
FAS250-NI2 10.10.1.203
" "
" "
" "
"[SYSTEM\CurrentControlSet \Services\ SWSvc\Para meters\Pro tocols]"
Because of the spacing I cannot tell if the double quotes are "" or " "
Dim sdRegistryData = (From j In File.ReadAllLines(txtPath.
This line does collect data, and it looks like the statement removes all empty strings from the array, but when I step through this it only removes the first line in the file so the area between the two registry keys looks like:
"[SYSTEM\CurrentControlSet
" "
" "
" "
FAS250-NI1 10.10.1.201
" "
FAS250-NI2 10.10.1.203
" "
" "
" "
"[SYSTEM\CurrentControlSet
Because of the spacing I cannot tell if the double quotes are "" or " "
ASKER
Arrrgh..... again it has to do with encoding. If i save the file as unicode it pulls the data. Is there a way i can on the fly convert the data to unicode as it's pulled into the array?
Hmm, turns out it is an encoding issue. What program creates your logs?
I'll repeat one of my previous comment.
-------------------------- ----
As this post, you can use powershell to automate encoding changing without knowing the incoming one.
http://superuser.com/questions/27060/batch-convert-files-for-encoding-or-line-ending/113682#113682
--------------------------
As this post, you can use powershell to automate encoding changing without knowing the incoming one.
http://superuser.com/questions/27060/batch-convert-files-for-encoding-or-line-ending/113682#113682
what encoding is the file?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Strange, but if you look at line 2
Dim Converter = Encoding.Convert(Encoding.Unicode, Encoding.Unicode, IO.File.ReadAllBytes(filePath))
all I do is convert the file from Unicode to Unicode .... does not make sense but Ihave seen stranger things happen with code!
ASKER
Its a program written by our engineering department. It's written in .NET but i'm not sure what any of the details are and I'm certain they won't change it so I'll have to work around it.
Yes as I said before djon thats a method of last resort at this point. I'm trying to wrap my head around all this filesystem io stuff mixed with LINQ. There is a point in the near future where I will need to run a server side executable against files to decode them, but I don't want to start down that road yet if i can avoid it.
Yes as I said before djon thats a method of last resort at this point. I'm trying to wrap my head around all this filesystem io stuff mixed with LINQ. There is a point in the near future where I will need to run a server side executable against files to decode them, but I don't want to start down that road yet if i can avoid it.
Maybe you could try this out too.. Didn't test it (that time), but as it seems that Unicode reading is already supported.
To nepaluz : I presume that initial encoding is not Unicode, but probably another charset compatible with it. As most of the charset are compatible with the old ASCII-us charset.
Dim sdRegistryData As String() = IO.File.ReadAllLines(txtPath.Text & "\SnapDriveInfo\SnapDrive_RegistryInfo.log", System.Text.Encoding.Unicode)
To nepaluz : I presume that initial encoding is not Unicode, but probably another charset compatible with it. As most of the charset are compatible with the old ASCII-us charset.
actually, it works so well that if you change line 16 above to
prefFlrIp = (From q In NewArray Select q.Split(vbTab).Last).ToList
you get just the IP address (turns out it is delimited by a tab)
ASKER
Thank you! This is exactly what I needed. How do you learn this stuff so well? I have been through my vb2010 and LINQ books and googled my butt off. Any suggestions as to what resources I should be using to learn this would be much appreciated.
I had to modify this to get what i was looking for but not much.
Again thank you both for so much help with this!
I had to modify this to get what i was looking for but not much.
prefFlrIp = (From q In NewArray Select q).ToList
Again thank you both for so much help with this!
How do we learn this stuff I hear you ask? Well, as you can see,we got this at the first attempt, thats why I am a Guru or is that Wizard! As for resources, EE is a very good resource, I have found that I learn more helping answer questions / finding solutions to questions from other people. At the moment, I am working on several projects in VB that involve parsing lots of data (and I get to use LINQ a lot!) thus a natural selection to answer any queries that come in on that topic area.
The code you have resorted to above is actually redundant, remove the declaration of NewArray and replace it with prefFlrIp inside the loop. You end up with the same result!
The code you have resorted to above is actually redundant, remove the declaration of NewArray and replace it with prefFlrIp inside the loop. You end up with the same result!