Streamwriter not adding text to file? - vb.net

I have the following code:
If line = Nothing Then
MsgBox("Login failed.")
Using sw As New StreamWriter(File.Open(Index.strLogPath, FileMode.OpenOrCreate)) ' open or create a new file at our path
sw.BaseStream.Seek(0, SeekOrigin.End) ' append new users to the end
sw.AutoFlush = True
sw.WriteLine("line is nothing")
sw.Flush()
sw.Close()
End Using
End If
My line = nothing condition is met, the msgbox pops up letting me know, but the file is not created. If the file is there, nothing is added to it.
I have checked the path validity, and ensured that applications have permission there, everything I can think of isn't working, and to make it more frustrating there are no errors! Any help would be greatly appreciated.

Did you know that the File class already has a utility method to do exactly that?
File.AppendAllText(Index.strLogPath, "line is nothing")
Should be as simple as that. :)
EDIT
If you insist on managing the file stream yourself, try this:
Using sw As New StreamWriter(File.Open(Index.strLogPath, FileMode.Append)) ' open or create a new file at our path
sw.WriteLine("line is nothing")
End Using
Points of interest:
Use FileMode.Append instead of OpenOrCreate
No need to flush or close. This is done automatically when you leave the "using" block.

Related

Log Writer not creating new line for each entry

I get the feeling this is something really simple, but I've tried I don't know how many permutations of vbNewLine, Environment.NewLine, sMessage & vbNewLine (or Environment.Newline) I've tried, or how many pages on this site, or through Google I've looked at but nothing has worked.
I even tried getting help from a VB.Net discord channel I'm a part of and they suggested to do the same things that I've done and the procedure is still writing each new log entry at the end of the previous one in a continuous string. My writer is below. Am I missing something simple?
Edit: The code that worked is below in case anyone else comes along with the same issue. If you want to see the original code it's in the edit log.
Option Explicit On
Imports System.IO
Public Class WriteroLog
Public Shared Sub LogPrint(sMessage As String)
Dim AppPath As String = My.Application.Info.DirectoryPath
If File.Exists($"{AppPath}\Log.txt") = True Then
Try
Using objWriter As StreamWriter = File.AppendText($"{AppPath}\Log.Txt")
objWriter.WriteLine($"{Format(Now, "dd-MMM-yyyy HH:mm:ss")} – {sMessage}")
objWriter.Close()
End Using
Catch ex As Exception
MsgBox(ex)
Return
End Try
Else
Try
Using objWriter As StreamWriter = File.CreateText($"{AppPath}\Log.Txt")
objWriter.WriteLine($"{Format(Now, "dd-MMM-yyyy HH:mm:ss")} – {sMessage}")
objWriter.Close()
End Using
Catch ex As Exception
MsgBox(ex)
Return
End Try
End If
End Sub
End Class
The File.AppendText() method creates a new StreamWriter that is then used to append Text to the specified File.
Note, reading the Docs about this method, that you don't need to verify whether the File already exists: if it doesn't, the File is automatically created.
As a side note, when creating a Path, it's a good thing to use the Path.Combine method: it can prevent errors in the path definition and handles platform-specific formats.
Your code could be simplified as follows:
Public Shared Sub LogPrint(sMessage As String)
Dim filePath As String = Path.Combine(Application.StartupPath, "Log.Txt")
Try
Using writer As StreamWriter = File.AppendText(filePath)
writer.WriteLine($"{Date.Now.ToString("dd-MMM-yyyy HH:mm:ss")} – {sMessage}")
End Using
Catch ex As IOException
MsgBox(ex)
End Try
End Sub
The File.CreateText does not assign result to "objWrite", should be:
objWriter = File.CreateText($"{AppPath}\Log.Txt")
Not really sure if this is the root of your problem, but it is an issue.
In essences, your logic is re-opening or creating the stream "objWriter" for every call to this method. I would recommend you initialize "objWriter" to Nothing and only define if it is Nothing.
Set to Nothing as below.
Shared objWriter As IO.StreamWriter = Nothing
Then add check for Nothing in logic.

Hangman System.IO.IOException' occurred in mscorlib.dll

i am creating a hangman game that is to be used on a few computers, i have created the hangman game itself but i am using the "load form" function to create the list when the program first starts, but i am having this issue.
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'h:\Bryson\words.txt' because it is being used by another process.
Using sw As StreamWriter = File.CreateText("h:\Bryson\words.txt")
^^that line is where the error pops up^^
I have inserted some in code Comments to make life easier. If anyone can help thanks in advance :)
'USED TO CREATE HANGMAN FILE IF NOT FOUND
Private Sub main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
fofound = False
fifound = False
MsgBox("remove this and change file path and fix qu2 quiz")
'DESIGNER USE
Dim path As String = "h:\Bryson\words.txt"
'CREATE VAR FOR PATH
If System.IO.Directory.Exists("h:\Bryson") Then
'CHECKS IF FOLDER EXISTS
fofound = True
Else
'IF IT DOES THEN IT MOVES ON
System.IO.Directory.CreateDirectory("h:\Bryson")
'IF NOT IT CREATES THE FOLDER
fofound = True
If File.Exists("h:\Bryson\test\words.txt") Then
'CHECKS IF FILE EXISTS
fifound = True
Else
'IF IT DOES IT MOVES ON
IO.File.Create("h:\Bryson\words.txt")
'IF NOT IT CREATES IT
FileClose()
End If
End If
If fofound And fifound = True Then
Else
Using sw As StreamWriter = File.CreateText("h:\Bryson\words.txt")
'CRASH POINT The process cannot access the file 'C:\Bryson\words.txt'
'because it Is being used by another process.
sw.WriteLine("Hangman")
sw.WriteLine("computer")
sw.WriteLine("electrode")
sw.WriteLine("independent")
sw.WriteLine("stream")
sw.WriteLine("enforcing")
End Using
'WRITES TO FILE
MsgBox("file created")
'DESIGNER USE
FileClose()
'CLOSES FILE
End If
End Sub
FileClose() is a legacy function from VB6 and will not affect anything in the System.IO namespace. To close a file you need to call .Close() or .Dispose() on the stream that has opened the file (wrapping the stream in a Using block does this automatically).
Your problem is this line:
IO.File.Create("h:\Bryson\words.txt")
The method creates a new file and opens a FileStream to it which locks the file. Since you never close the returned FileStream your file will remain locked until you close your application.
The File.Create() call is completely unnecessary though because File.CreateText() will create the file if it doesn't exist. So you should just remove the above line.

Null Reference Exception when reading file vb.NET

So I am creating a program that needs to be able to read line by line from a .cfg (config) file, it can open it happily; here is the code:
OpenConfig.ShowDialog()
file = OpenConfig.FileName()
fileReader()
However when it tries to read the file, using this code:
Function fileReader()
Dim reader As New StreamReader(file)
Dim vLb As ListBox = shopTabs.SelectedTab.Controls.Item(10) 'Listbox Variable
For i = 0 To reader.Peek
textline(i) = reader.ReadLine()
vLb.Items.Add(i)
Next
Return True
End Function
It throws an exception at the line:
textline(i) = reader.ReadLine()
Any help would be greatly appreciated as I can't work out why it does so.
Your code could be simplified into the following code:
Using openConfig As New OpenFileDialog()
If openConfig.ShowDialog(Me) = DialogResult.OK Then
For Each s As String In File.ReadAllLines(openConfig.FileName)
ListBox1.Items.Add(s)
Next
End If
End Using
As I commented, your code does some things that are highly questionable and undoubtedly difficult to maintain, such as referencing a control by the index property.
I suspect that your project would benefit from using UserControls too, since I'm guessing you have the same controls placed in every tab (a ListBox is always control index #10?).

How do I output to a text file without getting an IO exception?

I have this code.
Dim txtVern As String = String.Empty
Try
Using verSR As New StreamReader(appDataVersionLoc)
txtVern = verSR.ReadToEnd()
End Using
Catch ex As Exception
Dim verFile As System.IO.FileStream
verFile = System.IO.File.Create(appDataVersionLoc)
Dim wWFERes As DialogResult = MessageBox.Show("Version file missing/corrupt, created a new one.")
If My.Computer.FileSystem.FileExists(appDataVersionLoc) Then
My.Computer.FileSystem.WriteAllText(appDataVersionLoc, "0.0.0.0", True)
End If
End Try
But when it tries to execute My.Computer.FileSystem.WriteAllText(appDataVersionLoc, "0.0.0.0", True), I get this error:
The process cannot access the file 'C:\Users\Dubstaphone\AppData\Roaming\TheArena\version.txt' because it is being used by another process.
How to I avoid this? What I did was I made it create a text file called "version.txt" if it doesn't already exist. Now I'm trying to write "0.0.0.0" to it, but it's giving me that error. By the way, "appDataVersionLoc" equals GetFolderPath(SpecialFolder.ApplicationData) & "\TheArena\version.txt"
This variable works fine for everything else.
Thanks!
P.S.
I'm a complete noob.
System.IO.File.Create or My.Computer.FileSystem.WriteAllText may still hold a lock on the file. Use the System.IO.File WriteAllText and a Using statement.
If you use a Stream you should close/dispose of it. Better yet when dealing with files always use a Using statement.
Edit:
Example of creating a file
Using File.Create(path)
End Using
If File.Exists(appDataVersionLoc) Then
File.WriteAllText(appDataVersionLoc, "0.0.0.0")
End If
or
Dim appDataFile = File.Create(path)
appDataFile.Close

VB.NET Checking if a File is Open before proceeding with a Read/Write?

Is there a method to verify that a file is open? The only thing I can think of is the Try/Catch to see if i can catch the file-open exception but I figured that a method be available to return true/false if file is open.
Currently using System.IO and the following code under class named Wallet.
Private holdPath As String = "defaultLog.txt"
Private _file As New FileStream(holdPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
Private file As New StreamWriter(_file)
Public Function Check(ByVal CheckNumber As Integer, ByVal CheckAmount As Decimal) As Decimal
Try
file.WriteLine("testing")
file.Close()
Catch e As IOException
'Note sure if this is the proper way.
End Try
Return 0D
End Function
Any pointers will be appreciated! Thank you!!
Private Sub IsFileOpen(ByVal file As FileInfo)
Dim stream As FileStream = Nothing
Try
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)
stream.Close()
Catch ex As Exception
If TypeOf ex Is IOException AndAlso IsFileLocked(ex) Then
' do something here, either close the file if you have a handle, show a msgbox, retry or as a last resort terminate the process - which could cause corruption and lose data
End If
End Try
End Sub
Private Shared Function IsFileLocked(exception As Exception) As Boolean
Dim errorCode As Integer = Marshal.GetHRForException(exception) And ((1 << 16) - 1)
Return errorCode = 32 OrElse errorCode = 33
End Function
Call it like this:
Call IsFileOpen(new FileInfo(filePath))
There is really no point using a 'is file in use check' function since you will still need to have try catch to handle the case that the file fails to open. The file open can fail for many more reasons than it just being already open.
Also using a function to do a check is no guarantee of success. The 'is file in use check' might return false only for the file open to fail with a file already open error, because in time between the check and trying to open the file it was opened by someone else.
It looks like the two suggestions from this MSDN forum posting both involve trying to open the file.
The first one is similar to what you are doing now, and the second involves using a Windows API function (CreateFile) and checking for a invalid handle signifying the file is in use. In both cases they are relying on an error condition to determine if the file is open or not. In short, in my opinion the method you are using is correct since there is not a System.IO.File.IsOpen property.