Read the whole file into an array, replace one of the elements of that array, then write the whole file again. Text ends up the same - vb.net

I have a form3 that when the user exits it attempts to save the time they spent playing. When trying to replace the line I end up with the exact same text, therefore nothing changes in the file. Why will it not replace the text? Thanks in advance.
File.AppendAllLines(Application.StartupPath + "\content\main\userdata\tgametime.txt", FileLines)
'this line will not write to file if it has the same file name because FileLines is still using it, if this could be solved too awesome!
Private Sub SaveGameTime()
Dim fullpath = Path.Combine(Application.StartupPath + "\content\main\userdata\gametime.txt")
Dim FileLines = File.ReadLines(fullpath)
Dim alltext = File.ReadAllText(fullpath)
Dim datalist = New List(Of String)
Dim line
datalist.Add(tbGameName.Text + " : " + LBtimeout.Text)
TextDiag(FileLines.Count.ToString, "Clear")
If FileLines.Count > 0 Then
If alltext.Contains(tbGameName.Text) Then
For Each line In FileLines
TextDiag(line, "Clear")
line.Replace(line, tbGameName.Text + " : " + LBtimeout.Text)
TextDiag("new line: " + line, "Clear")
Next
File.AppendAllLines(Application.StartupPath + "\content\main\userdata\tgametime.txt", FileLines)
Else
TextDiag("Line not found, adding new line", "Clear")
File.AppendAllLines(fullpath, datalist)
End If
Else
TextDiag("No lines not found, adding new line", "Clear")
File.AppendAllLines(fullpath, datalist)
End If
datalist.Clear()
fullpath = Nothing
FileLines = Nothing
datalist = Nothing
TextDiag Output

Got it working, replaces text at a specified string value in a file formatted like this: "Text > 0 : 0 : 0" . It gets a new time value extracted from a label formatted like this: "0 : 0 : 0", removes everything but the numbers and colons to this: "0:0:0", formats them to a TimeSpan and adds them to the outputlines which also contain any other original text.
Thank you
Dim fullpath = "yourpath"
Dim FileLines = File.ReadLines(fullpath)
Dim outputlines As New List(Of String)
Dim alltext = File.ReadAllText(fullpath)
Dim datalist = New List(Of String)
Dim line
Dim lbtime = TimeSpan.Parse(LBtimeout.Text.Replace(" ", ""))
datalist.Add("youstring" + " : " + "yourstring")
If FileLines.Count > 0 Then
If alltext.Contains("yourstring") Then
For Each line In FileLines
If line.contains("yourstring") Then
Dim liness = line.substring(line.indexof(">") + 1)
Dim linerep = liness.replace(" ", "")
Dim linetime = TimeSpan.Parse(linerep)
Dim timesum As TimeSpan = lbtime + linetime
line.replace(line, "")
line = "yourstring" + " > " + timesum.ToString
outputlines.Add(line)
Else
outputlines.Add(line)
End If
Next
File.WriteAllLines("yourpath", outputlines)
Else
File.AppendAllLines(fullpath, datalist)
End If
Else
'No lines not found, adding new line
File.AppendAllLines(fullpath, datalist)
End If
datalist.Clear()
fullpath = Nothing
FileLines = Nothing
datalist = Nothing

Related

find character and Insert a new line in the file

I am looking to read a file line by line and once I reach a line that doesn't contain the same characters in columns 65 - 67 I want to insert a string line 2 lines above that. I am using VB.NET
So far I have written code that reads the file line by line.
I am unsure how to insert a string line to a file where characters in columns 65-67 are different
any help would be great. Thanks
Protected Sub UploadFile(sender As Object, e As EventArgs)
Dim fileName As String = Path.GetFileName(FileUpload1.PostedFile.FileName)
Dim filePath As String = Server.MapPath("~/Files/") & fileName
FileUpload1.SaveAs(filePath)
'--Read block of lines then insert line for each new block
For Each line In IO.File.ReadLines(filePath)
'If line.Substring(65, 3) <> " " Then '<> to previous substring
'--Insert new line
'End If
Next
End Sub
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" Text="Upload File" runat="server" OnClick="UploadFile" />
Something like this.
Dim lines As List(Of String) = IO.File.ReadLines(filePath).ToList
Dim idx As Integer = 0
Do While idx < lines.Count - 2
Dim thisLine As String = lines(idx)
Dim nextLine As String = lines(idx + 1)
If thisLine.Substring(65, 3) <> nextLine.Substring(65, 3) Then
lines.Insert(idx + 1, "NEW BLOCK")
idx += 1
End If
idx += 1
Loop
Dim foo As String = String.Join(ControlChars.Cr, lines)
IO.File.WriteAllText("path", foo)
edit - based on comments
Dim lines As List(Of String) = IO.File.ReadLines(filePath).ToList
Dim idx As Integer = 0
Do While idx < lines.Count - 2
Dim thisLine As String = lines(idx)
Dim nextLine As String = lines(idx + 1)
Dim key As String = thisLine.Substring(65, 3).Trim
If key <> nextLine.Substring(65, 3) AndAlso
key = "" Then
lines.Insert(idx + 1, "NEW BLOCK")
idx += 1
End If
idx += 1
Loop
Dim foo As String = String.Join(ControlChars.Cr, lines)
IO.File.WriteAllText("path", foo)

How to remove extra line feeds within double quoted fields

Newbie here. Code below removes ALL line feeds in my file but it also removes EOR line feeds. Can somebody please help me how to fix code below so it only removes extra line feeds within double quoted fields? Any help will be greatly appreciated. Thanks
Public Sub Main()
'
Dim objReader As IO.StreamReader
Dim contents As String
objReader = New IO.StreamReader("testfile.csv")
contents = objReader.ReadToEnd()
objReader.Close()
Dim objWriter As New System.IO.StreamWriter("testfile.csv")
MsgBox(contents)
'contents = Replace(contents, vbCr, "")
contents = Replace(contents, vbLf, "")
MsgBox(contents)
objWriter.Write(contents)
objWriter.Close()
'
Dts.TaskResult = ScriptResults.Success
End Sub
I forgot to mention that the input file name changes daily, How do I code so it doesn't care for the file name as long as it as a CSV file? So testfile name has current date and changes daily. I've tried just the file path and it errored out as well. Used the *.csv and it didnt like that either.
objReader = New IO.StreamReader("\FolderA\FolderB\TestFile09212022.csv")
If you are sure there are no double quotes text inside the double quotes you can do it like this:
Dim sNewString As String = ""
Dim s As String
Dim bFirstQuoted As Boolean = False
Dim i As Integer
Dim objWriter As New System.IO.StreamWriter("testfile.csv")
MsgBox(contents)
For i = 1 To contents.Length
s = Mid(contents, i, 1)
If s = """" Then bFirstQuoted = Not bFirstQuoted
If Not bFirstQuoted OrElse (s <> vbLf AndAlso bFirstQuoted) Then
sNewString += s
else
sNewString += " "
End If
Next
MsgBox(sNewString )
objWriter.Write(sNewString )
objWriter.Close()
Dts.TaskResult = ScriptResults.Success

This code is supposed to output the number of times a word starts with a letter from the alphabet, but just displays zero for each one

This code is supposed to output the number of times a word starts with a letter from the alphabet, but just displays zero for each one
I get no errors, but just a text file with all of the letters and zero for each one.
When pressing the debug button, it appears to do nothing. Here's the code
Imports System.IO
Module Module1
Sub Main()
Dim myArray As New List(Of String)
Using myReader As StreamReader = New StreamReader(".\myFile.txt")
'telling VB that we're using a StreamREader, read a line at a time
Dim myLine As String
myLine = myReader.ReadLine 'assigns the line to String Variable myLine
Do While (Not myLine Is Nothing)
myArray.Add(myLine) 'adding it to the list of words in the array
Console.WriteLine(myLine)
myLine = myReader.ReadLine
Loop
End Using
SortMyArray(myArray) 'Calls the new SubRoutine => SortMyArray, passing through the parameter myArray,
'created back on line 7 that stores all of the lines read from the text file.
'Console.ReadLine()
wordCount(myArray)
End Sub
Sub SortMyArray(ByVal mySort As List(Of String))
Dim Tmp As String, writePath As String = ".\sorted.txt"
Dim max As Integer = mySort.Count - 1
Dim myWriter As StreamWriter = New StreamWriter(writePath)
For Loop1 = 0 To max - 1
For Loop2 = Loop1 + 1 To max
If mySort(Loop1) > mySort(Loop2) Then
Tmp = mySort(Loop2)
mySort(Loop2) = mySort(Loop1)
mySort(Loop1) = Tmp
End If
Next
myWriter.WriteLine(mySort.Item(Loop1).ToString())
Next
myWriter.Dispose()
End Sub
Sub wordCount(ByVal stringArray As List(Of String))
Dim alphabet As String = "abcdefghijklmnopqrstuvwxyz", myString As String
Dim writePath As String = ".\counted.txt"
Dim myWriter As StreamWriter = New StreamWriter(writePath)
Dim countOf(25) As Integer, Max As Integer = stringArray.Count - 1
For Loop1 = 0 To 25
myString = alphabet.Substring(Loop1, 1)
For Loop2 = 0 To Max
If stringArray(Loop2).Substring(0, 1) = myString Then
countOf(Loop1) += 1
End If
Next
myWriter.WriteLine(myString & " occured " & countOf(Loop1) & " times ")
Next
myWriter.Dispose()
End Sub
End Module
Any help would be appreciated. Thanks

Formatting text output from DataGridView in vb.net

I'm writing the values of two (1 column) DGVs and a text box to a text file. The text box value is the heading, DGV1 is a column of strings (such as SI CA S C...etc) and DGV2 is a column of numbers of the format 11.23 or 0.01. The formats are exactly how I want them as displayed in the DGVs, but that formatting doesn't carry over to the text file these values are output to. Here's what I want the textfile to look like:
A012345 101 1.03
SI 32.13
C 1.45
CA 0.03
Here's what I'm getting instead:
A012345 101 1.03
SI32.13015
C1.452359
CA0.032568
Here's the code:
Try
Dim da, da2 As OleDbDataAdapter
Dim ds, ds2 As DataSet
'open connection to nit2.xlsm'
Dim cn As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=""" & TextBox2.Text & """;Extended Properties=""Excel 12.0;HDR=YES;""")
'Fill dataviewgrid1 with element symbols, string, once'
da = New OleDbDataAdapter("select * from [Sheet1$A:A" & lastrow & "]", cn)
ds = New System.Data.DataSet
da.Fill(ds)
DataGridView1.DataSource = ds.Tables(0)
'''''''''''''loop through each sample and write to text file'''''''''''''''''''''''
da2 = New OleDbDataAdapter("select * from [Sheet1$B:B" & lastrow & "]", cn)
ds2 = New System.Data.DataSet
da2.Fill(ds2)
DataGridView2.DataSource = ds2.Tables(0)
'write sample heading to textbox1, looped'
TextBox1.Text = "Q0" & xlWsheet1.Cells(1, 2).Value & " " & xlWsheet2.Cells(1, 2).Value
'write to text file each data analysis point with formatted heading, looped'
Dim title As String = TextBox1.Text
Dim sub_title As String = title.Substring(0, 16)
Using writer As New System.IO.StreamWriter(fName, True)
writer.WriteLine(sub_title) 'heading'
Dim symbol, SymbolT As String
Dim compo As String
For cell1 As Integer = 0 To (DataGridView1.Rows.Count - 2)
symbol = Me.DataGridView1(0, cell1).Value 'element symbol'
symbolT = symbol.Trim
compo = Me.DataGridView2(0, cell1).Value 'composition'
writer.WriteLine(symbolT & compo)
Next
writer.Close()
End Using
cn.Close()
How can I format the numbers from DGV2 so that they only display to 2 decimals?
I also need to set the spacing between SI and 32.13 (for example) so that the decimal points in each line line up.
Formatting...anyone?
Something like this ?
Dim symbol As String
Dim compo As String
Dim symbolSpan As Integer = 0 ' stores the MaxLength of symbol
Dim compoSpan As Integer = 0 ' stores the Max Integer Part Length of compo
Dim symbolList As New List(Of String) ' all trimmed symbol
Dim compoList As New List(Of String) ' all trimmed compo
Dim compoIntLengthList As New List(Of Integer)
Dim doubleValue As Double
Dim i As Integer
Dim j As Integer
For i = 0 To (DataGridView1.Rows.Count - 2)
' element symbol...
symbol = Me.DataGridView1(0, i).Value.ToString().Trim()
symbolList.Add(symbol)
If symbol.Length > symbolSpan Then
symbolSpan = symbol.Length
End If
' composition...
If Double.TryParse(Me.DataGridView2(0, i).Value.ToString().Trim(), doubleValue) Then
compoList.Add(doubleValue.ToString("R"))
' well, the ToString("R") is not really the displayed value.
' if your DGV allows scientific display for Double then
' you'll have to handle that here with another code...
compo = doubleValue.ToString("F0") ' gets the Integer part length...
compoIntLengthList.add(compo.Length)
If compo.Length > compoSpan Then
compoSpan = compo.Length
End If
Else
' ohhhh ! the Cell doesn't contain a valid number... :/
compo = Me.DataGridView2(0, i).Value.ToString().Trim()
compoList.Add(compo)
If compo.Contains(".") Then ' Watch out culture about dots and commas...
If compoSpan < compo.IndexOf("."c) Then
compoSpan = compo.IndexOf("."c)
End If
compoIntLengthList.add(compo.IndexOf("."c))
Else
If compoSpan < compo.Length Then
compoSpan = compo.Length
End If
compoIntLengthList.add(compo.Length)
End If
End If
Next
symbolSpan = symbolSpan + 1 ' space between symbol and compo.
Using writer As New System.IO.StreamWriter(fName, True)
writer.WriteLine(sub_title) 'heading'
For i = 0 To symbolList.Count - 1
symbol = symbolList.Item(i)
While symbol.Length < symbolSpan
symbol = symbol + " "
End While
compo = compoList.Item(i)
j = compoIntLengthList.Item(i)
While j < compoSpan
compo = " " + compo
j = j + 1 ' this is what was causing the endless loop.
End While
writer.WriteLine(symbol & compo)
Next
symbolList.Clear()
symbolList= Nothing
compoList.Clear()
compoList = Nothing
compoIntLengthList.Clear()
compoIntLengthList = Nothing
writer.Close()
End Using
I haven't tested the code. Just written it on the fly.. The approach looks ugly (and I agree) but that's one way I remember so far. Could be better with String.Format or StringBuilder I guess but don't remember well how those ones works, sorry.
EDIT : Missed the two decimals part...
Oh, sorry ! You want only two decimals.. Replace this :
compoList.Add(doubleValue.ToString("R"))
by this :
compoList.Add(doubleValue.ToString("F2"))
' or this :
compoList.Add(doubleValue.ToString("#.##")) ' to allow 0 or 1 decimal aswell
and replace this part :
' ohhhh ! the Cell doesn't contain a valid number... :/
compo = Me.DataGridView2(0, i).Value.ToString().Trim()
compoList.Add(compo)
If compo.Contains(".") Then ' Watch out culture about dots and commas...
If compoSpan < compo.IndexOf("."c) Then
compoSpan = compo.IndexOf("."c)
End If
compoIntLengthList.add(compo.IndexOf("."c))
Else
If compoSpan < compo.Length Then
compoSpan = compo.Length
End If
compoIntLengthList.add(compo.Length)
End If
by this :
' ohhhh ! the Cell doesn't contain a valid number... :/
compo = Me.DataGridView2(0, i).Value.ToString().Trim()
If compo.Contains(".") Then ' Watch out culture about dots and commas...
If compoSpan < compo.IndexOf("."c) Then
compoSpan = compo.IndexOf("."c)
End If
If compo.Length > (compo.IndexOf("."c) + 3) Then
compo = compo.SubString(0, compo.IndexOf("."c) + 3)
End If
compoIntLengthList.add(compo.IndexOf("."c))
Else
If compoSpan < compo.Length Then
compoSpan = compo.Length
End If
compoIntLengthList.add(compo.Length)
End If
compoList.Add(compo)

Reading Text line by line to make string manipulation

So to start this is the code I have already written:
Dim MyFile As String = "Path"
Dim str_new As String
Dim str_old As String = File.ReadAllText(MyFile)
Dim sr As New StreamReader(MyFile)
Dim strLines As String() = Strings.Split(sr.ReadToEnd, Environment.NewLine)
Dim Character As Integer = 5 'Line 1 always has 5 characters
For i = 2 To strLines.Length
Dim PreviousLine As String = sr.ReadLine(i - 1)
Dim CurrentLine As String = sr.ReadLine(i)
If CurrentLine.Contains(TextBox1.Text / 100) Then
If PreviousLine.Contains("divide") Then
Exit For
End If
End If
Character = Character + CurrentLine.Length
Next
sr.Close()
str_new = Replace(str_old, (TextBox1.Text / 100), (TextBox3.Text / 100), Character, 1)
Dim objWriter3 As New System.IO.StreamWriter(MyFile, False)
objWriter3.Write(str_new)
objWriter3.Flush()
objWriter3.Close()
I am trying to figure out a way to break a long code file into lines then check each line for certain strings. If the current line contains the string then I will do additional check on above and/or below lines to make sure This is the correct instance of the string. Finally I want to replace just that instance of the string with a different string.
An example: text file
class
...
0.3
divide <-- Previous Line
0.3 <-- TextBox1.Text is 30
.5
end
I want the code to go past the first instance of 0.3
Find the second instance
Check previous line for divide
Exit Loop
Replace second instance of 0.3 to some value
I have been looking into this for a while now and any help would be greatly appreciated!
~Matt
Revised: Code
Dim MyFile As String = "Path"
Dim NewFile As String = "Temporary Path"
Dim PreviousLine As String = ""
Dim CurrentLine As String = ""
Using sr As StreamReader = New StreamReader(MyFile)
Using sw As StreamWriter = New StreamWriter(NewFile)
CurrentLine = sr.ReadLine
Do While (Not CurrentLine Is Nothing)
Dim LinetoWrite = CurrentLine
If CurrentLine.Contains(TextBox1.Text) Then
If PreviousLine.Contains("divide") Then
LinetoWrite = Replace(CurrentLine, TextBox1.Text, TextBox3.Text)
End If
End If
sw.WriteLine(LinetoWrite)
PreviousLine = CurrentLine
CurrentLine = sr.ReadLine
Loop
End Using
End Using
My.Computer.FileSystem.CopyFile(NewFile, MyFile, True)
You are facing the problem in the wrong way. You have to set both, reader and writer, and generate a new file with all the modifications. Your code has various parts which should be improved; in this answer, I am just showing how to use StreamReader/StreamWriter properly. Sample code:
Dim MyFile As String = "input path"
Dim OutputFile As String = "output path"
Dim PreviousLine As String = ""
Dim CurrentLine As String = ""
Using sr As StreamReader = New StreamReader(MyFile)
Using sw As StreamWriter = New StreamWriter(OutputFile)
CurrentLine = sr.ReadLine
Do While (Not CurrentLine Is Nothing)
Dim lineToWrite = CurrentLine
'Perform the analysis you wish by involving the current line, the previous one and as many other (previous) lines as you wish; and store the changes in lineToWrite. You should call a function here to perform this analysis
sw.WriteLine(lineToWrite) 'Writing lineToWrite to the new file
PreviousLine = CurrentLine 'Future previous line
CurrentLine = sr.ReadLine 'Reading the line for the next iteration
Loop
End Using
End Using