How to fix 'Index was outside of bounds of the array' - arrays

Using visual basic. Trying to load a series of reports onto a listview, listview consists of 3 columns (location, date and severity level) everytime it loads it crashes due to 'index being outside the bounds of the array'.Specifically around DOI = reportdetails(1) in my code. It is loading off of a textfile. I have the data within the textfile so I am unsure of why it is saying I am asking for information that doesnt exist. The program also encypts the textfile.
Dim locate, DOI, SeverityLevel, ReportTitles, EReportTitles, ReportDetails(2) As String
Dim Index As Integer 'Define Variables
Dim FileNum As Integer = FreeFile()
Dim IncidentReport As ListViewItem
lstReports.Items.Clear()
If Dir("ReportTitles.txt") <> "" Then 'If the directory of the file exits then continue
FileOpen(FileNum, "ReportTitles.txt", OpenMode.Input) 'open file
Do Until EOF(FileNum) 'Repeat until the end of the file is reached
EReportTitles = "" 'Clear variables, to safeguard against crashes or errors
ReportTitles = ""
EReportTitles = LineInput(FileNum) 'EReportTitles is equal to the current file line
Dim FileName As String = "ReportTitles.txt" 'Define variables
Dim I, C As Integer
Dim Last As Integer = EReportTitles.Length - 1
Dim ThisChar As Char
For I = 0 To Last 'Begin for loop
ThisChar = EReportTitles.Chars(I) 'Decryption of file
C = Asc(ThisChar) Xor 22
ThisChar = Chr(C)
ReportTitles += ThisChar
Next
If ReportTitles <> "" Then
ReportDetails = Split(ReportTitles, ",") 'Split the lines when a "," is encountered
locate = ReportDetails(0) 'Assosciate to relevant value in array
DOI = ReportDetails(1)
SeverityLevel = ReportDetails(2)
IncidentReport = New ListViewItem
IncidentReport.Text = locate 'Add relevant values to IncidentReport ListViewItem variable
IncidentReport.SubItems.Add(DOI)
IncidentReport.SubItems.Add(SeverityLevel)
lstReports.Items.Add(IncidentReport) 'Transfer IncidentReport to listview
Else
End If
Loop
FileClose(FileNum) 'close file
End If
Expected result is to load all of the report location, dates and severity levels onto the listview.
Also sorry about the formatting of this question, i'm new to stack overflow.

There's no point declaring ReportDetails like this:
ReportDetails(2) As String
because that creates an array that you never use. Here:
ReportDetails = Split(ReportTitles, ",")
you are creating a new array anyway and the length of that array will be determined by the number of delimiters in ReportTitles. If you're being told that 1 is an invalid index for that array then that array must only contain 1 element, which means that ReportTitles didn't contain any delimiters.
This is not something that we should have to explain to you because you can easily see it for yourself by debugging and you should ALWAYS debug BEFORE posting here. Set a breakpoint at the top of the code, step through it line by line and examine the state at each step. You can easily see the contents of ReportTitles and ReportDetails and anything else to see whether they are what you expect them to be.
If the point here is to read a CSV file then you really ought to be using the TextFieldParser class. The documentation for that class includes a code example.

This requires .Net Standard 2.1, and so I'm not sure if VB.Net can use the required SpanAction for the String.Create() method, but if it is supported it should greatly outperform the original.
lstReports.Items.Clear()
'Read and "Decrypt" (and I use that term loosely) the file with only a single heap allocation
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
file = String.Create(fs.Length, fs,
Sub(chars, stream)
For i As Integer = 0 To stream.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
chars(i) = Chr(fs.ReadByte() Xor 22)
Next
End Sub)
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
If you are not able to use that version, this is not quite as good, but still a better approach than the original:
lstReports.Items.Clear()
'Load and "Decrypt" the file
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
Dim builder As New StringBuilder(fs.Length)
For i As Integer = 0 To fs.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
builder.Append(Chr(fs.ReadByte() Xor 22))
Next
file = builder.ToString()
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
In both cases, use Try/Catch rather than Dir() to check whether the location exists. Just try to open the file. Dir() costs an extra disk seek, and there are precious few things in programming slower than disk I/O.

Related

Line breaks lost when exporting datagrid to excel in CSV format WPF

This works fine, assuming there are no line breaks in certain cells.
dgvResults.SelectAllCells()
dgvResults.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader
ApplicationCommands.Copy.Execute(Nothing, dgvResults)
Dim result As [String] = DirectCast(Clipboard.GetData(DataFormats.CommaSeparatedValue), String)
Clipboard.Clear()
dgvResults.UnselectAllCells()
Try
Dim file As New System.IO.StreamWriter("c:\export.csv")
file.WriteLine(result)
file.Close()
Process.Start("c:\export.csv")
Catch ex As Exception
MessageBox.Show(ex.Message, "Error")
End Try
This is how I add line breaks
Dim x As New List(Of String)
For Each item In res.Properties("proxyaddresses")
x.Add(item)
Next
AllSMTPAddresses = String.Join(ControlChars.Lf, x)
When I export this, it doesn't take into consideration there are line breaks, and completely ignores them... so the excel formatting is a little wonky. I've tried: Environment.NewLine, vbCrLf, and now ControlChars.Lf. I think excel doesn't know what to do with the line breaks, so it just does w.e it wants, and creates new rows with them.
Any idea on how I would attack this?
Updated results #Jimmy
This is what it's supposed to look like...
I don't believe this will be possible without modifying those rows prior to the export. I found some example code that may help,
Public Sub writeCSV(grid1 As Object, outputFile As String)
' Create the CSV file to which grid data will be exported.
Dim sw As New StreamWriter(outputFile)
' First we will write the headers.
Dim dt As DataTable = DirectCast(grid1.DataSource, DataSet).Tables(0)
Dim iColCount As Integer = dt.Columns.Count
For i As Integer = 0 To iColCount - 1
sw.Write(dt.Columns(i))
If i < iColCount - 1 Then
sw.Write(",")
End If
Next
sw.Write(sw.NewLine)
' Now write all the rows.
For Each dr As DataRow In dt.Rows
For i As Integer = 0 To iColCount - 1
sw.Write("""") 'lets encapsulate those fields in quotes, quoted csv file!
If Not Convert.IsDBNull(dr(i)) Then
sw.Write(dr(i).ToString())
End If
sw.Write("""")
If i < iColCount - 1 Then
sw.Write(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator)
End If
Next
sw.Write(sw.NewLine)
Next
sw.Close()
End Sub
modified from here

Why Won't My Array Sort? (Visual Basic)

I'm working on a project, for school, that reads text from a .txt file to an array. After doing that, I'm supposed to sort the array, alphabetically, and then list the contents in a listbox. Here is my code:
Imports System.IO
Public Class Form1
'Allow array to be accessed by the entire program
Public books(1) As String
Private Sub btnView_Click(sender As Object, e As EventArgs) Handles btnView.Click
'Declare variables
Dim sr As New StreamReader("C:\Users\Bryson\Desktop\BooksinStock.txt")
Dim book As String
Dim i As Integer = 0
'Establish loop to read contents of the text file into the array and list the array in the listbox
'the sr.Peek = -1 simply means that the reader has reached the end of the file and there is nothing more to be read
Do Until sr.Peek = -1
book = sr.ReadLine()
'ReDim allows the array to grow with the set amount of books in text file
ReDim books(books.Length + 1)
books(i) = book
i += 1
Loop
Array.Sort(books)
lstBoxInventory.Items.Add(books(i))
End Sub
End Class
However, when I run the program, I receive an error on the lstBoxInventory.Items.Add(books(i)) line that says "an unhandled exception of the type 'System.ArgumentNullException' occurred in System.Windows.Forms.Dll
I've tried to lay the code out in various ways to get the sort to work but keep coming up short. Does anyone know how to get rid of this null error?
The problem happening because "i" is larger than the highest index
Do Until sr.Peek = -1
book = sr.ReadLine()
ReDim books(books.Length + 1)
books(i) = book
i += 1 'This is adding 1 to the very end
Loop
Array.Sort(books)
lstBoxInventory.Items.Add(books(i)) 'When the items are being added it is trying to add an extra i that does not exist
edit
Honestly I would change the format to use ReadAllLines and list(of String)
Something like (Im writing code from memory)
Dim bookList as new List(of String)
Dim bookTextFile as String() = File.ReadAllLines("C:\booklist.txt")
for each book as String in bookTextFile
bookList.add(book)
next
bookList.Sort
Edit Again
Just using this
Dim bookList As String() = System.IO.File.ReadAllLines("C:\Users\Bryson\Desktop\BooksinStock.txt")
creates a single dimension array ..
Strings() are single Arrays String(,) are two dimensional Arrays
Honestly your whole homework could be
Dim bookList As String() = System.IO.File.ReadAllLines("C:\Users\Bryson\Desktop\BooksinStock.txt")
Array.Sort(BookList)
boom - done.
Test it using
for each book as String in BookList
Msgbox(book)
next
You could do
Dim bookList As String() = System.IO.File.ReadAllLines("C:\Users\Bryson\Desktop\BooksinStock.txt")
Dim books(bookList.Length - 1) As String 'This is the same as ReDim
For x As Integer = 0 To bookList.Length - 1
books(x) = bookList(x)
Next
Array.Sort(books)
but you would literally be saying bookList = books
But.... if you just want to get your code working, just try this
lstBoxInventory.Items.Add(books(i -1)) 'This takes away the extra i that you added

parallel array for Visual Basic assignment

For this assignment I am being ask to "Read the file into parallel string arrays corresponding to the columns in the file".
The columns in the file are: "P_CODE" "P_DESCRIPT" "P_INDATE" "P_QOH" "P_MIN" "P_PRICE".
My question is "What is a parallel array?" and what does it look like. I took a guess at how I would imagine it might done but I'm not sure I'm on the right track.
========== project Inventory ==========
Selecting the Read button shall cause the contents of the
InventoryData.txt file to be read from your project’s default folder.
The file does contain a column header line.
Read the file into parallel string arrays corresponding to the columns in the file. After reading the file, close it. Display the
contents of the file in the parallel arrays, including column titles,
in the List box formatted using the Format() method. Left and right
align columns according to convention for their type of data. Hint:
Set the Font property of you List Box to a nonproportional space font
such as Courier.
Write the contents of the file in the parallel arrays, including
column titles, to a file named InventoryDataOut.txt created in your
project’s default folder. Delimit the columns with the pipe (|)
symbol. Each inventory item to one line of output to the file.
This is what I have done so far. I just started so this is not functioning code.
Private Sub btnRead_Click(sender As Object, e As EventArgs) Handles btnRead.Click
Dim dirPath As String = "C:\Users\...\Inventory\"
Dim filePath As String = dirPath & "InventoryData.txt"
'Arrays
Dim P_CODE As String()
Dim P_DESCRIPT As String()
Dim P_INDATE As String()
Dim P_QOH As String()
Dim P_MIN As String()
Dim P_PRICE As String()
' Open file for reading
Dim textIn As New StreamReader(
New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
'Read in the lines of text into the String variables in the array;
Dim i As Integer = 0
Do While textIn.Peek <> -1
Dim row As String = textIn.ReadLine
Dim columns As String() = row.Split(CChar(" "))
P_CODE(i) = columns(i)
P_DESCRIPT(i) = columns(i)
P_INDATE(i) = columns(i)
P_QOH(i) = columns(i)
P_MIN(i) = columns(i)
P_PRICE(i) = columns(i)
i = i + 1
Loop
'=====================================
'- After reading the file, close it.
textIn.Close()
I get the following warning and error (for each array) :
Warning 1 Variable 'P_CODE' is used before it has been assigned a
value. A null reference exception could result at
runtime.
Columns as independant arrays ? :/
One line answer : You're doing it right !
However :
there are simplier ways to do this (in terms of usage and readability - not performance)
there are typos in your code.
StackOverflow's main purpose is not to teach basic language reference, but help you overcome a specific problem with the appropriate coding (while keeping in mind an answer can't be an answer if it doesn't provide the elements to answer OP's question)
The error you stated is not really related to the question "what is a parallel array". "Variable used before it has been assigned a value". Of course ! Your array is Null. The variable is declared but no instance of it has been created. And Arrays are that strict in dotNet (unlike JavaScript)
What's your real question ?
It's more related to "how should I assign values to (parallel) array(s)" and could be reformulated like "How to read string values stored in a text file in parallel arrays and write them back ?"
Homework questions usually disallows the use of alternative approaches (and sometimes such homework questions are downvoted)
Different approaches like (using a database with linq or) :
Use File.ReadAllLines() to know the number of lines right from the beginning...
Declare your arrays top level : you won't be able to access them outside your btnRead Click otherwise.
Private P_CODE As String()
Private P_DESCRIPT As String()
' ...
Private P_PRICE As String()
Load the file content inside your btnRead Click...
Dim AllLines As String() = File.ReadAllLines(filePath)
' ^^ the above will open and close the file XD
Dim Columns As String()
' Initialize your arrays...
ReDim(P_CODE, AllLines.Length - 1)
ReDim(P_DESCRIPT, AllLines.Length - 1)
' ...
ReDim(P_PRICE, AllLines.Length - 1)
' set each cell value.
For LineIndex As Int32 = 0 To P_CODE.Length - 1
Columns = AllLines(LineIndex).Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
' Hey ! Your File Datas are ordered horizontaly,
' so Columns must be indexed from 0 to 5
' instead of you "i" in your code in order
' to correctly feed your parallel arrays
Next
Your teacher wanna force you to open the file using StreamReader and teach you to not forget to close the file... and use StreamReader.ReadLine() ... Okay..!
' ...
Dim LineIndex As Int32 = 0
Dim textIn As New StreamReader(filePath)
' ^^ why do you bother using a FileStream ?
Dim Row As String = textIn.ReadLine()
Dim Columns As String()
Do While row IsNot Nothing
Redim Preserve P_CODE(LineIndex)
Redim Preserve P_DESCRIPT(LineIndex)
' ...
Redim Preserve P_PRICE(LineIndex)
Columns = Row.Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
Row = textIn.ReadLine()
LineIndex = LineIndex + 1
Loop
textIn.Close() ' Voila !
' /!\ Add at least a Try Catch enclosing your Do/Loop if you're lazy.
Tell your teacher you're gonna use Using because he forces you to use StreamReader.Peek() (is .Peek() necessary ?)
Using textIn As New StreamReader(filePath)
Dim LineIndex As Int32 = 0
Dim Columns As String()
Do While textIn.Peek() <> -1
Redim Preserve P_CODE(LineIndex)
Redim Preserve P_DESCRIPT(LineIndex)
' ...
Redim Preserve P_PRICE(LineIndex)
Columns = textIn.ReadLine().Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
LineIndex = LineIndex + 1
Loop
End Using ' StreamReader closed ! XD
No ! Don't ask me to use a FileStream ! I would if I know the size of each data chunck in the file and I'm using structures of fixed size. FileStream is best used when manipulating large buffer of datas as it directly works in memory with appropriate asynchronous checks.
Just to read lines ? No ! For this part, read the documentation.
String.Format()
Dim Row As String
MyListBox.Items.Clear()
For LineIndex As Int32 = 0 To P_CODE.Length - 1
Row = String.Format("{0, -12}{1,-16}{2,10}{3,10}{4,8}{5,10}", _
P_CODE(LineIndex), _
P_DESCRIPT(LineIndex), _
P_INDATE(LineIndex), _
P_QOH(LineIndex), _
P_MIN(LineIndex), _
P_PRICE(LineIndex))
MyListBox.Items.Add(Row)
Next
Write file to InventoryDataOut.txt..
Dim Separator As String = "|"
Dim FileContent As New StringBuilder() ' System.Text
' Prepare File content...
If P_CODE.Length > 0 Then
For LineIndex As Int32 = 0 To P_CODE.Length - 2 ' Note the -2
FileContent.AppendLine(String.Format("{0}{6}{1}{6}{2}{6}{3}{6}{4}{6}{5}", _
P_CODE(LineIndex), _
P_DESCRIPT(LineIndex), _
P_INDATE(LineIndex), _
P_QOH(LineIndex), _
P_MIN(LineIndex), _
P_PRICE(LineIndex), _
Separator)))
Next
FileContent.Append(String.Format("{0}{6}{1}{6}{2}{6}{3}{6}{4}{6}{5}", _
P_CODE(P_CODE.Length - 1), _
P_DESCRIPT(P_CODE.Length - 1), _
P_INDATE(P_CODE.Length - 1), _
P_QOH(P_CODE.Length - 1), _
P_MIN(P_CODE.Length - 1), _
P_PRICE(P_CODE.Length - 1), _
Separator)))
' This ensures we don't add unnecessary line at the end of the file
' which would make your application explode !
' best move is to check for null entries upon file parsing.
' (Again : File.ReadAllLines() + RemoveEmptyString parameter to keep it simple)
End If
' Create your file using the stream object
' you're forced to use by your teacher,
' then dump the the content of your StringBuilder inside like
MyDummyStream.Write(FileContent.ToString())
' And close you dummy stream or use Using XD
Does your teacher has a bunch of CSV-like files which needs separator conversion from space to pipe ?
It seems he's just lazy to write the code to dispatch each column in several parallel arrays for display or other purpose. Or why would you use the space as separator upon loading the content of your file while using pipe instead to write them ?
If its a typo, just don't bother reading this. Otherwise, your teacher is just asking you to create a small program that converts the space separator to pipe... (while giving you the mission to learn manipulate (parallel) arrays, streams I/O, and String.Format)
.

VB.NET Checking for existing files and assigning new Version Numbers to the name?

Alright, this one has been driving me up a wall for the past few hours, and I feel like I can almost taste victory, but I am stuck.
I am writing files into a directory based on user supplied requirements, and this particular section deals with assigning a new Version Number to the new file. So basically, this creates the new file using a naming convention of:
Path\FileName_ver1
Path\FileName_ver2
And so on. The issue is, I cannot figure out how to determine if a file with similiar naming (minus the _ver# string) exists in the directory, and then parse the name to find out the current version number, and then create the new file using the version number and adding 1 to it.
If you look at my current code, the issue at the moment is arising when it goes into the loop, telling me that the array is out of bounds, even though the file does exist within the directory.
Dim strPossibleFilename() As String = Directory.GetFiles(savePath, saveName & "_ver*" & saveExt)
Dim intVersionNumber As Integer = 1
For i = 0 To strPossibleFilename.Length - 1
If File.Exists(strPossibleFilename(i)) Then
Dim fileInfo As New FileInfo(strPossibleFilename(i))
Dim fullName As String
Dim strVersionNumber As String
fullName = fileInfo.FullName
Dim versionPosition As Integer = fullName.IndexOf("_ver")
Dim dotPosition As Integer = fullName.IndexOf(".")
Dim versionCharacterCount As Integer = dotPosition - versionPosition
strVersionNumber = fullName.Substring(versionPosition, versionCharacterCount)
If intVersionNumber < strVersionNumber Then
intVersionNumber = strVersionNumber
End If
End If
Next i
If intVersionNumber > 1 Then
saveLocation = savePath & saveName & "_ver" & intVersionNumber + 1 & saveExt
fstr = New FileStream(saveLocation, FileMode.CreateNew, FileAccess.ReadWrite)
fstr.Write(inBuf, 0, bytesRead)
Else
saveLocation = savePath & saveName & "_ver1" & saveExt
fstr = New FileStream(saveLocation, FileMode.CreateNew, FileAccess.ReadWrite)
fstr.Write(inBuf, 0, bytesRead)
End If
P.S. All of the other functionality works, as far as the writing and everything, I am doing this in multiple places in my code, including assigning other varied strings to file names when one already exists...
Please let me know if you need more information.
EDIT:
Made a couple changes based on the answers given, and now it is finding the file, but this brings up a new problem... So I cannot figure out how to ONLY grab the number that is AFTER "_ver" to assign that to intVersionNumber.. Any ideas?
EDIT 2:
Okay, to solve that issue, I added:
Dim strVersionString As String
And added a few other things, so now the for loop looks like this:
For i = 0 To strPossibleFilename.Length - 1
If File.Exists(strPossibleFilename(i)) Then
Dim fileInfo As New FileInfo(strPossibleFilename(i))
Dim fullName As String
Dim strVersionString As String
Dim strVersionNumber As String
fullName = fileInfo.FullName
Dim versionPosition As Integer = fullName.IndexOf("_ver")
Dim dotPosition As Integer = fullName.IndexOf(".")
Dim versionCharacterCount As Integer = dotPosition - versionPosition
strVersionString = fullName.Substring(versionPosition, versionCharacterCount)
Dim rPosition As Integer = strVersionString.IndexOf("r") + 1
strVersionNumber = strVersionString.Substring(rPosition, strVersionString.Length - rPosition)
If intVersionNumber < strVersionNumber Then
intVersionNumber = strVersionNumber
End If
End If
Next i
And now it is working :D Thanks for all the help!
You are doing it right, I have a sneaking suspicion here with this line
For i = 0 To strPossibleFilename.Length
change it to
For i = 0 To strPossibleFilename.Length -1
and then unless you kissed BillGates daughter and he's pissed off, it should work!
For the second part of your question, how to get the number after the _ver
' consider padding the version number
' with leading zeros
' and using a second underscore
' to make it easier to parse for number
Dim fileName As String = "filename_ver_001"
Dim parts As String() = fileName.Split("_"c)
Dim verNumber As Integer = Integer.Parse(parts(2))
If you add a second underscore, you can use the String.Split to break the filename into an array.
FWIW, if you want a more sortable file list pad out the number with leading zeros. Otherwise filename_ver11 is ordered before filename_ver2

vb.NET Arrays - Turning a String into a Table

I am working on a windows form application, and I have it reading a text file that has information stored in the form of a table. It looks somewhat like this:
ID Name URL
1 client1 client1.com
2 client2 client2.com
3 client3 client3.com
And so on...
What I need to do is get this data to be read from a stream reader, that throws it into a string, including vbtabs and newlines, and then create an array out of that information, so that it acts as a table that I can then later pull information from based on the column names (i.e. ID, Name, URL) and the ID number. I do not have a lot of experience with arrays, so I was hoping to get some help here as how to do this.
The code I have so far for this functionality is:
Dim readCLientTxtListReader As New StreamReader(strReplicationDataClientAccessListPath)
Dim strClientAccessList As String = readCLientTxtListReader.ReadToEnd
Console.Write(strClientAccessList)
readCLientTxtListReader.Close()
Dim i As Integer
Dim aryClientAccessList() As String
aryClientAccessList = strClientAccessList.Split(vbTab)
For i = 0 To UBound(aryClientAccessList)
Console.WriteLine(aryClientAccessList)
Next i
The problem about this is that it just creates a new instance of the array as each individual string of characters between each vbtab. which means, the arrays look like:
ID
Name
URL
1
client1
client1.com
2
client2
client2.com
3
client3
client3.com
Which is not really what I need.
Any ideas?
If you need more info, let me know.
Edit: As an added side-note, I believe multidimensional arrays are what I am looking for, and am currently looking them up now, but if you have any more information on these, I would greatly appreciate it.
The way I am reading your end goal is that you want to have an array that that contains each row of the file and that each row should be an array with the tokens for that row in it. If that is correct, then you could do something like this:
var lines = new List<string[]>();
using (var strReplicationDataClientAccessListPath = new FileStream("path", FileMode.Open))
using (var streamReader = new StreamReader(strReplicationDataClientAccessListPath))
{
while (streamReader.Peek() >= 0)
{
var line = streamReader.ReadLine();
if (!string.IsNullOrEmpty(line))
lines.Add(line.Split('\t'));
}
}
foreach (var line in lines)
{
foreach (var token in line)
Console.Write(token);
Console.WriteLine();
}
I have not done VB in a long time but here is the C# which can be run through a converter to get VB.NET. Also I did it using a List, if you need an array at the end you can do:
lines.ToArray();
This is rclements code
converted to VB
Dim lines = New List(Of String())()
Using strReplicationDataClientAccessListPath = New FileStream("path", FileMode.Open)
Using streamReader = New StreamReader(strReplicationDataClientAccessListPath)
While streamReader.Peek() >= 0
Dim line = streamReader.ReadLine()
If Not String.IsNullOrEmpty(line) Then
lines.Add(line.Split(ControlChars.Tab))
End If
End While
End Using
End Using
For Each line As var In lines
For Each token As var In line
Console.Write(token)
Next
Console.WriteLine()
Next
You are trying to simulate CSV -> DataTable workflow, where vbTab is your CSV delimiter, and DataTable is your storage structure (you can query by field name, and by row index). There are numerous solutions on the internet, just google for CSV to DataTable.
Here is one, linked from here (SO answer).
If you still want multi-dimensional arrays, I recommended a List(Of String()) instead of String(,), because you would then not need to manage memory allocation. Each line of data would be an element of List, and a single dimension array, where column values are array elements 0-N.
To read from file, you can use IO.File.ReadAllLines.
Is it what you need?
'Read Values from the text file and store in a DataTable
Dim dt As New DataTable
Using TextReader As New IO.StreamReader("C:\Data.txt")
Dim Line As String = TextReader.ReadLine
If String.IsNullOrEmpty(Line) Then
MsgBox("No Data")
Exit Sub
End If
With Line.Split(vbTab)
dt.Columns.Add(.GetValue(0))
dt.Columns.Add(.GetValue(1))
dt.Columns.Add(.GetValue(2))
End With
Do
Line = TextReader.ReadLine
If Line Is Nothing Then Exit Do
dt.Rows.Add(Line.Split(vbTab))
Loop
End Using
'Print the DataTable header
For Each Column As DataColumn In dt.Columns
Console.Write(Column.ColumnName & vbTab)
Next
Console.WriteLine(vbCrLf & New String("-", 24))
'Print the DataTable contents
For Each Row As DataRow In dt.Rows
Console.WriteLine(Row("ID") & vbTab & Row("Name") & vbTab & Row("URL"))
Next
I have added another solution using List in case you prefer it more than the DataTable:
'Read Values from the text file and store in a List of type Tuples
Dim Values As New List(Of Tuple(Of String, String, String))
Using TextReader As New IO.StreamReader("C:\Data.txt")
Dim Line As String = TextReader.ReadLine
Do Until Line Is Nothing
With Line.Split(vbTab)
Values.Add(Tuple.Create(.GetValue(0).ToString, .GetValue(1).ToString, .GetValue(2).ToString))
End With
Line = TextReader.ReadLine
Loop
End Using
'Print the List contents
For Each T As Tuple(Of String, String, String) In Values
Console.WriteLine(T.Item1 & vbTab & T.Item2 & vbTab & T.Item3)
Next

Resources