I'm trying to Multithread read all lines with 2 Threads to get diffrent Text instead of same? - vb.net

The problem is when i Multithread to read all lines it somehow reads the same line with the 2 Threads so i can see in my console "hello1" "hello1" but i want to see 1thread."hello1" 2thread."hello2" 1thread."hello3" 2thread. "hello4" and so one how is that Possible?
to read the lines im using this:
For Each element As String In File.ReadAllLines("test.txt")
console.writeline(element)
next

There are probably more efficient ways to do it, but try this...
' Custom "indexes"
Dim t1Count As Integer = 1
Dim t2Count As Integer = 1
' In Thread #1
For Each Element As String In File.ReadAllLines("test.txt")
' Index is odd
If Not t1Count Mod 2 = 0 Then
console.writeline(element)
End If
t1Count += 1
Next
' In Thread #2
For Each Element As String In File.ReadAllLines("test.txt")
' Index is even
If t2Count Mod 2 = 0 Then
console.writeline(element)
End If
t2Count += 1
Next

Related

How do you delete empty lines from a textfile

I am trying to delete empty lines from a textfile using vb.net. This is an example of what I have tried so far however it is not working as expected:
Dim i As Integer = 0
Dim CountDeleted = 0
Dim TextString As String
For Each Line As String In lines
TextString = lines(i)
If TextString.Trim = "" Then
lines.RemoveAt(i)
CountDeleted += 1
End If
i += 1
Next Line
This is an example of the data within a textfile that I would like to remove the lines from:
BUSINESS_UNIT|PO_ID|LINE_NBR|CANCEL_STATUS|
A
B
C
Required output:
BUSINESS_UNIT|PO_ID|LINE_NBR|CANCEL_STATUS|
A
B
C
Any help would be much appreciated
To remove all the blank lines is just one line of code with linq
Dim nonBlank = lines.Where(Function(x) Not String.IsNullOrWhiteSpace(x))
Counting the removed is just a difference between elements in the two lists
Dim CountDeleted = lines.Count - nonBlank.Count
Your code will trigger a runtime exception because you are removing an item from the same collection that you enumerate with the For Each loop.
You could switch to an old fashioned For Next loop but be careful to start from the end of the collection and examine the strings toward the beginning of the collection.
For i = lines.Count - 1 To 0 Step - 1
TextString = lines(i)
If string.IsNullOrWhiteSpace() Then
lines.RemoveAt(i)
CountDeleted += 1
End If
Next
This backward loop is required because when you remove an item from the collection the total items count decrease and the items following the current index will slide one position. A normal (forward) loop will skip to examine the item following the one deleted.
To remove all WhiteSpace strings from List(Of String):
lines.RemoveAll(addressOf String.IsNullOrWhiteSpace)
To remove all WhiteSpace lines from a text file:
File.WriteAllText(path, Regex.Replace(File.ReadAllText(path), "(?m)^\s+^", ""))

Readline Error While Reading From .txt file in vb.net

I have a Streamreader which is trowing an error after checking every line in Daycounts.txt. It is not a stable txt file. String lines in it are not stable. Count of lines increasing or decresing constantly. Thats why I am using a range 0 to 167. But
Here is the content of Daycounts.txt: Daycounts
Dim HourSum as integer
Private Sub Change()
Dim R As IO.StreamReader
R = New IO.StreamReader("Daycounts.txt")
Dim sum As Integer = 0
For p = 0 To 167
Dim a As String = R.ReadLine
If a.Substring(0, 2) <> "G." Then
sum += a.Substring(a.Length - 2, 2)
Else
End If
Next
HourSum = sum
R.Close()
End Sub
If you don't know how many lines are present in your text file then you could use the method File.ReadAllLines to load all lines in memory and then apply your logic
Dim HourSum As Integer
Private Sub Change()
Dim lines = File.ReadAllLines("Daycounts.txt")
Dim sum As Integer = 0
For Each line In lines
If line.Substring(0, 2) <> "G." Then
sum += Convert.ToInt32(line.Substring(line.Length - 2, 2))
Else
....
End If
Next
HourSum = sum
End Sub
This is somewhat inefficient because you loop over the lines two times (one to read them in, and one to apply your logic) but with a small set of lines this should be not a big problem
However, you could also use File.ReadLines that start the enumeration of your lines without loading them all in memory. According to this question, ReadLines locks writes your file until the end of your read loop, so, perhaps this could be a better option for you only if you don't have something external to your code writing concurrently to the file.
Dim HourSum As Integer
Private Sub Change()
Dim sum As Integer = 0
For Each line In File.ReadLines("Daycounts.txt")
If line.Substring(0, 2) <> "G." Then
sum += Convert.ToInt32(line.Substring(line.Length - 2, 2))
Else
....
End If
Next
HourSum = sum
End Sub
By the way, notice that I have added a conversion to an integer against the loaded line. In your code, the sum operation is applied directly on the string. This could work only if you have Option Strict set to Off for your project. This setting is a very bad practice maintained for VB6 compatibility and should be changed to Option Strict On for new VB.NET projects

Progress bar with VB.NET Console Application

I've written a parsing utility as a Console Application and have it working pretty smoothly. The utility reads delimited files and based on a user value as a command line arguments splits the record to one of 2 files (good records or bad records).
Looking to do a progress bar or status indicator to show work performed or remaining work while parsing. I could easily write a <.> across the screen within the loop but would like to give a %.
Thanks!
Here is an example of how to calculate the percentage complete and output it in a progress counter:
Option Strict On
Option Explicit On
Imports System.IO
Module Module1
Sub Main()
Dim filePath As String = "C:\StackOverflow\tabSeperatedFile.txt"
Dim FileContents As String()
Console.WriteLine("Reading file contents")
Using fleStream As StreamReader = New StreamReader(IO.File.Open(filePath, FileMode.Open, FileAccess.Read))
FileContents = fleStream.ReadToEnd.Split(CChar(vbTab))
End Using
Console.WriteLine("Sorting Entries")
Dim TotalWork As Decimal = CDec(FileContents.Count)
Dim currentLine As Decimal = 0D
For Each entry As String In FileContents
'Do something with the file contents
currentLine += 1D
Dim progress = CDec((currentLine / TotalWork) * 100)
Console.SetCursorPosition(0I, Console.CursorTop)
Console.Write(progress.ToString("00.00") & " %")
Next
Console.WriteLine()
Console.WriteLine("Finished.")
Console.ReadLine()
End Sub
End Module
1rst you have to know how many lines you will expect.
In your loop calculate "intLineCount / 100 * intCurrentLine"
int totalLines = 0 // "GetTotalLines"
int currentLine = 0;
foreach (line in Lines)
{
/// YOUR OPERATION
currentLine ++;
int progress = totalLines / 100 * currentLine;
///print out the result with the suggested method...
///!Caution: if there are many updates consider to update the output only if the value has changed or just every n loop by using the MOD operator or any other useful approach ;)
}
and print the result on the same posititon in your loop by using the SetCursor method
MSDN Console.SetCursorPosition
VB.NET:
Dim totalLines as Integer = 0
Dim currentLine as integer = 0
For Each line as string in Lines
' Your operation
currentLine += 1I
Dim Progress as integer = (currentLine / totalLines) * 100
' print out the result with the suggested method...
' !Caution: if there are many updates consider to update the output only if the value has changed or just every n loop by using the MOD operator or any other useful approach
Next
Well The easiest way is to update the progressBar variable often,
Ex: if your code consist of around 100 lines or may be 100 functionality
after each function or certain lines of code update progressbar variable with percentage :)

Start reading massive text file from the end

I would ask if you could give me some alternatives in my problems.
basically I'm reading a .txt log file averaging to 8 million lines. Around 600megs of pure raw txt file.
I'm currently using streamreader to do 2 passes on those 8 million lines doing sorting and filtering important parts in the log file, but to do so, My computer is taking ~50sec to do 1 complete run.
One way that I can optimize this is to make the first pass to start reading at the end because the most important data is located approximately at the final 200k line(s) . Unfortunately, I searched and streamreader can't do this. Any ideas to do this?
Some general restriction
# of lines varies
size of file varies
location of important data varies but approx at the final 200k line
Here's the loop code for the first pass of the log file just to give you an idea
Do Until sr.EndOfStream = True 'Read whole File
Dim streambuff As String = sr.ReadLine 'Array to Store CombatLogNames
Dim CombatLogNames() As String
Dim searcher As String
If streambuff.Contains("CombatLogNames flags:0x1") Then 'Keyword to Filter CombatLogNames Packets in the .txt
Dim check As String = streambuff 'Duplicate of the Line being read
Dim index1 As Char = check.Substring(check.IndexOf("(") + 1) '
Dim index2 As Char = check.Substring(check.IndexOf("(") + 2) 'Used to bypass the first CombatLogNames packet that contain only 1 entry
If (check.IndexOf("(") <> -1 And index1 <> "" And index2 <> " ") Then 'Stricter Filters for CombatLogNames
Dim endCLN As Integer = 0 'Signifies the end of CombatLogNames Packet
Dim x As Integer = 0 'Counter for array
While (endCLN = 0 And streambuff <> "---- CNETMsg_Tick") 'Loops until the end keyword for CombatLogNames is seen
streambuff = sr.ReadLine 'Reads a new line to flush out "CombatLogNames flags:0x1" which is unneeded
If ((streambuff.Contains("---- CNETMsg_Tick") = True) Or (streambuff.Contains("ResponseKeys flags:0x0 ") = True)) Then
endCLN = 1 'Value change to determine end of CombatLogName packet
Else
ReDim Preserve CombatLogNames(x) 'Resizes the array while preserving the values
searcher = streambuff.Trim.Remove(streambuff.IndexOf("(") - 5).Remove(0, _
streambuff.Trim.Remove(streambuff.IndexOf("(")).IndexOf("'")) 'Additional filtering to get only valuable data
CombatLogNames(x) = search(searcher)
x += 1 '+1 to Array counter
End If
End While
Else
'MsgBox("Something went wrong, Flame the coder of this program!!") 'Bug Testing code that is disabled
End If
Else
End If
If (sr.EndOfStream = True) Then
ReDim GlobalArr(CombatLogNames.Length - 1) 'Resizing the Global array to prime it for copying data
Array.Copy(CombatLogNames, GlobalArr, CombatLogNames.Length) 'Just copying the array to make it global
End If
Loop
You CAN set the BaseStream to the desired reading position, you just cant set it to a specfic LINE (because counting lines requires to read the complete file)
Using sw As New StreamWriter("foo.txt", False, System.Text.Encoding.ASCII)
For i = 1 To 100
sw.WriteLine("the quick brown fox jumps ovr the lazy dog")
Next
End Using
Using sr As New StreamReader("foo.txt", System.Text.Encoding.ASCII)
sr.BaseStream.Seek(-100, SeekOrigin.End)
Dim garbage = sr.ReadLine ' can not use, because very likely not a COMPLETE line
While Not sr.EndOfStream
Dim line = sr.ReadLine
Console.WriteLine(line)
End While
End Using
For any later read attempt on the same file, you could simply save the final position (of the basestream) and on the next read to advance to that position before you start reading lines.
What worked for me was skipping first 4M lines (just a simple if counter > 4M surrounding everything inside the loop), and then adding background workers that did the filtering, and if important added the line to an array, while main thread continued reading the lines. This saved about third of the time at the end of a day.

How do I use loops in VB.NET?

EDIT:
I have a ItemList : Dim ItemList As New List(Of String)
I wanna append each element from itemlist to a new list for 10 times each, then to start over again.
How can I make a loop for each element while there are still elements in the list (10 times each)?
I tried this but it's not working. it's too complicated for me cause I'm a newbie
Private crt As Integer = 0
Private limit As Integer = 0
Private Function getline() As String
Dim line As String = ""
SyncLock addlines
Do While limit < 10
line = ItemList(crt)
limit += 1
Loop
limit = 0
crt += 1
End SyncLock
addlines.AppendText(Environment.NewLine & line & " limit:" & limit & " crt:" & crt)
'Return line
End Function
thanks
I have also tried this:
For Each I As Item In Items
If I = x Then Continue For
' Do something
Next
but I didn't know where to add the 10 times limit and also the current item number(crt)
As best I can make out of that mess of a question, you seem to want to append each line in ItemList (whatever that object is) 10 times.
This should do the trick.
Dim limit as integer=10
For each line as string in ItemList
For lineNum as integer = 1 to limit
addlines.AppendText(string.format("{0}{1} Limit: {2} CRT:{3}", Environment.NewLine, line, limit, lineNum ))
Next lineNum
Next line
Update: Updated answer for explanation in comments about what CRT was.