Ethan
Ethan

Reputation: 37

Populating a DataTable with a Text File

I am making a password manager for myself and am storing all of the data locally within a text file. I am not worried about security at the moment, simply trying to get it to work.

I can read from the text file fine and have each of my entries split with commas, but I can't figure out how to properly format my for loop to get them in the correct order

Here is how the data looks within pass.txt

Gmail,07/31/2020,password,
Facebook,07/31/2020,password,

I have 3 columns, Service,Last Changed, and Password. Currently, my data fills the first column from the top down until the end of my array splitData and then does the same for the remaining 2 columns

My thought is that I need a nested for loop within my existing one, but am stuck on the logic

Public Class Form2
    Private thedatatable As New DataTable
    Private workDirectory = My.Computer.FileSystem.CurrentDirectory
    Private rw As System.IO.StreamReader
    Private fileContents As String
    Private splitData As String()

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        With thedatatable
            .Columns.Add("Service", System.Type.GetType("System.String"))
            .Columns.Add("Last Changed", System.Type.GetType("System.String"))
            .Columns.Add("Password", System.Type.GetType("System.String"))
        End With

        workDirectory += "\pass.txt"
        rw = My.Computer.FileSystem.OpenTextFileReader(workDirectory)
        fileContents = rw.ReadToEnd()
        'reads pass.txt to string array while splitting at commas
        splitData = fileContents.Split(New Char() {","c}) 

        Dim word As String
        For Each word In splitData      REM iterates for each split word
            Dim newrow As DataRow = thedatatable.NewRow
            newrow("Service") = word
            newrow("Last Changed") = word
            newrow("Password") = word
            thedatatable.Rows.Add(newrow)
        Next
        DataGridView1.DataSource = thedatatable
    End Sub
End Class

Upvotes: 1

Views: 2316

Answers (2)

Jimi
Jimi

Reputation: 32288

Since you may need it, here's an example you can follow to store your data as JSON.

► If you're not using .Net Core 3.0+ (which provides its own System.Text.Json - when you'll move to .Net Core, switch to this without a second thought), I suggest to install Json.Net:

  • Open up Visual Studio's NuGet Package Manager (Tool -> NuGet Package Manager -> Manage NuGet Packages for Solution)
  • search for Newtownsoft.Json. The first entry will be, at this date, Newtownsoft.Json v.12.0.3.
  • Choose to install the Package, build the Solution.

Now, to Serialize a DataTable, you need one command:

Dim json as String = JsonConvert.SerializeObject([Your DataTable])

To deserialize the data, converting the JSON to a DataTable, one more command:

Dim dt = JsonConvert.DeserializeObject(Of DataTable)([JSON String])
  • These are implemented in code in two methods: SaveMyPasswords() and LoadMyPasswords(). You just need to specify the path where the JSON is stored.

The path where the data is stored is an important matter. There are different choices you can make:

  • the User [User]\AppData\Local folder is often used. This location is returned by Application.LocalUserAppDataPath.
  • the [User]\AppData\Roaming section is returned by Application.UserAppDataPath.
  • The \ProgramData folder is a good option, this path is returned by Application.CommonAppDataPath

Note that these paths already contain sub-folders named after your assembly (Product or Company + assembly name + version). In this code, I'm using Application.CommonAppDataPath. Choose whatever you see fit in your scenario.

  • I'd avoid to (try to) store the data in the Executable's path, you may find out that you have no access rights to write data there. Of course, you could prompt the User to provide a path for storage (with a SaveFileDialog or a FolderBrowserDialog). This is another possible choice.

When you first run your app, this path won't exist, but it will be created as soon as you save your data in this location: File.WriteAllText(), for example, creates the full path of the file if it doesn't exist yet.

The btnSaveData.Click handler calls SaveMyPasswords() to serialize and store the data.

Assume your DataTable is built ~as in your OP (but the date is a DateTime object):

Private theDataTable As DataTable

Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim dataPath = Path.Combine(Application.CommonAppDataPath, "myPasswords.json")
    theDataTable = LoadMyPasswords(dataPath)

    If theDataTable Is Nothing Then
        theDataTable = New DataTable("MyPassowrds")
        theDataTable.Columns.AddRange({
            New DataColumn("Service", GetType(String)),
            New DataColumn("Last Changed", GetType(Date)),
            New DataColumn("Password", GetType(String))
        })
    End If
    DataGridView1.DataSource = theDataTable
End Sub

Private Sub btnSaveData_Click(sender As Object, e As EventArgs) Handles btnSaveData.Click
    Dim dataPath = Path.Combine(Application.CommonAppDataPath, "myPasswords.json")
    SaveMyPasswords(dataPath, theDataTable)
End Sub

Private Function LoadMyPasswords(dataPath As String) As DataTable
    If File.Exists(dataPath) Then
        Return JsonConvert.DeserializeObject(Of DataTable)(File.ReadAllText(dataPath))
    End If
    Return Nothing
End Function

Private Sub SaveMyPasswords(dataPath As String, data As DataTable)
    File.WriteAllText(dataPath, JsonConvert.SerializeObject(data))
End Sub

Upvotes: 1

Idle_Mind
Idle_Mind

Reputation: 39152

An quick example of using ReadLines() and String.Split():

Dim FileName As String = System.IO.Path.Combine(workDirectory, "pass.txt")
For Each line As String In System.IO.File.ReadLines(FileName)
    Dim values() As String = line.Split(",".ToCharArray)
    If values.Length >= 3 Then
        Dim newrow As DataRow = thedatatable.NewRow
        newrow("Service") = values(0)
        newrow("Last Changed") = values(1)
        newrow("Password") = values(2)
        thedatatable.Rows.Add(newrow)
    End If
Next

Upvotes: 1

Related Questions