How to read from exact line to EOF - vb.net

I'm creating a program that is supposed to enter text from file ( in .txt format) to Textbox1 when Button1 action clicked. But reading must start after line 6 (in 1,2,3,4,5,6 notation) or after line 5 (in 0,1,2,3,4,5 notation) and it should last till end of the file.

Use
File.ReadLines("C:\data\text.txt")
and bypass the lines you don´t need
Dim Lines = File.ReadLines("C:\data\text.txt")
Dim sb As New StringBuilder()
' Start on Line 7 To Last Line
For i As Long = 7 To Lines.Count
Dim line as String = Lines(i)
sb.AppendLine(line)
Next
MessageBox.Show(sb.ToString())

Related

Read part of text file using VB.net

I am new to VB.net and I need help.
What I want to do is read lines from a text file that take place between two specific lines. Within these lines I have to look for a specific one and display the next line, if that makes any sense. The catch is that there are more than one pair of these marker lines that contain the exact lines that I need within them. I hope the explanation is clear enough for you guys! Is that possible?
I am looking for the line under the number 10 in the parts of the text file shown on the screenshot. Since there are a lot of 10s in that file I need to read it on parts in order to get the exact line needed.
The code below is what I have so far thanks to #TimSchmelter in my previous question Read certain line in text file and display the next. Which is actually the bit that looks for a specific line and displays the next one, but it reads all of the lines within that text file.
Dim x1 As Decimal = File.ReadLines("filepath").
SkipWhile(Function(line) Not line.Contains(" 10")).Skip(1).FirstOrDefault()
If x1 >= 0.0 Then TextBox1.Text = x1
Your original code was the best since it allowed you to have better control over what you read and whatnot, so I'm going to use that in my answer.
The LINQ approach will only give you the first instance of what you're looking for, therefore it is better to read though the whole file line-by-line.
First, a structure holding the coordinates of a line:
Public Structure Line
Public Start As PointF 'Start coordinates.
Public [End] As PointF 'End coordinates.
Public Sub New(ByVal Start As PointF, ByVal [End] As PointF)
Me.Start = Start
Me.End = [End]
End Sub
Public Sub New(ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single)
Me.New(New PointF(x1, y1), New PointF(x2, y2))
End Sub
End Structure
We will use this structure so that we can return a list of all lines we've found.
This will read the file line-by-line and look for our wanted values:
EDIT: I've updated the code to make it properly read the coordinates (i.e. it is no longer bound by the order: 10, 20, 11, 21).
I have also made it only read coordinates located inside AcDbLine/LINE blocks.
Public Function ParseLines(ByVal File As String) As List(Of Line)
'Create a list of Line structures.
Dim Lines As New List(Of Line)
'Create an array holding four items: the coordinates for 10, 20, 11 and 21.
Dim CoordValues As Single() = New Single(4 - 1) {}
'Declare a variable holding the current index in the array:
'CoordIndex = 0 represents the first X-coordinate (10).
'CoordIndex = 1 represents the first Y-coordinate (20).
'CoordIndex = 2 represents the second X-coordinate (11).
'CoordIndex = 3 represents the second Y-coordinate (21).
Dim CoordIndex As Integer = 0
'Declare a variable indicating whether we are currently inside an AcDbLine/LINE block.
Dim InsideAcDbLine As Boolean = False
Using sReader As New StreamReader(File) 'Open a StreamReader to our file.
While Not sReader.EndOfStream 'Keep reading until we've reached the end of the file.
Dim line As String = sReader.ReadLine() 'Read a line.
'Check if we're inside a AcDbLine/LINE block and that we aren't at the end of the file.
If InsideAcDbLine = True AndAlso Not sReader.EndOfStream Then
'Determine if the current line contains 10, 20, 11 or 21.
'Depending on what "line.Trim()" returns it will execute the code of the respective "Case".
'Ex: If "line.Trim()" returns "20" it will execute the code of 'Case "20"', which is 'CoordIndex = 1'.
Select Case line.Trim() 'Trim() removes leading or trailing space characters from the string (i.e. " 10" -> "10").
Case "10" : CoordIndex = 0 'We've reached "10", the following line is coordinate x1.
Case "20" : CoordIndex = 1 'We've reached "20", the following line is coordinate y1.
Case "11" : CoordIndex = 2 '[...] x2.
Case "21" : CoordIndex = 3 '[...] y2.
Case Else : Continue While
' "Continue While" stops execution at this point and
' goes back to the beginning of the loop to: "Dim line As String = ...".
'
' - If "line.Trim()" DOES NOT return 10, 20, 11 or 21 then we
' just want to skip the rest of the code (in other words: ignore the current line).
End Select
'I used colons above for better readability as they can be used to replace line breaks.
'For example the above SHOULD ACTUALLY be:
'
'Select Case line.Trim()
' Case "10"
' CoordIndex = 0
' Case "11"
' (and so on)
'=========================================
Dim nextLine As String = sReader.ReadLine() 'Read the next line.
Dim Coordinate As Single 'Declare a variable for the current coordinate.
'Try parsing the line into a single using
'invariant culture settings (decimal points must be dots: '.').
If Single.TryParse(nextLine.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, Coordinate) = True Then
CoordValues(CoordIndex) = Coordinate 'Add the coordinate to the array.
If CoordIndex = CoordValues.Length - 1 Then 'Have we reached the end of the array?
InsideAcDbLine = False 'We've found all values we want. Do not look for any more in this block.
Lines.Add(New Line(CoordValues(0), CoordValues(1), CoordValues(2), CoordValues(3))) 'Create a new Line and set its coordinates to the values of 10, 20, 11 and 21.
Array.Clear(CoordValues, 0, CoordValues.Length) 'Set all the items in the array to zero.
End If
End If
End If
'Check if we've reached an "AcDbLine" or "LINE" marker.
'Used in order to determine whether we are inside a AcDbLine/LINE block.
'If we aren't, then we shouldn't look for any coordinates.
Select Case line.Trim()
Case "AcDbLine" : InsideAcDbLine = True 'Start of an AcDbLine/LINE block.
Case "LINE" : InsideAcDbLine = False 'End of an AcDbLine/LINE block.
End Select
End While
End Using
Return Lines 'Return our list of lines.
End Function
This code will only add a new line to the list once it has found four different coordinates, i.e. if it at the end only finds x1, y1 and x2 (but not y2) it will just ignore those values.
Here's how you can use it:
Dim Lines As List(Of Line) = ParseLines("filepath")
'Iterate through every parsed line.
For Each Line As Line In Lines
'Print all parsed lines to console in the format of:
'Line start: {X=x1, Y=y1}
'Line end: {X=x2, Y=y2}
Console.WriteLine("Line start: " & Line.Start.ToString())
Console.WriteLine("Line end: " & Line.End.ToString())
Console.WriteLine()
Next
To get individual coordinates of a line you can do (assuming you're still using the loop above):
Dim StartX As Single = Line.Start.X
Dim StartY As Single = Line.Start.Y
Dim EndX As Single = Line.End.X
Dim EndY As Single = Line.End.Y
If you want to access individual lines without a loop you can do:
Dim Line As Line = Lines(0) '0 is the first found line, 1 is the second (and so on).
Documentation:
List(Of T) class
PointF class
How to: Declare a Structure (Visual Basic)
Arrays in Visual Basic
Single Data Type (Visual Basic)
Single.TryParse() method
Select Case statement

replace a line in richtextbox vb.net

I have this code but it have errors , what should i do ?
Dim lines As New List(Of String)
lines = RichTextBox1.Lines.ToList
'Dim FilterText = "#"
For i As Integer = lines.Count - 1 To 0 Step -1
'If (lines(i).Contains(FilterText)) Then
RichTextBox1.Lines(i) = RichTextBox1.Lines(i).Replace("#", "#sometext")
'End If
Next
RichTextBox1.Lines = lines.ToArray
Update: while the following "works" it does only modify the array which was returned from the Lines-property. If you change that array you don't change the text of the TextBox. So you need to re-assign the whole array to the Lines-property if you want to change the text(as shown below). So i keep the first part of my answer only because it fixes the syntax not the real issue.
It's not
RichTextBox1.Lines(i).Replace = "#sometext"
but
RichTextBox1.Lines(i) = "#sometext"
You can loop the Lines forward, the reverse loop is not needed here.
Maybe you want to replace all "#" with "#sometext" instead:
RichTextBox1.Lines(i) = RichTextBox1.Lines(i).Replace("#","#sometext")
So here the full code necessary (since it still seems to be a problem):
Dim newLines As New List(Of String)
For i As Integer = 0 To RichTextBox1.Lines.Length - 1
newLines.Add(RichTextBox1.Lines(i).Replace("#", "#sometext"))
Next
RichTextBox1.Lines = newLines.ToArray()
But maybe you could even use:
RichTextBox1.Text = RichTextBox1.Text.Replace("#","#sometext")`
because if we have # abcd this code change it to # sometextabcd ! I
Want a code to replace for example line 1 completely to # sometext
Please provide all relevant informations in the first place next time:
Dim newLines As New List(Of String)
For Each line As String In RichTextBox1.Lines
Dim newLine = If(line.Contains("#"), "#sometext", line)
newLines.Add(newLine)
Next
RichTextBox1.Lines = newLines.ToArray()

How to Read first x characters of each line of a text file

HI have a Program that loops through a text file and reads the lines.
Using r As StreamReader = New StreamReader("C:\test.txt")
Dim lineCount = File.ReadAllLines("C:\test.txt").Length
MsgBox(lineCount)
For x = 1 to linecount
line = r.ReadLine
msgbox (line)
next
How can I read the Left most 15 characters of each line of the text file, ignoring the other characters in each line. Lastly, if there are spaces in the first 15 characters, i'd like to remove them.
Calling ReadAllLines to discover how many lines are there to drive a for..loop is wrong and a waste of resources (Essentially you are reading all the file content two times). In particular consider that a StreamReader has a method that tells you if you have reached the end of file
So everything could be changed to a simpler
Dim clippedLines = new List(Of String)()
Dim line As String
Using r As StreamReader = New StreamReader("C:\test.txt")
While r.Peek() >= 0
line = r.ReadLine
Dim temp = if(line.Length > 15, line.Substring(0,15), line)
clippedLines.Add(temp.Trim().Replace(" "c, ""))
End While
End Using
This will remove all the spaces from the line AFTER taking the first 15 char (and thus the result could be a string shorter than 15 chars) If you want a line of 15 char after the space removing operation, then
While r.Peek() >= 0
line = r.ReadLine.Trim().Replace(" "c, "")
Dim temp = if(line.Length > 15, line.Substring(0,15), line)
clippedLines.Add(temp)
End While

A loop exits prematurely when using StreamReader

It's been a long time since I've programmed. I'm writing a form in VB.NET, and using StreamReader to read a text file and populate an 2D array. Here is the text file:
あかさたなはまやらわん
いきしちにひみ り
うくすつぬふむゆる
えけせてねへめ れ
おこそとのほもよろを
And here is the loop, which is within the Load event.
Dim Line As String
Dim Row As Integer = 0
Using sReader As New IO.StreamReader("KanaTable.txt")
Do
Line = sReader.ReadLine
For i = 0 To Line.Length - 1
KanaTable(Row, i) = Line(i)
Next
Row += 1
Loop Until sReader.EndOfStream
End Using
The problem is, once the i in the For Loop reaches 10, it completes the loop and skips the other lines, even when I have a breakpoint. Can you let me know what's probably going on here?
I've figured out the problem, it was very simple. The array declaration for KanaTable:
Dim KanaTable(4, 9) As Char
should have been
Dim KanaTable(4, 10) As Char
Because there was one less space in the array than there should have been, the debugger must have been throwing an IndexOutOfRange which I couldn't see, because, stupid Windows bug (thanks to Bradley Uffner for pointing out this bug.)
If you can use an array of arrays or a list of arrays (List(Of Char())), you can get this down to a single line of code:
Dim KanaTable()() As Char = IO.File.ReadLines("KanaTable.txt").Select(Function(line) line.ToCharArray()).ToArray()
If that's too complicated for you, we can at least simplify the existing code:
Dim KanaTable As New List(Of Char())
Dim Line As String
Using sReader As New IO.StreamReader("KanaTable.txt")
Line = sReader.ReadLine()
While Line IsNot Nothing
KanaTable.Add(Line.ToCharArray())
Line = sReader.ReadLine()
End While
End Using
I can't see an error immediately, but you could try to adapt your code to this:
Using reader As New IO.StreamReader("KanaTable.txt")
Do
line= reader.ReadLine()
If line = Nothing Then
Exit Do
End If
For i = 0 To Line.Length - 1
KanaTable(Row, i) = Line(i)
Next
Row += 1
Loop
End Using

Nested Loop Not Working vb.net

I am trying to read file names from source directory and then read a separate file to rename and move files to target directory. Below code reads the file names but the problem is it only reading the contents of app.ini file only once i.e. for first file name. Code is not looping app.ini as soon as for loops switches to second file name.
Dim di As New IO.DirectoryInfo("D:\Transcend")
Dim diar1 As IO.FileInfo() = di.GetFiles()
Dim dra As IO.FileInfo
If (di.GetFiles.Count > 0) Then
Dim a As Integer = 1
Dim b As Integer = 1
For Each dra In diar1
ComboBox1.Items.Add(dra.FullName.ToString)
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
Do While reader2.Peek() >= 0
Dim line2 = reader2.ReadLine
Do Until line2 Is Nothing
'line2 = reader2.ReadLine()
'ComboBox1.Items.Add(line2.ToString)
'Label1.Text = line2
If line2 <> Nothing Then
If line2.Contains("filename" + a.ToString) Then
Dim values() As String = line2.Split(CChar(":")).ToArray
Dim values2() As String = values(1).Split(CChar(";")).ToArray() 'full filename
Dim values3() As String = values(2).Split(CChar(";")).ToArray() 'keyword to be replaced in filename
Dim values4() As String = values(3).Split(CChar(";")).ToArray() 'fullname in place of keyword
Dim values5() As String = values(4).Split(CChar(";")).ToArray 'destination drive letter
Dim values6() As String = values(5).Split(CChar(";")).ToArray 'destination path after drive letter
ComboBox1.Items.Add(values2(0))
ComboBox1.Items.Add(values3(0))
ComboBox1.Items.Add(values4(0))
ComboBox1.Items.Add(values5(0) + ":" + values6(0))
'Label1.Text = dra.Name.ToString
If dra.Name.ToString.Contains(values2(0)) Then
Dim n As String = dra.Name.Replace(values3(0), values4(0))
File.Copy(dra.FullName, values5(0) + ":" + values6(0) + n)
End If
End If
End If
Exit Do
Loop
a = a + 1
Loop
reader2.Close()
End Using
b = b + 1
Next
Label1.Text = b
Else
MsgBox("No files!")
End
End If
ouput image:
Above image is to show the output and error, first line is the filename1 and the next 8 lines are the output of the app.ini file. As you can see as soon as the filename1 changes to the next file name i.e. Autorun.inf in the 9th line of the above image the same 8 lines of app.ini(line 2nd to 9th in the above image) should be reiterated after Autorun.inf file name but app.ini is not getting to read after file name increments to Autorun.inf and then to FreeSoftware(JF).htm.
The only difference between the first and the second file are the a and b values.
On the first run a will start from 1 and it will be incremented for each line in the app.ini file. After reading 8 lines, the final value of a will be 9.
For the second file, the value a isn't reset so it's value will still be 9. This means that the following condition will never be true because the first run only found value from 1 to 8 *.
If line2.Contains("filename" + a.ToString) Then
To fix your issue, you must set the a variable value back to 1 between each file:
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
a = 1
Do While reader2.Peek() >= 0
* I'm assuming that the filename in your .ini file are sorted (i.e. line containing filename9 isn't listed before filename2) and that no external process changed the content of your .ini file between the first and the second file.