I have created a form to write data to a text file and to read the data from the text file. The program is working fine, if I run the program and write data to text file. The data is saved to the file. Then I stop the program and re-run it and now read the data from the file, the text data is also shown in the corresponding text box.
But the problem occurs when I write the data to the text file and then try to read the data from the text file without re-running the program. Now in this case, it shows error: Stream was not readable.
Why is it so?
Imports System.IO
Public Class Form1
Dim fileStream_ As FileStream
Dim fileWrite_ As StreamWriter
Dim fileRead_ As StreamReader
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
fileStream_ = New FileStream("C:\Users\USER\Desktop\demo\vb.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
' for WRITE data to text file
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
fileWrite_ = New StreamWriter(fileStream_)
fileWrite_.Write(TextBox1.Text)
fileWrite_.Close()
MsgBox("Text written to file", MsgBoxStyle.Information)
TextBox1.Text = ""
TextBox2.Text = ""
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
' for READ data from text file
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
fileRead_ = New StreamReader(fileStream_)
TextBox2.Text = fileRead_.ReadToEnd
fileRead_.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
End Class
CodePudding user response:
Do not keep these global variables around because you don't really need them.
And they can shoot in your feet when, for some reason they are no more valid.
Your's is an example case where global variables introduce subtle and not evident bugs. When you close the StreamWriter the fileStream_ variable is automatically disposed and, in the next button click, is no more usable.
Of course if you close/reopen the application and go directly to read the file, it works. But then, it will be the write that will fail.
Instead use the Using statement to correctly handle all disposable objects like a StreamWriter, StreamReader or FileStream
So your click handlers could be rewritten as
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Using fileStream_ As FileStream = New FileStream("C:\Users\USER\Desktop\demo\vb.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)
Using fileWrite_ As StreamWriter = New StreamWriter(fileStream_)
fileWrite_.Write(TextBox1.Text)
' the call to close is no more needed when inside the using
' fileWrite_.Close()
MsgBox("Text written to file", MsgBoxStyle.Information)
TextBox1.Text = ""
TextBox2.Text = ""
End Using
End Using
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
Using fileStream_ As FileStream = New FileStream("C:\Users\USER\Desktop\demo\vb.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)
Using fileRead_ As StreamReader = New StreamReader(fileStream_)
TextBox2.Text = fileRead_.ReadToEnd
End Using
End Using
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
But, unless you have some valid reasons for these Streams to exist, then you can code everything with a single statement.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
File.WriteAllText("C:\Users\USER\Desktop\demo\vb.txt", TextBox1.Text)
MsgBox("Text written to file", MsgBoxStyle.Information)
TextBox1.Text = ""
TextBox2.Text = ""
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
TextBox2.Text = File.ReadAllText("C:\Users\USER\Desktop\demo\vb.txt")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
The File class has many useful methods when you need to work with files
CodePudding user response:
While you close the writer, the underlying steam also gets closed, you need to create a new instance of the stream if you need to read from the same file.
Ref: https://docs.microsoft.com/en-us/dotnet/api/system.io.streamwriter.close?view=net-6.0
Imports System.IO
Public Class Form1
Dim fileStream_ As FileStream
Dim fileWrite_ As StreamWriter
Dim fileRead_ As StreamReader
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
' for WRITE data to text file
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
fileStream_ = New FileStream("C:\Users\USER\Desktop\demo\vb.txt", FileMode.OpenOrCreate, FileAccess.Write)
fileWrite_ = New StreamWriter(fileStream_)
fileWrite_.Write(TextBox1.Text)
fileWrite_.Close()
MsgBox("Text written to file", MsgBoxStyle.Information)
TextBox1.Text = ""
TextBox2.Text = ""
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
' for READ data from text file
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
fileStream_ = New FileStream("C:\Users\USER\Desktop\demo\vb.txt", FileMode.OpenOrCreate, FileAccess.Read)
fileRead_ = New StreamReader(fileStream_)
TextBox2.Text = fileRead_.ReadToEnd
fileRead_.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
End Class
I would also suggest you to wrap the stream using 'Using' statement in order to better manage the resource