4

I have a number of files, with varying sizes. But I want to accomplish the same thing with all of them, load them into a string(,).

Over the last many hours, I've searched for many variations of code similar to this with some small changes it seems, but even then I could only get a single row to load in at best:

    Dim strimport As String() = {}
    Dim strimportsplit As String(,) = {}
    Dim i As Integer = 0

    strimport = File.ReadAllLines("C:\test.txt")

    For i = 0 To strimport.Length - 1
        strimportsplit = strimport(i).Split(New Char() {vbTab}) 'This line doesn't work
    Next

This is an example of my files (only they're significantly larger):

aaa fff 0
bbb ggg 1
ccc hhh 2
ddd iii 3
eee jjj 4

This is basically how i'd want the above to load into my array from external text files:

        Dim strexample As String(,) = {{"aaa", "fff", "0"},
                                {"bbb", "ggg", "1"},
                                {"ccc", "hhh", "2"},
                                {"ddd", "iii", "3"},
                                {"eee", "jjj", "4"}}

I've even tried adding all of my tables as string(,)'s to VB manually. That works... But putting it in manually like that jumps up the filesize to ~30mb and gives me a MASSIVE performance hit. Not very ideal.

My question is, how can I load from a text file into a string(,) similar to my last example above?

Thank you very much in advance.

Acalia
  • 43
  • 4
  • Don't write this code yourself, use the dedicated [TextFieldParser class](https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser(v=vs.110).aspx). And be sure to use a better collection type to store the data, never an array. The List(Of T) class is good at dynamic sizing. – Hans Passant Jul 02 '18 at 12:41

3 Answers3

3

This would be easier if you switched to a Jagged Array rather than a two-dimensional one. The issue (here) with two-dimensional arrays is that you can only access and modify one element at a time, whereas with a jagged array you can access an entire row.

A jagged array is essentially an array of arrays, and can be declared like:

Dim strimportsplit As String()()

You'd have to set its row size to that of strimport.Length to ensure that it can hold the same amount of lines:

Dim strimport As String()
Dim strimportsplit As String()()

'Dim i As Integer = 0 -- No need for this, it's declared by the loop.

strimport = File.ReadAllLines("C:\test.txt")
strimportsplit = New String(strimport.Length - 1)() {}

NOTE: The reason I use strimport.Length - 1 above is because in VB.NET you actually don't specify the length when declaring a new array, but rather the index of the last item. And since indexes start at 0 the last item will have index Length - 1.

Then inside the loop you just use i to refer to the current array (row/line) of items:

strimportsplit(i) = strimport(i).Split(New Char() {vbTab})

Accessing an item can be done like so:

'strimportsplit(row)(column)

MessageBox.Show(strimportsplit(0)(1)) 'Displays "fff".
MessageBox.Show(strimportsplit(3)(2)) 'Displays "3".

You can also access an entire row if you'd like:

Dim ThirdRow As String() = strimportsplit(2)

MessageBox.Show(ThirdRow(0)) 'Displays "ccc".
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
3
strimportsplit = strimport(i).Split(New Char() {vbTab}) 'This line doesn't work

It doesn't work because you change the value of strimportsplit each time. You do not add more "rows" to it like what you probably think is happening.

If you really want to use a 2D array, you would need to know the length for both dimensions or you'd need to make some conversions afterward. You can calculate the lengths and create a 2D array by doing something like this:

Dim lines As String() = File.ReadAllLines(filePath)
Dim height As Integer = lines.Count - 1
' Calculating the max. number of "columns" in case they vary.
Dim width As Integer = lines.Select(Function(l) l.Split(vbTab).Count).Max - 1

Dim my2DArray(height, width) As String

For i = 0 To lines.Count - 1
    Dim columns As String() = lines(i).Split(vbTab)
    For j = 0 To columns.Count - 1
        my2DArray(i, j) = columns(j)
    Next
Next

Note that if the lines don't have the same number of "columns", some items in the array will be equal to null (or Nothing).

However, a much better way is to use a jagged array instead of a 2D array. You can achieve that using Linq by writing something as simple as:

Dim myJaggedArray As String()() = File.ReadAllLines(filePath).
                                       Select(Function(l) l.Split(vbTab)).ToArray

A jagged array is an array of an array (array of a string array in your case) which you can access its values using arr(x)(y) instead of arr(x, y).


Another alternative to deal with this situation is to use any existing library that works with delimited files (comma separated, tab separated, etc.) instead of having to handle this by yourself. I would recommend using GenericParser which you can easily use to load data from delimited files into a DataTable. You can check my answer to another question for more about how to use it.

2

Instead of using a jagged array I'd use a List of String(). Here is your code slightly modified to illustrate.

    Dim strimport() As String

    strimport = IO.File.ReadAllLines("C:\test.txt")

    Dim StrImportSplit As New List(Of String())

    For Each ln As String In strimport 'iterate lines in file
        StrImportSplit.Add(ln.Split(New Char() {ControlChars.Tab}))
    Next

And a check

    'check
    For lidx As Integer = 0 To StrImportSplit.Count - 1 'rows
        Dim l As New System.Text.StringBuilder
        For cidx As Integer = 0 To StrImportSplit(lidx).Length - 1 'columns
            l.Append(StrImportSplit(lidx)(cidx))
            l.Append(" ")
        Next
        Debug.WriteLine(l)
    Next
dbasnett
  • 11,334
  • 2
  • 25
  • 33