I am using Visual Basic.net.
If I have a string that has many lines in it, is it possible to insert a string at a certain line? I see that there is an insert function for strings. Is there a function to insert a string at a certain line of another string?
Is there a function to insert a string at a certain line of another
string?
No, because a string is not a list/array of lines. You have to split it by Environment.NewLine to get an array, ToList to get a List(Of String) which has an Insert method. Then you can use String.Join to put it together after you have inserted it:
Dim lines = MultiLineText.Split({Environment.NewLine}, StringSplitOptions.None).ToList()
lines.Insert(2, "test") ' will throw an ArgumentOutOfRangeException if there are less than 2 lines '
Dim result = String.Join(Environment.NewLine, lines)
There is no string methods that handles a string as a collections of lines. You can use the Insert method, but you have to find out where in the string to put the line yourself.
Example:
' Where to insert
Dim line As Integer = 4
' What to insert
Dim content As String = "asdf"
' Locate the start of the line
Dim pos As Integer = 0
Dim breakLen As Integer = Environment.Newline.Length
For i As Integer = 0 to line
pos = text.IndexOf(Environment.Newline, pos + breakLen)
Next
' Insert the line
text = text.Insert(pos, content + Environment.Newline)
Strings have no idea what a "line" is. A string is only a sequence of characters. What you can do is to convert your string into a list of individual lines (for example as List<string>) and then insert into that list.
List<string> listOfLines = new List<string>();
listOfLines.AddRange(sourceString.Split(new String[] { Environment.NewLine }, StringSplitOptions.None));
listOfLines.Insert(13, "I'm new here");
string result = String.Join(Environment.NewLine, listOfLines);
This is C# code, but I'm pretty sure you can easily convert this to VB.NET.
Related
I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.
As an example I have a text file called system.txt which contains single line text. The text is something like this:
[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]
What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box
Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.
Here is what i could write so far but i dont have any idea if there is any logic in my code:
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
For i = 1 To 3
If line.Contains("Last Name=" & i) Then
field.Add(line.Substring(line.IndexOf("=") + 2))
End If
Next
Next
End Sub
Im
You can get this down to a function with a single line of code:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function
But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")
Return File.ReadLines(fileName).
Select(Function(line) exp.Match(line)).
Where(Function(m) m.Success).
Select(Function(m) m.Groups("LastName").Value)
End Function
See a simple example of the expression here:
https://dotnetfiddle.net/gJf3su
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
.Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
.ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()
Using your sample data...
I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.
Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)
Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).
If no match is found, an empty string is returned.
Private Function readcrnFile() As String
Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
For Each s In splits
If s.StartsWith("Last Name=") Then
Return s.Substring(10)
End If
Next
Return ""
End Function
Usage...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = readcrnFile()
End Sub
You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.
Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)
At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array
For Each p As String In parts
If p.StartsWith("Last Name") Then
Dim data = p.Split("="c)
field.Add(data(1))
Exit For
End If
Next
Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry
Dim data = parts(1).Split("="c)
A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.
So, for example, the loop above could be replaced with
field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))
As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string
You should first know the difference between ReadAllLines() and ReadLines().
Then, here's an example using only two simple string manipulation functions, String.IndexOf() and String.Substring():
Sub Main(args As String())
Dim entryMarker As String = "[Last Name="
Dim closingMarker As String = "]"
Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
If Not IsNothing(value) Then
Console.WriteLine("value = " & value)
Else
Console.WriteLine("Entry not found")
End If
Console.Write("Press Enter to Quit...")
Console.ReadKey()
End Sub
Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
Dim entryIndex As Integer
Dim closingIndex As Integer
For Each line In File.ReadLines(fileName)
entryIndex = line.IndexOf(entry) ' see if the marker is in our line
If entryIndex <> -1 Then
closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
If closingIndex <> -1 Then
' calculate the starting position and length of the value after the entry marker
Dim startAt As Integer = entryIndex + entry.Length
Dim length As Integer = closingIndex - startAt
Return line.Substring(startAt, length)
End If
End If
Next
Return Nothing
End Function
I have data in the following structure:
Structure student
Dim stdntpass As String
Dim fname As String
Dim sname As String
Dim age As Byte
Dim year As Integer
Dim stdntuser As String
End Structure
I need to take the data in that structure and output it to CSV. I was planning on using a StringBuilder object to do it, but I can't figure out how to give the structure to the StringBuilder.
Here is a function that uses reflection to determine what fields exist in the student structure:
Public Function StudentsToCSV(students As IEnumerable(Of student)) As String
Const separator As Char = ";"c
Dim sb As New StringBuilder
'Get the data elements
Dim studentFields = GetType(student).GetFields()
'Output headline (may be removed)
For Each field In studentFields
sb.Append(field.Name)
sb.Append(separator)
Next
sb.AppendLine("")
'Write a line for each student
For Each s In students
'Write the value of each field
For Each field In studentFields
Dim value As String = Convert.ToString(field.GetValue(s))
sb.Append(value)
'... followed by the separator
sb.Append(separator)
Next
sb.AppendLine("")
Next
Return sb.ToString()
End Function
You can pass any set of students to this function - may it be an array, a List(Of student) or whatever.
One way is to override the ToString function. now passing a whole object to a stringbuilder or even sending the Tostring function to the file will pass the values how you want them:
Structure student
Dim stdntpass As String
Dim fname As String
Dim sname As String
Dim age As Byte
Dim year As Integer
Dim stdntuser As String
Public Overrides Function ToString() As String
Return Join({stdntpass, fname, sname, age.ToString, year.ToString, stdntuser}, ","c) + vbNewLine
End Function
End Structure
The StringBuilder has no way to take a whole Structure and automatically append each of the properties from that Structure. If you must use a StringBuilder, you could do it like this:
builder.Append(s.stdntpass)
builder.Append(",")
builder.Append(s.fname)
builder.Append(",")
builder.Append(s.sname)
builder.Append(",")
builder.Append(s.age)
builder.Append(",")
builder.Append(s.year)
builder.Append(",")
builder.Append(s.stdntuser)
Dim csvLine As String = builder.ToString()
However, it would be easier to use the String.Join method, like this:
Dim csvLine As String = String.Join(",", s.stdntpass, s.fname, s.sname, s.age, s.year, s.stdntuser)
You could use reflection to dynamically get the list of properties from the structure, but then you won't have much control over the order in which the fields get appended without using attributes, or something, which could get ugly.
In any case, you should be careful, though, that values are properly escaped. If any of the strings in your structure contain commas, you need to surround that field with quotation marks. And if any of those strings quotation marks, they need to be doubled. You could fix the values with a method like this:
Public Function EscapeValueForCsv(value As String) As String
Return """" & value.Replace("""", """""") & """"
End Function
Then you could call that on each of the properties before passing it to String.Join:
Dim csvLine As String = String.Join _
(
",",
EscapeValueForCsv(s.stdntpass),
EscapeValueForCsv(s.fname),
EscapeValueForCsv(s.sname),
EscapeValueForCsv(s.age.ToString()),
EscapeValueForCsv(s.year.ToString()),
EscapeValueForCsv(s.stdntuser)
)
I have a CSV file with many rows in which I need to update/replace column four's value using VB.NET. There are no headers on the columns so the loop can start on row one.
infile.csv
"value1","value2","value3","value4"
After much googling, there are lots of examples on how to read and write CSV files, but none quite what is needed. I know there are multiple ways to accomplish this task, but a requirement is that it's done with VB.NET. Any help would be greatly appreciated.
Final code ported from Marco's C# answer
Private Sub CSVmod(ByVal strFileName As String, ByVal newFileName As String)
Dim strLines As String() = File.ReadAllLines(strFileName)
Dim strList As New List(Of String)
Dim strReplace As String = "test"
For Each line In strLines
Dim strValues As String() = line.Split(",")
If (strValues.Length = 14) Then
strValues(3) = strReplace
strList.Add(String.Join(",", strValues))
End If
Next
File.WriteAllLines(newFileName, strList.ToArray())
I'm sorry, but I can write it only in C#.
I think you won't find many problems to convert to VB.NET.
Here is my code:
private void SubstFile(string filename, string newFileName)
{
// Reading all rows of the file
string[] lines = File.ReadAllLines(filename);
List<string> list = new List<string>();
foreach (string line in lines)
{
// For every row I split it with commas
string[] values = line.Split(',');
// Check to have 4 values
if (values.Length == 4)
{
// Substitute fourth value
values[3] = "new value";
// Add modified row to list
list.Add(String.Join(",", values));
}
}
// Save list to new file
File.WriteAllLines(newFileName, list.ToArray());
}
VB.NET version:
Private Sub SubstFile(filename As String, newFileName As String)
' Reading all rows of the file
Dim lines As String() = File.ReadAllLines(filename)
Dim list As List(Of String) = New List(Of String)()
For Each line As String In lines
' For every row I split it with commas
Dim values As String() = line.Split(","c)
' Check to have 4 values
If values.Length = 4 Then
' Substitute fourth value
values(3) = "new value"
' Add modified row to list
list.Add(String.Join(",", values))
End If
Next
' Save list to new file
File.WriteAllLines(newFileName, list.ToArray())
End Sub
Use python....one line of code
df = pandas.read_csv('file.csv)
I have a file txt file that holds 3 values each seperated by a space how can i assign each value to its own variable and use that for other things?
as example the numbers might be displayed in the text file as:
-1100.02 -1958.19 0.0
Translating Marco’s C# code to VB:
Dim s As String = File.ReadAllText(filename)
Dim nums As String() = s.Split(" "c)
To get numbers, you need to parse the strings separately. You can use Linq to do this:
Dim numbers As Double() = From num In nums Select Double.Parse(num)
In C#:
string s = File.ReadAllText(filename);
string[] nums = s.Split(' ');
So you can access nums[index] where index should be between 0 and 2.
Note that you MUST check if everything went ok...
If you need you can also try:
foreach (string num in nums)
{
double d = double.Parse(num);
// Here you can do what you want with d
}
Try this:
Dim line as String = "-1100.02 -1958.19 0.0"
Dim values() as Double = Array.ConvertAll(line.Split(New Char() { " "c }, StringSplitOptions.RemoveEmotyEntries), AddressOf Convert.ToDouble)
This will result in values being filled with numbers from the input string (assuming a set of valid numbers on each line).
dim strSplitted() as string = Line.split(" "c)
' strSplitted(0), strSplitted(1) and strSplitted(2) will hold the values.
Line is the line in the file ofcourse :-)
update: code updated according to comments.
Right - to start with, I'm entering unfamiliar areas with this - so please be kind!
I have a script that looks a little something like this:
Private Function checkString(ByVal strIn As String) As String
Dim astrWords As String() = New String() {"bak", "log", "dfd"}
Dim strOut As String = ""
Dim strWord As String
For Each strWord In astrWords
If strIn.ToLower.IndexOf(strWord.ToLower, 0) >= 0 Then
strOut = strWord.ToLower
Exit For
End If
Next
Return strOut
End Function
It's function is to check the input string and see if any of those 'astrWords' are in there and then return the value.
So I wrote a bit of code to dynamically create those words that goes something like this:
Dim extensionArray As String = ""
Dim count As Integer = 0
For Each item In lstExtentions.Items
If count = 0 Then
extensionArray = extensionArray & """." & item & """"
Else
extensionArray = extensionArray & ", ""." & item & """"
End If
count = count + 1
Next
My.Settings.extensionArray = extensionArray
My.Settings.Save()
Obviously - it's creating that same array using list items. The output of that code is exactly the same as if I hard coded it - but when I change the first bit of code to:
Dim astrWords As String() = New String() {My.Settings.extensionArray}
instead of:
Dim astrWords As String() = New String() {"bak", "log", "dfd"}
It starts looking for the whole statement instead of looping through each individual one?
I think it has something to do with having brackets on the end of the word string - but I'm lost!
Any help appreciated :)
When you use the string from the settings in the literal array, it's just as if you used a single strings containing the delimited strings:
Dim astrWords As String() = New String() {"""bak"", ""log"", ""dfd"""}
What you probably want to do is to put a comma separated string like "bak,log,dfd" in the settings, then you can split it to get it as an array:
Dim astrWords As String() = My.Settings.extensionArray.Split(","C)
You need to set extensionArray up as a string array instead of simply a string.
Note that
Dim something as String
... defines a single string, but
Dim somethingElse as String()
... defines a whole array of strings.
I think with your code, you need something like:
Dim extensionArray As String() = new String(lstExtensions.Items)
Dim count As Integer = 0
For Each item In lstExtentions.Items
extensionArray(count) = item
count = count + 1
Next
My.Settings.extensionArray = extensionArray
My.Settings.Save()
Then at the start of checkString you need something like
Private Function checkString(ByVal strIn As String) As String
Dim astrWords As String() = My.Settings.extensionArray
...
There also might be an even easier way to turn lstExtentions.Items into an Array if Items has a 'ToArray()' method, but I'm not sure what Type you are using there...
What you've done is created a single string containing all 3 words. You need to create an array of strings.
New String() {"bak", "log", "dfd"}
means create a new array of strings containing the 3 strings values "bak", "log" and "dfd".
New String() {My.Settings.extensionArray}
means create a new array of strings containing just one value which is the contents of extensionArray. (Which you have set to ""bak", "log", "dfd""). Note this is one string, not an array of strings. You can't just create 1 string with commas in it, you need to create an array of strings.
If you want to create your array dynamically, you need to define it like this:
Dim astrWords As String() = New String(3)
This creates an array with 3 empty spaces.
You can then assign a string to each space by doing this:
astrWords(0) = "bak"
astrWords(1) = "log"
astrWords(2) = "dfd"
You could do that bit in a for loop:
Dim count As Integer = 0
For Each item In lstExtentions.Items
astrWords(count) = item
count = count + 1
Next
Alternatively, you could look at using a generic collection. That way you could use the Add() method to add multiple strings to it
I think you want your extensionArray to be of type String() and not String. When you are trying to initialize the new array, the initializer doesn't know to parse out multiple values. It just sees your single string.