Saving a Structure to a Binary File - vb.net

I am creating an application using a windows forms application in visual studio in the vb.net language. I need help converting a structure that I coded into a binary file that is essentially a save in user results. I'm not a very good coder so excuse the poor code.
The code below shows that I have created a structure called saveresults and by clicking button1, it should get the contents of the binary file and edit them to be the new result. When I run the code the problem seems to be in the line FileOpen(1, "/bin/debug/1.txt", OpenMode.Binary) in the saveres subroutine.
Structure saveresults 'Structure for saving results
Dim numright As Integer
Dim numwrong As Integer
Dim totalnum As Integer
End Structure
'Subroutine aimed at getting stats saved to a text file to eventually be displayed to the user
Sub saveres(saveresults As saveresults, correct As Boolean)
saveresults.totalnum = saveresults.totalnum + 1
'Determining the contents to be saved to the binary file
If correct = True Then
saveresults.numright = saveresults.numright + 1
ElseIf correct = False Then
saveresults.numwrong = saveresults.numwrong + 1
End If
FileOpen(1, "/bin/debug/1.txt", OpenMode.Binary)
FilePut(1, saveresults)
FileClose(1)
End Sub
'attempt at saving results to the binary file
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim correct = True
Dim results As saveresults
FileOpen(1, "/bin/debug/1.txt", OpenMode.Binary)
FileGet(1, results)
saveres(results, correct)
FileClose(1)
End Sub
Any help would be appreciated. Thank you.

Use this instead
FileOpen(1, "1.txt", OpenMode.Binary)
Using the above opens the file in your project's debug folder.

You are referring to text files and binary files as if they are the same thing. They are not. Text files are human readable in Notepad; binary files are not.
I have not used the methods you are attempting since VB 6. Use the .Net System.IO methods. To use these you need to add Imports System.IO at the very top of your code file.
I have broken your code into Subs and Functions that have a single purpose. Reading the file, writing the file, updating the data, and displaying the data. This makes code more maintainable. If your code misbehaves it is easier to find the error and easier to fix if a method has only one thing to do.
The file location in the example is in the same directory as your .exe file. Probably
/bin/Degug.
'A Form level variable to hold the data
Private results As New saveresults
Structure saveresults 'Structure for saving results
Dim numright As Integer
Dim numwrong As Integer
Dim totalnum As Integer
End Structure
'Update the data
Private Sub UpdateResults(Correct As Boolean)
'It is not necessary to include = True when testing a Boolean
If Correct Then
'this is a shortcut method of writin results.numright = results.numright + 1
results.numright += 1
'A Boolean can only be True or False so if it is not True
'it must be False so, we can just use an Else
'No need to check the condition again
Else
results.numwrong += 1
End If
results.totalnum += 1
End Sub
'Write text file
Private Sub SaveResultsFile(results As saveresults, correct As Boolean)
Dim sb As New StringBuilder
sb.AppendLine(results.numright.ToString)
sb.AppendLine(results.numwrong.ToString)
sb.AppendLine(results.totalnum.ToString)
File.WriteAllText("1.txt", sb.ToString)
End Sub
'Read the text file
Private Function ReadResultsFile() As saveresults
Dim ResultsFiLe() = File.ReadAllLines("1.txt")
Dim results As New saveresults With
{
.numright = CInt(ResultsFiLe(0)),
.numwrong = CInt(ResultsFiLe(1)),
.totalnum = CInt(ResultsFiLe(2))
}
Return results
End Function
'Display
Private Sub DisplayResults()
Dim ResultsToDisplay As saveresults = ReadResultsFile()
'The $ indicates an interpolated string, the same thing can be accomplished with String.Format
Label1.Text = $"The correct number is {ResultsToDisplay.numright}. The wrong number is {ResultsToDisplay.numwrong}. The total is {ResultsToDisplay.totalnum}."
End Sub

Related

Moving Files From One Folder To Another VB.Net

I am trying to figure out how to move 5 files
settings.txt
settings2.txt
settings3.txt
settings4.txt
settings5.txt
from one folder to another.
Although I know what the file names will be and what folder Name they will be in, I don't know where that folder will be on the Users computer.
My thought process is to use a FolderBrowseDialog which the user can browse to where the Folder is, and then when OK is pressed, it will perform the File copy to the destination folder, overwriting what's there.
This is what I have so far.
Dim FolderPath As String
Dim result As Windows.Forms.DialogResult = FolderBrowserImport.ShowDialog()
If result = DialogResult.OK Then
FolderPath = FolderBrowserImport.SelectedPath & "\"
My.Computer.FileSystem.CopyFile(
FolderPath & "settings.txt", "c:\test\settings.txt", overwrite:=True)
ElseIf result = DialogResult.Cancel Then
Exit Sub
End If
Rather than run this 5 times, is there a way where it can copy all 5 files at once
I know why IdleMind recommended the approach they did, but it would probably make for a bit more readable code to just list out the file names:
Imports System.IO
...
Dim result = FolderBrowserImport.ShowDialog()
If result <> DialogResult.OK Then Exit Sub
For Each s as String in {"settings.txt", "settings2.txt", "settings3.txt", "settings4.txt", "settings5.txt" }
File.Copy( _
Path.Combine(FolderBrowserImport.SelectedPath, s), _
Path.Combine("c:\test", s), _
True _
)
Next s
You can swap this fixed array out for a list that VB prepares for you:
For Each s as String in Directory.GetFiles(FolderBrowserImport.SelectedPath, "settings*.txt", SearchOption.TopDirectoryOnly)
File.Copy(s, Path.Combine("c:\test", Path.GetFilename(s)), True)
Next s
Tips:
It's usually cleaner to do a If bad Then Exit Sub than a If good Then (big load of indented code) End If - test all your known failure conditions at the start and exit the sub if anything fails, rather than arranging a huge amount of indented code
Use Path.Combine to combine path and filenames etc; it knows how to deal with stray \ characters
Use Imports to import namespaces rather than spelling everything out all the time (System.Windows.Forms.DialogResult - a winforms app will probably have all the necessaries imported already in the partial class so you can just say DialogResult. If you get a red wiggly line, point to the adjacent lightbulb and choose to import System.WIndows/Forms etc)
Once you have the selected folder, use a For loop to build up the names of the files you're looking for. Use System.IO.File.Exists() to see if they are there. Use System.IO.Path.Combine() to properly combine your folders with the filenames.
Here's a full example (without exception handling, which should be added):
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If FolderBrowserImport.ShowDialog() = DialogResult.OK Then
Dim FolderPath As String = FolderBrowserImport.SelectedPath
For i As Integer = 1 To 5
Dim FileName As String = "settings" & If(i = 1, "", i) & ".txt"
Dim FullPathFileName As String = System.IO.Path.Combine(FolderPath, FileName)
If System.IO.File.Exists(FullPathFileName) Then
Dim DestinationFullPathFileName = System.IO.Path.Combine("c:\test", FileName)
My.Computer.FileSystem.CopyFile(FullPathFileName, DestinationFullPathFileName, True)
Else
' possibly do something in here if the file does not exist?
MessageBox.Show("File not found: " & FullPathFileName)
End If
Next
End If
End Sub

Why am I getting an error when I try to print the contents of a file I am searching for?

Can you help me with searching for and printing a file specified by text in textbox1? I have the following code but textbox1 shows me an error. I don't know if the code is correctly written and functioning right.
First class:
Public Class tisk
'print
Public Shared Function printers()
Dim printThis
Dim strDir As String
Dim strFile As String
Dim Textbox1 As String
strDir = "C:\_Montix a.s. - cloud\iMontix\Testy"
strFile = "C:\_Montix a.s. - cloud\iMontix\Testy\" & Textbox1.text & ".lbe"
If Not fileexprint.FileExists Then
MsgBox("Soubor neexistuje")
printers = False
Else
fileprint.PrintThisfile()
printers = True
End If
End Function
End Class
Second class:
Public Class fileprint
Public Shared Function PrintThisfile()
Dim formname As Long
Dim FileName As String
On Error Resume Next
Dim X As Long
X = Shell(formname, "Print", FileName, 0&)
End Function
End Class
Third class:
Public Class fileexprint
Public Shared Function FileExists()
Dim fname As Boolean
' Returns TRUE if the file exists
Dim X As String
X = Dir(fname)
If X <> "" Then FileExists = True _
Else FileExists = False
End Function
End Class
When I fill a textbox with text, how can I search for a file in the computer using this text and print this file?
Your "Textbox1" is a variable and not actually getting the value from a textbox. If I'm not wrong, I believe you intend to get the value of a textbox and concatenate to form your directory url. You'll first need to add a text box to your windows/web form, give that textbox an id then call that id in your code behind. E.g. You add a text box with id "textbox001", in your code behind you'll do something like "textbox001.text". In your case it'll now be: strFile = "C:_Montix a.s. - cloud\iMontix\Testy\" & textbox001.text & ".lbe". Hope this helps.
Not sure this will fix your issue, but there are some poor practices in that code that are addressed below. This will certainly get you closer than what you have right now.
Public Class tisk
'print
Public Shared Function printers(ByVal fileName As String) As Boolean
Dim basePath As String = "C:\_Montix a.s. - cloud\iMontix\Testy"
Dim filePath As String = IO.Path.Combine(basePath, fileName & ".lbe")
If IO.File.Exists(filePath) Then
fileprint.PrintThisfile(filePath)
Return True
End If
'Don't show a message box here. Do it in the calling code
Return False
End Function
End Class
Public Class fileprint
Public Shared Sub PrintThisfile(ByVal fileName As String)
'Not sure how well this will work, but it has better chances than the original
Dim p As New Process()
p.StartInfo.FileName = fileName
p.StartInfo.Verb = "Print"
p.Start()
End Sub
End Class
One additional comment on the File.Exists() check. It's actually poor practice to check if the file exists here at all. The file system is volatile. It's possible for things to change in the short time between when you check and when you try to use the file. In addition, whether the file exists is only one thing you need to look at. There's also access permissions and whether the file is locked or in use. The better practice is to just try to do whatever you need with the file, and then handle the exception if it fails.

VB.NET stopping strings being automatically split by spaces

I am building a program in VB that populates a listbox with all the songs in a chosen folder and opens them with media player when you click on them in the list. All of that works but my problem is that pretty much no matter what I do (I've tested this with WMP, VLC, and Winamp) it splits up the argument string by spaces, for example if the file path is C:\Program Files (x86)\Test song.mp3, it will try to open in sequence: C:\Program, then Files, then (x86)\Test, then song.mp3. It works on file paths containing no spaces, but else it always fails.
Private Sub SongListBox_Click(sender As Object, e As EventArgs) Handles SongListBox.Click
Dim song As String = SongListBox.SelectedIndex
If SongListBox.SelectedIndex = "-1" Then
Else
Dim SongPath As String = Pathlist.Items.Item(song)
Dim SongProcess As New ProcessStartInfo
SongProcess.FileName = "C:\Program Files\Winamp\winamp.exe"
SongProcess.Arguments = SongPath
SongProcess.UseShellExecute = True
SongProcess.WindowStyle = ProcessWindowStyle.Normal
MsgBox(Pathlist.Items.Item(song), MsgBoxStyle.Information, "Song")
Dim SongStart As Process = Process.Start(SongProcess)
SongListBox.Select()
End If
End Sub

Writing to a text file in Visual Basic stops at 3074 bytes. Any idea why?

I have developed a small program using Visual Basic Express 2010 that reads a file, scans it line by line, when the line contains some specific text, it manipulates the text and writes that manipulated text to a new file, if that condition is not met, it writes the original line.
It is working ok, gives no errors and completes the run. However, it stops writing to the file at some point. I have checked the files and the only common thing I find between the several tests is that the new files all have 3074 bytes as size. Is this a limitation of VB Express? Am I using the wrong way of writing to the file?
Here a reduced version of the code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Linha As String
Dim datapag As String
'Open File
If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim novoficheiro As New System.IO.StreamWriter(OpenFileDialog1.FileName + "2.xml")
Dim Ficheiro As New System.IO.StreamReader(OpenFileDialog1.FileName)
'Scan lines one at a time
Do While Ficheiro.Peek <> -1
Linha = Ficheiro.ReadLine
Dim tratada As Boolean
tratada = False
'Make some changes in specific conditions
If Linha.Contains("<PaymentDueDate>") Then
datapag = Mid(Linha, 17, 8)
Dim composta, Novalinha3 As String
composta = Mid(datapag, 1, 4) + "-"
composta = composta + Mid(datapag, 5, 2) + "-"
composta = composta + Mid(datapag, 7, 2)
Novalinha3 = Replace(Linha, datapag, composta)
novoficheiro.WriteLine(Novalinha3)
tratada = True
End If
'If no changes were made write the original line
If tratada = False Then
novoficheiro.WriteLine(Linha)
End If
Loop
End If
End Sub
End Class
So, the idea is that I have a new version of the file with just some lines changed.
I have added messages throughout the code to show me the contents of the lines sent to the new file and they are all parsed ok, corrected correctly when needed and unchanged when no correction is necessary.
The file just gets truncated at some point, depending on how many different conditions I handle but always resulting in a file with 3074 byte size (the original file is 2787 bytes long, BTW).
Any help?
Thanks in advance!
I believe that you need to flush and close the StreamWriter after your done writing the file and before you exit the function. After the Loop and before the End If, add the line:
novoficheiro.Close()
This should fix the issue.

code that doesn't work...Kill-process , search-for-file , streamwrite on file searched file

can you help me with that code ?
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As String = "C:\Users\Andy\Documents\Visual Studio 2008\Projects\minecraft srv\"
For Each app As Process In Process.GetProcesses
If app.ProcessName = "notepad" Then
app.Kill()
End If
Next
Dim result As String
Dim servprop() As String
servprop = System.IO.Directory.GetFiles(x, "server.*")
For Each file In servprop
result = Path.GetFileName(file)
Next
Dim z As String = "C:\Users\Andy\Documents\Visual Studio 2008\Projects\minecraft srv\" & result.ToString
Dim t As StreamWriter = New StreamWriter(z)
t.WriteLine(TextBox1.Text.ToString)
t.Close()
End Sub
so... I got a button (button1) that finds if notepad is opened and kills it.
Then it searches for "server.Properties" in "x" location
if server.properties is found , then "result" will get his name (server)
"z" is the file location where streamwriter must write the text from textbox1 .
And it doesn't work... streamwirter is not writing on server.properties ... why ?
mention : I'm just a kid :D and i'm trying to learn by myself visual basic .
If you have only one file called "server.properties" then you could remove all the code that search for this file and write it directly.
Dim z As String
z = System.IO.Path.Combine(x, "server.properties")
Using t = New StreamWriter(z)
t.WriteLine(TextBox1.Text.ToString)
t.Flush()
End Using
Regarding the error, encapsulating the writing code with a proper using statement ensures a complete clean-up. Also adding a call to Flush() is probably not necessary, but doesn't hurt.