How can i serialize and deserialize a dictionary in vb.net? - vb.net

I am working with an application that needs to store large dictionaries of 40 000+ keys and values in a file, and then load them back into dictionaries on startup... Right now i am using a simple character separation with split and a for each loop on startup like:
key1=value1|key2=value2|key3=value3 etc...
however, i am looking for a more efficient way of serializing and deserializing the dictionaries... also with size of the serialized data in mind as there is quite a lot of entries.

You could make use of BinaryFormatter
On my mid end machine: save took: 390ms load took: 359ms data saved was about 1500kb
'save
Dim dict = New Dictionary(Of String, String)
For i = 1 To 40000
dict.Add("key" & i, "value" & i)
Next
Dim fs As IO.FileStream = New IO.FileStream("d:\test\test.bin", IO.FileMode.OpenOrCreate)
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(fs, dict)
fs.Close()
'load
Dim fsRead As New IO.FileStream("d:\test\test.bin", IO.FileMode.Open)
Dim objTest As Dictionary(Of String, String) = bf.Deserialize(fsRead)
fsRead.Close()

This works well when using stacked dictionaries:
Dim DataDict as New Dictionary(Of String,Dictionary(Of String,String))
Here is a working example of embedded dictionaries being serialized for writing and reading:
Imports System.IO
Module Modules
Public Sub TestDict()
Dim DictsToSave As New Dictionary(Of String, Dictionary(Of String, String))
For DictsToHave = 1 To 10
Dim SingelDictData As New Dictionary(Of String, String)
For Values = 1 To 10000
SingelDictData.Add("Key " & Values.ToString(), "Value " & Values.ToString())
Next
DictsToSave.Add("Key " & DictsToHave.ToString(), SingelDictData)
Next
Dim WriteResult = WriteMultiSerializedDict("D:\TestDict.Bin", DictsToSave)
Dim ReadResult As Dictionary(Of String, Dictionary(Of String, String)) = ReadMultiSerializedDict("D:\TestDict.Bin")
End Sub
Public Function WriteMultiSerializedDict(ByVal FullPath As String, ByVal DataDict As Dictionary(Of String, Dictionary(Of String, String))) As Boolean
Try
Dim FileStream As IO.FileStream = New FileStream(FullPath, IO.FileMode.OpenOrCreate)
Dim BinFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
BinFormatter.Serialize(FileStream, DataDict)
FileStream.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Function ReadMultiSerializedDict(ByVal FullPath As String) As Dictionary(Of String, Dictionary(Of String, String))
Try
Dim DataDict As New Dictionary(Of String, Dictionary(Of String, String))
Dim FileStream As IO.FileStream = New FileStream(FullPath, IO.FileMode.Open)
Dim BinFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
DataDict = BinFormatter.Deserialize(FileStream)
FileStream.Close()
Return DataDict
Catch ex As Exception
Return Nothing
End Try
End Function
On my mid end dev machine, this took about 260 ms for the write and 545 for the read, with a file that measured at 3.70 mb. Important note: If you change any of the dict's keys (not values), the load bombs! So, as a matter of programming, always assemble your dicts in the same order. I've used this approach before, using 5 100 key/value pairs in the sub dictionary's, without issue or problem.

Related

How many count lines duplicates in text files

please how can I get count of duplicate lines?
Source data: line e.g. user_id;name;surname;3400;44711;30.05.2022 7:00:00;30.05.2022 15:30:00;0;480;0;1;682;10000120;9
Private Sub remove_duplicite(sender As Object, e As EventArgs)
Dim sFiles() As String
sFiles = Directory.GetFiles(filesPath1, remove_dupl)
Dim path As String = String.Join("", sFiles)
'MessageBox.Show(path)
Dim lines As New HashSet(Of String)()
'Read to file
Using sr As StreamReader = New StreamReader(path)
Do While sr.Peek() >= 0
lines.Add(sr.ReadLine())
Loop
End Using
'Write to file
Using sw As StreamWriter = New StreamWriter(path)
For Each line As String In lines
sw.WriteLine(line)
Next
End Using
Close()
End Sub
I try some answers but no success.But I think that will be easy.
Thank you
Dim sList As New List(of String)
sList.Add("1")
sList.Add("2")
sList.Add("2")
sList.Add("3")
Dim sListDistinct As List(Of String) = sList.Distinct().ToList()
Dim iCount as Integer = sList.Count - sListDistinct.Count
But depending on the size of your file, this isn't the best performance way.
Maybe check in your HashSet with .Contains and count if entry already exists

from list to string with formatting

i have a function getSelectedNumbers that take as input 3 list of number. after a manipulation i need to obtain a string in the format
"[1_3,10,20,30,500],[1_1,2],[]"
if the list is empty i need to have in the string the "[]" char
i wrote the below function but i need to manage the empty case.
Based on comment of Anu6is :
i was able to rewrite my code as below
'''vb
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel1.Find(".//div[#class='selected']")
Dim selectedNumbers2 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel2.Find(".//div[#class='selected']")
Dim selectedNumbers3 As IList(Of Element) = repo.CanvasTerminalProduct.BoardDetails.Panel.pnlSuper3Panel3.Find(".//div[#class='selected']")
Dim list1 As New List(Of String)
Dim list2 As New List(Of String)
Dim list3 As New List(Of String)
For i As Integer = 0 To selectedNumbers1.Count -1
list1.Add(selectedNumbers1(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers2.Count -1
list2.Add(selectedNumbers2(i).GetAttributeValue("innerText").ToString)
Next i
For i As Integer = 0 To selectedNumbers3.Count -1
list3.Add(selectedNumbers3(i).GetAttributeValue("innerText").ToString)
Next i
'Create List of List
Dim selectedNumbersList As New List(Of List(Of String)) From {list1, list2, list3}
Dim builder As New StringBuilder 'Used to build the output
'Convert all the list in the correct string format using the join
For Each listX As List(Of String) In selectedNumbersList
builder.Append("[1_").Append(String.Join(",", listX)).Append("],") 'String.Join() give you a comma delmited string
Next
'Remove the last, and the [1_] that are not needed
Dim strSelectedNunmber As String = builder.ToString().TrimEnd(","c)
strSelectedNunmber = strSelectedNunmber.ToString().Replace("[1_]","[]")
Return str
End Function
'''
now my question is there is a better way to generate the list1 list2 list3 ?
This is assuming that Element is simply an Integer
Public Function getSelectedNumbers() As String
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3} 'Unordered list
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500} 'Ordered list
Dim selectedNumbers3 As New List(Of Integer) 'empty list
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
Dim builder As New StringBuilder 'Used to build the output
For Each list In selectedNumbersList
list.Sort() 'Sort your list
builder.Append("[").Append(String.Join(",", list)).Append("],") 'String.Join() give you a comma delmited string
Next
Return builder.ToString.TrimEnd(","c) 'Remove the final comma (,) and return the formatted string
End Function
[3,10,20,30,500],[1,2,500],[]
Does this work for you?
Dim selectedNumbers1 As New List(Of Integer) From {20, 30, 500, 10, 3}
Dim selectedNumbers2 As New List(Of Integer) From {1, 2, 500}
Dim selectedNumbers3 As New List(Of Integer)
'either make 3 loops or 1, but you have to make a list of lists first
Dim selectedNumbersList As New List(Of List(Of Integer)) From {selectedNumbers1, selectedNumbers2, selectedNumbers3}
For Each listX In selectedNumbersList
listX.Sort()
Dim ReturnString As String = "["
If listX.Count > 0 Then
For Each itemvalue In listX
ReturnString &= itemvalue & ","
Next
ReturnString = ReturnString.Remove(ReturnString.Length - 1)
End If
ReturnString &= "]"
Debug.Print(ReturnString)
Next
'[3,10,20,30,500]
'[1,2,500]
'[]

repetition time of adding data list

resembles a python code like this
while listCompanion :
in vb net I tried to use the code For Each kvp In listCompanion but failed
Dim listCompanion As New Dictionary(Of String, String()) From {"dessy", New String() {"age: 21", "gender: girl"}}
Dim kvp As KeyValuePair(Of String, String())
ListBox1.Items.Clear()
For Each kvp In listCompanion
Dim member As String = String.Format("{0} = {1} - {2}", kvp.Key, kvp.Value(0), kvp.Value(1))
ListBox1.Items.Add(member) 'I want every additions will enter the listbox
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add({"jony", New String() {"age: 25", "gender: boy"}})
End If
next
when you want to add a data list, the For Each actually not working again
I want after listCompanion.Add({"jony", New String() {"age: 25", "gender: boy"}})
can repeat For Each kvp In listCompanion
There are three problems that don't allow your code to compile.
First you miss a couple of curly braces in the initialization of the listCompanion,
Dim listCompanion = New Dictionary(Of String, String()) From
{ {"dessy", New String() {"age: 21", "gender: girl"}}}
Second there are too many curly braces when you add a new element to the listCompanion.
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add("jony", New String() {"age: 25", "gender: boy"})
End If
Finally you can't change the listCompanion while you loop over it, so if you want to add that KeyValuePair also to the Listbox items then you should add it before starting the loop
Dim kvp As KeyValuePair(Of String, String())
ListBox1.Items.Clear()
If listCompanion.Count < 2 Then 'Error here
listCompanion.Add("jony", New String() {"age: 25", "gender: boy"})
End If
For Each kvp In listCompanion
Dim member As String = String.Format("{0} = {1} - {2}", kvp.Key, kvp.Value(0), kvp.Value(1))
ListBox1.Items.Add(member) 'I want every additions will enter the listbox
Next

Tab Delimited File vb.net to Access 97

I have to import products from a denormalized table to Access 97 file. This scheme can't change, so I can't use SQL. I use the following routine to import the products. There are over 7000 products in the file and the function takes a long time. Is there any way to speed it up?
Public Sub ImportToOrders()
Try
'Dim actualFileName As String = IO.Path.GetFileName(filename)
'Dim streamReader As New IO.StreamReader(filename)
'Dim streamWriter As New IO.StreamWriter(filename & ".tsv")
'streamWriter.WriteLine()
'streamWriter.Close()
'streamWriter.Dispose()
Dim strFile As String = "C:\windows\figure.ini"
Dim strRet As String
Dim inifile As New IniFileManager
strRet = inifile.ReadINI(strFile, "DATABASE SECTION", "FILENAME", "")
Dim strPriCatFile As String = ""
strPriCatFile = "C:\three_software\incoming\skechers\Pricat.edi.tsv"
Dim fields As String()
Dim counter As Integer = 0
Dim delimiter As String = ControlChars.Tab
Using parser As New TextFieldParser(strPriCatFile)
parser.SetDelimiters(delimiter)
While Not parser.EndOfData
counter = counter + 1
' Read in the fields for the current line
fields = parser.ReadFields()
If counter = 1 Then
'this will be the header row we want to ignore this
Else
' the fiels we will go ahead and parse
WriteData(fields(1), fields(3), fields(4), fields(6), fields(5), fields(11), fields(8), fields(9), fields(11), fields(10), fields(12), fields(13), fields(14), "t")
End If
Debug.Write("Records Importing" + counter.ToString())
End While
End Using
Catch ex As Exception
MsgBox(ex.ToString())
End Try
Write Data function
Public Function WriteData(sUPCode As String, sColourDescription As String, sSize As String, sColorCode As String, sDivsionDescription As String, sDescription As String, sDepartment As String, sSubDeparment As String, sProductShortDescription As String, sGender As String, sProductDescription As String, sCostPrice As String, sRetailPrice As String, sDiscountedPrice As String)
Try
Dim pricateTableAdapter As New SkechersPricatTableAdapter()
pricateTableAdapter.Insert(1, sUPCode, "stylenumber", sColourDescription, sSize, sColorCode, sDivsionDescription, sDepartment, sSubDeparment, sProductShortDescription, sGender, sProductDescription, sCostPrice, sRetailPrice, sDiscountedPrice)
Catch ex As Exception
MsgBox(ex.ToString())
End Try
End Function

Building a multidimensional array in vb.net

I'm trying to build up a multidimensional array which will hold two bits of info for each record in a database e.g. id, description.
This is what I am currently doing.
Dim mArray(,) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
The problem I have here is that it doesn't like the i in mArray(i,0). Anyone have any ideas about this? This is the error that is given Object reference not set to an instance of an object.
Thanks for any and all help.
Nalum
Why not rather make use of List Class and Dictionary Class
You can rather then create a List of Dictionaries, with the key and value both strings. The key can then represent your key (id and description in your example, and the value can be what ever was stored).
Something like
Dim values As New List(Of Dictionary(Of String, String))()
and then in the while loop something like
values.Add(New Dictionary(Of String, String)() From { _
{"id", cmdReader.Item("id")} _
})
values.Add(New Dictionary(Of String, String)() From { _
{"description", cmdReader.Item("description")} _
})
You could then use foreach
For Each value As Dictionary(Of String, String) In values
Dim id As String = value("id")
Dim description As String = value("description")
Next
Or a for
For i As Integer = 0 To values.Count - 1
Dim value As Dictionary(Of String, String) = values(i)
Dim id As String = value("id")
Dim description As String = value("description")
Next
Try this
Dim mArray(1,1) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
ReDim Preserve mArray(i,1)
End While
The problem is that you are not initializing the array.
This should work, until i will not reach the limits set in the initialization.
Dim mArray(100,100) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
But if the array limits are not known I suggest to follow astander's suggestion.
This works for me:
Dim values As New List(Of Dictionary(Of String, String))()
values.Add(New Dictionary(Of String, String)() From {{"quarter", q1.ToString}, {"year", y1.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q2.ToString}, {"year", y2.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q3.ToString}, {"year", y3.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q4.ToString}, {"year", y4.ToString}})
For Each value As Dictionary(Of String, String) In values
Dim quarter As String = value("quarter")
Dim year As String = value("year")
Debug.Print(quarter & "/" & year)
Next
Correct it by
Dim mArray(,) As String = ""