Error saying file is already open when writing to a file - vb.net

I have a form with fields that i am saving to the text file.
On that same form I have a button that allows you to view what you saved prior from that text file
When i hit the button it reads the textfile and displays on a datagrid.
This code is what is displaying to the datagrid
Dim reader As StreamReader
reader = New StreamReader("C:\Users\John\Desktop\tickets.txt")
Dim a As String
Dim results() As String
Do
a = reader.ReadLine
results = a.Split(vbTab)
dgv.Rows.Add(results(0), results(1), results(2), results(3), results(4), results(5))
' Code here
'
Loop Until a Is Nothing
reader.Close()
reader.Dispose()
this code saves to the file
Dim file As StreamWriter
file = New StreamWriter("C:\Users\John\Desktop\tickets.txt", True)
file.WriteLine(txtname.Text & vbTab & dtdate.Text & vbTab & txttime.Text & vbTab & txtwho.Text & vbTab & txtproblem.Text & vbTab & txtresolution.Text)
file.Close()
When I read the records first then try to save them I keep getting the error the process cannot access the file because it is being used by another process.
I closed both the reader and writer, and am not sure why this is happeneing

Better code, are you sure your loop was ending?
Write:
Dim path As String = "C:\Users\John\Desktop\tickets.txt"
If File.Exists(path) Then
Using sw As New StreamWriter(path, True)
'code
End Using' closes and disposes for you
End If
Read:
Dim path As String = "C:\Users\John\Desktop\tickets.txt"
If File.Exists(path) Then
Dim results As New List(Of String)
Using sr As New StreamReader(path)
While Not sr.EndOfStream()
results.Add(sr.Readline())
'better than do loop
End While
End Using' closes and disposes for you
End If
For Each line In results
'add to DGV
Next

Related

How to Update CSV file not to Insert new Items using vb.net

I want to Update row of CSV file I tried but I only found append which adds new row. where as I need to update row not to insert new row.
Here is data in my csv file
EnjoyBaseHid=hid://002AB1E3,MinID=1,MaxID=900
EnjoyBaseHid=hid://005AC1D4,MinID=1,MaxID=600
I want to update according to EnjoyBaseHid
While Not sr.EndOfStream
Dim line = sr.ReadLine()
Dim values() As String = line.Split(",")
If values(0).Equals("EnjoyBaseHid=" & portAddress) Then
Nobasefound = False
line = line.Replace(values(1), "MinID=" & minID)
line = line.Replace(values(2), "MaxID=" & maxID)
sr.Close()
Dim strWrite As New IO.StreamWriter(ExportListPathString, False)
strWrite.WriteLine(line)
strWrite.Close()
Exit While
End If
End While
This overwrites all file and the result is
EnjoyBaseHid=hid://005AC1D4,MinID=1,MaxID=1000
When I change following line
Dim strWrite As New IO.StreamWriter(ExportListPathString, False)
To this
Dim strWrite As New IO.StreamWriter(ExportListPathString, True)
It appends new line and result is following
EnjoyBaseHid=hid://002AB1E3,MinID=1,MaxID=900
EnjoyBaseHid=hid://005AC1D4,MinID=1,MaxID=600
EnjoyBaseHid=hid://005AC1D4,MinID=1,MaxID=1000
But I need this
EnjoyBaseHid=hid://002AB1E3,MinID=1,MaxID=900
EnjoyBaseHid=hid://005AC1D4,MinID=1,MaxID=1000
This is the idea I had in mind.
Private Sub fileHandler(sourceFile As String, portAddress As String, newMin As String, newMax As String)
Dim tempOutFileName As String = String.Concat(sourceFile, "_tmp")
Dim oldFileName As String = String.Concat(sourceFile, "_old")
'clear away temp file
If File.Exists(tempOutFileName) Then
File.Delete(tempOutFileName)
End If
'clear away old file
If File.Exists(oldFileName) Then
File.Delete(oldFileName)
End If
'open writer for new temp file
Using sw As StreamWriter = New StreamWriter(tempOutFileName, True)
'open reader for source file
Using sr As StreamReader = New StreamReader(sourceFile)
Do While sr.Peek <> -1
Dim line As String = sr.ReadLine
'check if the line read is the one you want to change
If line.Contains(portAddress) Then
'write your NEW line
sw.WriteLine(String.Concat(portAddress, "-", newMin, "-", newMax))
Else
'write the existing line without changes
sw.WriteLine(line)
End If
Loop
sr.Close()
End Using
sw.Close()
End Using
'backup source to old
File.Move(sourceFile, oldFileName)
'move temp to source
File.Move(tempOutFileName, sourceFile)
End Sub

Saving data with a file name of my choice

Very kindly, an intelligent member of stack overflow showed me how to loop with 'Do Until' and generate messages boxes to enable a user to save a file or rename one, if it already exists. However, I'm still hitting a wall. I can't save the ListView data in my for loop, with the file name I have chosen in the Input Box (see code below). Its like I have two separate pieces of code because rtb is saving data in a Rich Text File called Test.txt and saveFile has nothing to do with this! Please help
Code
Dim fileSaved As Boolean
Do Until fileSaved
Dim saveFile As String = InputBox("Enter a file name to save this message")
If saveFile = "" Then Exit Sub
Dim docs As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments
Dim filePath As String = IO.Path.Combine(docs, "Visual Studio 2013\Projects", saveFile & ".txt")
fileSaved = True
If My.Computer.FileSystem.FileExists(filePath) Then
Dim msg As String = "File Already Exists. Do You Wish To Overwrite it?"
Dim style As MsgBoxStyle = MsgBoxStyle.YesNo Or MsgBoxStyle.DefaultButton2 Or MsgBoxStyle.Critical
fileSaved = (MsgBox(msg, style, "Warning") = MsgBoxResult.Yes)
End If
Loop
'THIS NEXT bit of code saves content to Test.txt NOT saveFile as desired!
Dim rtb As New RichTextBox
rtb.AppendText("Generation, Num Of Juveniles, Num of Adults, Num of Semiles, Total" & vbNewLine)
For Each saveitem As ListViewItem In ListView1.Items
rtb.AppendText(
saveitem.Text & ", " &
saveitem.SubItems(1).Text & ", " &
saveitem.SubItems(2).Text & ", " &
saveitem.SubItems(3).Text & ", " &
saveitem.SubItems(4).Text & vbNewLine)
Next
rtb.SaveFile("C:\Users\SMITH\Documents\Visual Studio 2013\Projects\Test.txt", _
RichTextBoxStreamType.PlainText)
When you try to save the file with the RichTextBox method SaveFile you need to be able to use the variable filePath that receive the input from your user. But this variable is declared inside the block Do Until .... Loop and according to scope rules of variables in VB.NET is not available outside that block. You could move the declaration of the variable before entering the loop
Dim fileSaved As Boolean
Dim filePath As String
Do Until fileSaved
Dim saveFile As String = InputBox("Enter a file name to save this message")
If saveFile = "" Then Exit Sub
Dim docs as String = My.Computer.FileSystem.SpecialDirectories.MyDocuments
filePath = IO.Path.Combine(docs, "Visual Studio 2013\Projects", saveFile & ".txt")
fileSaved = True
If My.Computer.FileSystem.FileExists(filePath) Then
Dim msg As String = "File Already Exists. Do You Wish To Overwrite it?"
Dim style As MsgBoxStyle = MsgBoxStyle.YesNo Or MsgBoxStyle.DefaultButton2 Or MsgBoxStyle.Critical
fileSaved = (MsgBox(msg, style, "Warning") = MsgBoxResult.Yes)
End If
Loop
' The remainder of your code can be left unchanged until the SaveFile line
Now you could use it in the call
rtb.SaveFile(filePath, RichTextBoxStreamType.PlainText)

How to replace multiple consective lines in a line and skip the header for that section

I need to find a section header, in this case "[Store Hours]", in a text file that I'm using to save the settings for the program. I need to skip the header and replace the next 7 lines with the text that is in the text boxes. The code below currently deletes the header "[Store Hours]" and does not replace any of the lines.
Dim objFileName As String = "Settings.txt"
Private Sub BtnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim OutPutLine As New List(Of String)()
Dim matchFound As Boolean
For Each line As String In System.IO.File.ReadAllLines(objFileName)
matchFound = line.Contains("[Store Hours]")
If matchFound Then
'does not skip the header line
line.Skip(line.Length)
'Need to loop through this 7 times (for each day of the week)
'without reading the header again
For intCount = 0 To 6
Dim aryLabelDay() As String = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
Dim varLabelNameIn As String = "txt" & aryLabelDay(intCount).ToString & "In"
Dim varDropNameIn As String = "drp" & aryLabelDay(intCount).ToString & "In"
Dim varLabelNameOut As String = "txt" & aryLabelDay(intCount).ToString & "Out"
Dim varDropNameOut As String = "drp" & aryLabelDay(intCount).ToString & "Out"
Dim varTextBoxInControl() As Control = Me.Controls.Find(varLabelNameIn, True)
Dim varDropBoxInControl() As Control = Me.Controls.Find(varDropNameIn, True)
Dim varTextBoxOutControl() As Control = Me.Controls.Find(varLabelNameOut, True)
Dim varDropBoxOutControl() As Control = Me.Controls.Find(varDropNameOut, True)
Dim dymTextNameIn As TextBox = DirectCast(varTextBoxInControl(0), TextBox)
Dim dymDropNameIn As ComboBox = DirectCast(varDropBoxInControl(0), ComboBox)
Dim dymTextNameOut As TextBox = DirectCast(varTextBoxOutControl(0), TextBox)
Dim dymDropNameOut As ComboBox = DirectCast(varDropBoxOutControl(0), ComboBox)
Dim ReplaceLine As String
ReplaceLine = dymTextNameIn.Text & "," & dymDropNameIn.Text & "," & dymTextNameOut.Text & "," & dymDropNameOut.Text
'this doesn't replace anything
line.Replace(line, ReplaceLine)
intCount += 1
Next intCount
Else
OutPutLine.Add(line)
End If
Next
End Sub
Instead of using ReadAllLines simply use a streamreader and read the file line by line, like this;
Dim line As String
Using reader As StreamReader = New StreamReader("file.txt")
' Read one line from file
line = reader.ReadLine
If(line.Contains("[Store Hours]") Then
'The current line is the store hours header, so we skip it (read the next line)
line = reader.ReadLine
'Process the line like you want, and keep processing through the lines by doing a readline each time you want to progress to the next line.
End If
End Using
More importantly though, you should not be saving the settings for your program in a text file. They should be stored in app.config or web.config. See this question for further guidance on that.
Part of your confusion might be coming from the fact that you can't just replace part of a text file without copying it and overwriting it. One way, to do this, is to copy the file to memory changing the appropriate lines and overwriting the existing file with the new information. Here's one way that can be done:
Private Sub BtnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim OutPutLine As New List(Of String)()
Dim sr As New StreamReader(objFileName)
While Not sr.EndOfStream
Dim line = sr.ReadLine
'Found the header so let's save that line to memory and add all the other _
info after it.
If line.Contains("[Store Hours]") Then
OutPutLine.Add(line)
'Need to loop through this 7 times (for each day of the week)
'without reading the header again
Dim aryLabelDay() As String = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
For intCount = 0 To 6
'even though we're not using the info from the file, calling _
Readline advances the file pointer so that the next iteration _
of the while loop we can finish reading the file.
If Not sr.EndOfStream Then
line = sr.ReadLine
Dim dymTextNameIn As TextBox = DirectCast(Me.Controls("txt" & aryLabelDay(intCount) & "In"), TextBox)
Dim dymDropNameIn As ComboBox = DirectCast(Me.Controls("drp" & aryLabelDay(intCount) & "In"), ComboBox)
Dim dymTextNameOut As TextBox = DirectCast(Me.Controls("txt" & aryLabelDay(intCount) & "Out"), TextBox)
Dim dymDropNameOut As ComboBox = DirectCast(Me.Controls("drp" & aryLabelDay(intCount) & "Out"), ComboBox)
OutPutLine.Add(dymTextNameIn.Text & "," & dymDropNameIn.Text & "," & dymTextNameOut.Text & "," & dymDropNameOut.Text)
End If
Next
Else
'Any line that isn't in that section gets copied as is.
OutPutLine.Add(line)
End If
End While
'Copy all the new info to the same file overwriting the old info.
File.WriteAllLines(objFileName, OutPutLine)
End Sub
On a side note. The Controls collection is indexed by number or name which makes it fairly simple to access the appropriate control just by knowing its name.
Thanks for the help I actually figured it out and this is the final code I used
Private Sub btnSaveHours_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim intOutPutLine As New List(Of String)()
Dim blnSearchString As Boolean
Dim intLineCount As Integer = -1
Dim intLoopCount As Integer
For Each line As String In System.IO.File.ReadAllLines(objFileName)
blnSearchString = line.Contains("[Store Hours]")
If blnSearchString Then
intLineCount = intOutPutLine.Count
line.Remove(0)
intLoopCount = 0
ElseIf intLineCount = intOutPutLine.Count And intLoopCount < 7 Then
line.Length.ToString()
line.Remove(0)
intLoopCount += 1
Else
intOutPutLine.Add(line)
End If
Next
System.IO.File.WriteAllLines(objFileName, intOutPutLine.ToArray())
Dim objFileWrite As New StreamWriter(objFileName, True)
If File.Exists(objFileName) Then
objFileWrite.WriteLine("[Store Hours]")
Dim varMe As Control = Me
Call subConvertFrom12to24Hours(objFileWrite, varMe)
Else
objFileWrite.WriteLine("[Store Hours]")
Dim varMe As Control = Me
Call subConvertFrom12to24Hours(objFileWrite, varMe)
End If
Call btnClear_Click(sender, e)
End Sub

Problems reading an Excel file in VB.net

I have been trying to upload and read an Excel file (.xls, or .xlsx)
I am upploading sucessfully using this code:
Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpload.Click
Dim filepath As String = ""
If FileUpload1.HasFile Then
Try
Dim filename As String = FileUpload1.PostedFile.FileName
Dim extension = (filename.Substring(filename.LastIndexOf("."), (filename.Length() - filename.LastIndexOf("."))))
If extension = ".xlsx" Or extension = ".xls" Then
filepath = "\" & Common.toUnix(Now) & "_" & filename
FileUpload1.SaveAs(Server.MapPath("~/") & filepath)
' ==== NOW READ THE FILE
Else
StatusLabel.InnerText = "Only Excel file types are accepted (.xls/.xlsx)<br> File Uploaded had extension: " & extension
End If
Catch ex As Exception
StatusLabel.InnerText = "Upload status: The file could not be uploaded. The following error occured: " + ex.ToString()
End Try
End If
End Sub
It uploads OK, but when trying to read the file I get this error:
System.Data.OleDb.OleDbException (0x80004005): The Microsoft Jet database engine cannot open the file ''. It is already opened exclusively by another user, or you need permission to view its data.
I am using code to read similar to this:
vb.net traversing an xls / xlsx file?
Therefore the connection is as follows:
Dim connString As String = "Provider=Microsoft.Jet.OLEDB.4.0" & _
";Data Source=" & ExcelFile & _
";Extended Properties=Excel 8.0;"
Dim conn As OleDbConnection = Nothing
Dim dt As System.Data.DataTable = Nothing
Dim excelDataSet As New DataSet()
Try
conn = New OleDbConnection(connString)
conn.Open() '<<< ERROR IS RAISED ON THIS LINE
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
If dt Is Nothing Then
Return Nothing
End If
Dim excelSheets(dt.Rows.Count) As String
Dim i As Integer = 0
For Each row As DataRow In dt.Rows
excelSheets(i) = row("payments").ToString
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
If i = SheetNumber Then
Exit For
End If
Next
..................
I'm uploading to a shared server so don't have control as to permissions as such, but I do have read/write permissions and uploading Images works OK, but it's reading this file that I can't get to work.
NOTE
This error occurs with .xls files, when using .xlsx I get this error:
System.Data.OleDb.OleDbException (0x80004005): Cannot update. Database or object is read-only. at System.Data.OleDb.OleDbConnectionInternal
This error occurs on this line:
For Each row As DataRow In dt.Rows
So it appears it is uplpoading and opening the file OK, but not reading the rows....
I am not sure why that's happening either!
Any help would be much appreciated!
ACE is brutal, have troubles with it all the time and it cannot exist on a System in both 32 and 64 bit version at the same time. As a result I just dont use it at all.
To read an Excel XLSX file I use "EPPlus" which has proven to be very easy to deal with and extreamly efficient.
It ONLY works with XLSX (not XLS)
Example... (simple just pulls out first sheet as a datatable)
Public Function XlsxToDataTable(byteStream As IO.MemoryStream) As DataTable
Using pac As New OfficeOpenXml.ExcelPackage(byteStream)
Dim wb As OfficeOpenXml.ExcelWorkbook = pac.Workbook
Dim ws As OfficeOpenXml.ExcelWorksheet = wb.Worksheets(1) '1 based
Dim out As New DataTable
For iC As Integer = 1 To ws.Dimension.End.Column
out.Columns.Add(ws.Cells(1, iC).Value.ToString)
Next
For iR As Integer = 2 To ws.Dimension.End.Row
Dim nr As DataRow = out.NewRow
For iC As Integer = 1 To ws.Dimension.End.Column
nr(iC - 1) = ws.Cells(iR, iC).Value
Next
out.Rows.Add(nr)
Next
Return out
End Using
End Function

VB.NET - Problems trying to write a textfile

I have problems when trying to delete/create/write to this file.
The error:
The process cannot access the file 'C:\Users\Administrador\AppData\Local\Temp\PlayList_temp.txt' because it is being used by another process.
The highlighted lines by debugger:
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
System.IO.File.Create(Temp_file)
(Any of two, if I delete one line, the other line takes the same error id)
The sub:
Public Sub C1Button2_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Not playerargs = Nothing Then
Dim Str As String
Dim Pattern As String = ControlChars.Quote
Dim ArgsArray() As String
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
Dim objWriter As New System.IO.StreamWriter(Temp_file)
Str = Replace(playerargs, " " & ControlChars.Quote, "")
ArgsArray = Split(Str, Pattern)
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
System.IO.File.Create(Temp_file)
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
For Each file In files
' command to writleline
'Console.WriteLine("File Name: {0}", file.Name)
'Console.WriteLine("File Full Name: {0}", file.FullName)
objWriter.Write(file.FullName)
objWriter.Close()
Next
End If
Next
If randomize.Checked = True Then
RandomiseFile(Temp_file)
End If
Process.Start(userSelectedPlayerFilePath, playerargs)
If autoclose.Checked = True Then
Me.Close()
End If
Else
MessageBox.Show("You must select at least one folder...", My.Settings.APPName)
End If
End Sub
First, File.Create creates or overwrite the file specified, so you don't need to Delete it before.
Second, initializing a StreamWriter as you do, blocks the file and therefore you can't recreate it after.
So, simply move the StreamWriter intialization after the File.Create, or better, remove altogether the File.Create and use the StreamWriter overload that overwrites the file
....
If Not playerargs = Nothing Then
....
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
Using objWriter As New System.IO.StreamWriter(Temp_file, false)
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
For Each file In files
' command to writleline
'Console.WriteLine("File Name: {0}", file.Name)
'Console.WriteLine("File Full Name: {0}", file.FullName)
objWriter.Write(file.FullName)
' objWriter.Close()
Next
End If
Next
End Using ' Flush, close and dispose the objWriter
....
Noticed also that you close the writer while still inside the loop, use the Using statement to close correctly the writer after the work is done.
The process cannot access the file 'C:\Users\Administrador\AppData\Local\Temp\PlayList_temp.txt' because it is being used by another process.
That means the file is opened or been used by another process.
Open your task manager and check if the file is there, then close it or simplex end the process.
I have had the same issue but I got it solved by closing the file.
Hope this helps!
From your details it seems that you are willing to delete if file exists and creates a new one.
I would suggest to remove this line:
System.IO.File.Create(Temp_file)
and move this line just over the streamwriter line:
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
Something like this would help you:
Partial code:
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
' Delete file if exists
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
' Create file for write.
Dim objWriter As New System.IO.StreamWriter(Temp_file)
Str = Replace(playerargs, " " & ControlChars.Quote, "")
ArgsArray = Split(Str, Pattern)
...
...
...