How to access a random access file in VB.NET - vb.net

I am trying to open a random access file using VB.NET I am getting the following error messge when attempting to access the file Error 75 (Access to the path ....is denied). Is there something that I must change to fix this?
Structure StdSections
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(15), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=15)> Public A() As Char 'BEAM --- complete beam designation 15
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(2), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2)> Public B() As Char 'DSG --- shape ie "W" or "C" 2
Dim C As Single 'DN --- nominal depth of section 4
Dim d As Single 'WGT --- weight 4
.
.
.
End structure
''Note 'File1' holds complete path!
Public std As StdSections
Dim i,ffr,fLength,lastmembNo as integer
sectionFound = False
fLength = Len(std)
If fLength = 0 Then fLength = 168 ' 177
ffr = FreeFile()
'FileOpen(ffr, File1, OpenMode.Random, , , fLength)
FileOpen(ffr, File1, OpenMode.Random, OpenAccess.ReadWrite, OpenShare.LockRead, fLength)
>>Error 75 (Access to the path ....is denied) << path is perfectly good!!!
lastmembNo = CInt(LOF(ffr)) \ fLength
'ReDim std(lastmembNo)
For i = 1 To lastmembNo
FileGet(ffr, std, i)
If Trim(memberID) = Trim(std.A) Then
sectionFound = True
end if
next i

The first thing to check is permissions to the file in question. "Access to the path is denied" doesn't mean the path is bad or invalid, but that you either don't have permission, or the file is locked by another process. Still another possibility is a typo in the path variable (File1 in your sample)

Related

Converting a String into a Single

My question might sound stupid but I tried several solutions exposed on internet without any success. I'm totally new to VBA.
Problem:
I am extracting data from a txt file. That data is stored into a String and I need to store that value into a Single variable.
Context:
I am using Microsoft Excel 2010, the code is done under Microsoft Visual Basic for Applications.
Solutions that i tried:
In all these cases, valueToRead is equal to "1.580000".
1) realAngle = CSng(valueToRead)
I get the execution error '13', type incompatibility
2) realAngle = Single.Parse(valueToRead)
Compilation error, syntax error
3) realAngle = Single.Parse(valueToRead, System.Globalization.NumberFormatInfo.InvariantInfo)
Compilation error, syntax error
4) realAngle = Convert.ToSingle(valueToRead)
Execution error '424': object required
My code is below :
Sub macro_test()
' File to read data from
Dim logFile As String
' Variable containing a line from the file
Dim textLine As String
' Variable containing a part of the line
Dim ReadValue As Variant
' Variable containing a part of ReadValue
Dim ReadValue2 As Variant
' Desperate variable in order to be sure to have a String value
Dim valueToRead As String
' Angle value stored in the file
Dim realAngle As Single
' Number of elements separated by " | " in the lien
Dim Size As Integer
' Initialize variables
Size = 0
realAngle = 0
logFile = "FilePathAndName"
' Open the txt file
Open logFile For Input As #1
' Read until the end of the file
Do Until EOF(1)
' Get a line of text from the file
Line Input #1, textLine
' Split the line with " | " separator
ReadValue = Split(textLine, " | ")
' Count the number of elements
Size = UBound(ReadValue) - LBound(ReadValue) + 1
' If the line have enough elements then it may be of interest
If Size > 9 Then
' if this is the correct line thanks to a correct identificator
If ReadValue(3) = "MyIdentificator" Then
' Split the line with the " = " sign
ReadValue2 = Split(ReadValue(8), " = ")
' Storing the value into a String
valueToRead = ReadValue2(1)
realAngle = CSng(valueToRead)
'realAngle = Single.Parse(valueToRead)
'realAngle = Convert.ToSingle(valueToRead)
'realAngle = Single.Parse(valueToRead, System.Globalization.NumberFormatInfo.InvariantInfo)
End If
End If
Loop
Close #1
End Sub
Thank you in advance for your help!
edit: Here is an exemple of the line that I get in the file:
Log Level: LogLevel | File name: X:\Folder1\Folder2\Folder3\Folder4\Folder5\Folder6\FileName.h | Function name: FunctionName| Line number: XXXX | Information: MYINFO | BLABLA | VALUE1 = 32768 | VALUE2 = 0.000000 | VALUE3 = 1.580000 | VALUE4 = 0.000000 | VALUE5 = 3581.941895 | VALUE6 = 36349.941406
I am currently trying to get VALUE3.
Just guessing that you are not in USA/UK. In Germany, you have , and not . as a regional setting. Thus, add this to the string, before casting:
Public Function change_commas(ByVal myValue As Variant) As String
Dim str_temp As String
str_temp = CStr(myValue)
change_commas = Replace(str_temp, ",", ".")
End Function

Reading formatted data from a text file

The following code reads in values (in a loop) from a text file containing two numbers per line into X and Y. The first iteration of the loop gives correct values for X and Y (70, 210). The next iteration onwards, the X and Y values are not what is contained in the file (210, 210 for the second iteration instead of 0, 210). I ust be making a mistake but I can't seem to find it !
Sub main()
Dim X As Double
Dim Y As Double
Open "perforatedcircles.txt" For Input As #1
Do While Not EOF(1)
Input #1, X, Y
Loop
Close #1
End Sub
Sample Contents of "perforatedcircles.txt":
70.000 210.000
0.000 210.000
-70.000 -210.000
How was the input file created? It appears to be in a different format than the Input # directive is expecting.
https://msdn.microsoft.com/en-us/library/aa243386(v=vs.60).aspx
"Data read with Input # is usually written to a file with Write #. Use this statement only with files opened in Input or Binary mode."
"Note To be able to correctly read data from a file into variables using Input #, use the Write # statement instead of the Print # statement to write the data to the files. Using Write # ensures each separate data field is properly delimited."
Given the space delimitation, you'll need to parse the file differently. Here is one example:
Dim iLine As Integer,
Dim sFile As String
Dim sData As String
Dim sLine() As String
Dim sSplitLine() As String
Dim x as Double
Dim y as Double
'read the whole file into 1 string variable
sFile = "perforatedcircles.txt"
Open sFile For Input As #1
sData = Input(LOF(1), 1)
Close #1
sLine = Split(sData, vbCrLf)
For iLine = 0 To UBound(sLine)
sSplitLine = Split(sLine(UBound(sLine)), " ")
x = CDbl(sSplitLine(0))
y = CDbl(sSplitLine(1))
'Do Stuff with your numbers here
Next iLine

Nested Loop Not Working vb.net

I am trying to read file names from source directory and then read a separate file to rename and move files to target directory. Below code reads the file names but the problem is it only reading the contents of app.ini file only once i.e. for first file name. Code is not looping app.ini as soon as for loops switches to second file name.
Dim di As New IO.DirectoryInfo("D:\Transcend")
Dim diar1 As IO.FileInfo() = di.GetFiles()
Dim dra As IO.FileInfo
If (di.GetFiles.Count > 0) Then
Dim a As Integer = 1
Dim b As Integer = 1
For Each dra In diar1
ComboBox1.Items.Add(dra.FullName.ToString)
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
Do While reader2.Peek() >= 0
Dim line2 = reader2.ReadLine
Do Until line2 Is Nothing
'line2 = reader2.ReadLine()
'ComboBox1.Items.Add(line2.ToString)
'Label1.Text = line2
If line2 <> Nothing Then
If line2.Contains("filename" + a.ToString) Then
Dim values() As String = line2.Split(CChar(":")).ToArray
Dim values2() As String = values(1).Split(CChar(";")).ToArray() 'full filename
Dim values3() As String = values(2).Split(CChar(";")).ToArray() 'keyword to be replaced in filename
Dim values4() As String = values(3).Split(CChar(";")).ToArray() 'fullname in place of keyword
Dim values5() As String = values(4).Split(CChar(";")).ToArray 'destination drive letter
Dim values6() As String = values(5).Split(CChar(";")).ToArray 'destination path after drive letter
ComboBox1.Items.Add(values2(0))
ComboBox1.Items.Add(values3(0))
ComboBox1.Items.Add(values4(0))
ComboBox1.Items.Add(values5(0) + ":" + values6(0))
'Label1.Text = dra.Name.ToString
If dra.Name.ToString.Contains(values2(0)) Then
Dim n As String = dra.Name.Replace(values3(0), values4(0))
File.Copy(dra.FullName, values5(0) + ":" + values6(0) + n)
End If
End If
End If
Exit Do
Loop
a = a + 1
Loop
reader2.Close()
End Using
b = b + 1
Next
Label1.Text = b
Else
MsgBox("No files!")
End
End If
ouput image:
Above image is to show the output and error, first line is the filename1 and the next 8 lines are the output of the app.ini file. As you can see as soon as the filename1 changes to the next file name i.e. Autorun.inf in the 9th line of the above image the same 8 lines of app.ini(line 2nd to 9th in the above image) should be reiterated after Autorun.inf file name but app.ini is not getting to read after file name increments to Autorun.inf and then to FreeSoftware(JF).htm.
The only difference between the first and the second file are the a and b values.
On the first run a will start from 1 and it will be incremented for each line in the app.ini file. After reading 8 lines, the final value of a will be 9.
For the second file, the value a isn't reset so it's value will still be 9. This means that the following condition will never be true because the first run only found value from 1 to 8 *.
If line2.Contains("filename" + a.ToString) Then
To fix your issue, you must set the a variable value back to 1 between each file:
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
a = 1
Do While reader2.Peek() >= 0
* I'm assuming that the filename in your .ini file are sorted (i.e. line containing filename9 isn't listed before filename2) and that no external process changed the content of your .ini file between the first and the second file.

Reading the next line from a text file

I'm working on an RPG type game for a project and I am stuck.
Basically, this code searches for a name in a text file (structure: odds as names and evens as levels). It then needs to output the next line which is the level they where on. I have the counter (variable "count") to output the right text line in which the level is written but I can not use that count to read that line (using "FileSystem.LineInput(count)").
Here is my full code:
Sub LoadGame()
Dim filename, filepath, searchitem, question, read As String
Dim found As Boolean
Dim count As Integer = 1
filename = "save.txt"
filepath = CurDir() & "\" & filename
searchitem = name
FileOpen(1, filename, OpenMode.Input)
Do While Not EOF(1)
read = LineInput(1)
If read = searchitem Then
found = True
Exit Do
Else
found = False
End If
count = count + 1
Loop
If found = True Then
If count >= 3 Then
count = count + 1
End If
question = FileSystem.LineInput(count) ' This bit is broken
Console.WriteLine("Found save game... Loading: " & question)
Console.ReadLine()
Console.BackgroundColor = ConsoleColor.Black
Console.ForegroundColor = ConsoleColor.Red
Console.Clear()
Race(question)
Else
Console.WriteLine("No save game...")
Console.ReadLine()
End If
FileClose(1)
End Sub
I am not sure what is wrong but any help would be greatly appreciated (using VB 2010)
LineInput reads the next line of the specified file (parameter FileNumber).
Your file has the FileNumber 1 and the file pointer points to the desired line. Therefore, it should be sufficient to
question = FileSystem.LineInput(1)
In my oppinion, you should avoid those kinds of file access (per FileNumber) in .Net. This is just an old relict from VB6 times. In .Net you have easy-to-use classes such as StreamReader for that purpose. But if you want to do it the old-fashioned way, at least use the FreeFile method to define the file number.

Start reading massive text file from the end

I would ask if you could give me some alternatives in my problems.
basically I'm reading a .txt log file averaging to 8 million lines. Around 600megs of pure raw txt file.
I'm currently using streamreader to do 2 passes on those 8 million lines doing sorting and filtering important parts in the log file, but to do so, My computer is taking ~50sec to do 1 complete run.
One way that I can optimize this is to make the first pass to start reading at the end because the most important data is located approximately at the final 200k line(s) . Unfortunately, I searched and streamreader can't do this. Any ideas to do this?
Some general restriction
# of lines varies
size of file varies
location of important data varies but approx at the final 200k line
Here's the loop code for the first pass of the log file just to give you an idea
Do Until sr.EndOfStream = True 'Read whole File
Dim streambuff As String = sr.ReadLine 'Array to Store CombatLogNames
Dim CombatLogNames() As String
Dim searcher As String
If streambuff.Contains("CombatLogNames flags:0x1") Then 'Keyword to Filter CombatLogNames Packets in the .txt
Dim check As String = streambuff 'Duplicate of the Line being read
Dim index1 As Char = check.Substring(check.IndexOf("(") + 1) '
Dim index2 As Char = check.Substring(check.IndexOf("(") + 2) 'Used to bypass the first CombatLogNames packet that contain only 1 entry
If (check.IndexOf("(") <> -1 And index1 <> "" And index2 <> " ") Then 'Stricter Filters for CombatLogNames
Dim endCLN As Integer = 0 'Signifies the end of CombatLogNames Packet
Dim x As Integer = 0 'Counter for array
While (endCLN = 0 And streambuff <> "---- CNETMsg_Tick") 'Loops until the end keyword for CombatLogNames is seen
streambuff = sr.ReadLine 'Reads a new line to flush out "CombatLogNames flags:0x1" which is unneeded
If ((streambuff.Contains("---- CNETMsg_Tick") = True) Or (streambuff.Contains("ResponseKeys flags:0x0 ") = True)) Then
endCLN = 1 'Value change to determine end of CombatLogName packet
Else
ReDim Preserve CombatLogNames(x) 'Resizes the array while preserving the values
searcher = streambuff.Trim.Remove(streambuff.IndexOf("(") - 5).Remove(0, _
streambuff.Trim.Remove(streambuff.IndexOf("(")).IndexOf("'")) 'Additional filtering to get only valuable data
CombatLogNames(x) = search(searcher)
x += 1 '+1 to Array counter
End If
End While
Else
'MsgBox("Something went wrong, Flame the coder of this program!!") 'Bug Testing code that is disabled
End If
Else
End If
If (sr.EndOfStream = True) Then
ReDim GlobalArr(CombatLogNames.Length - 1) 'Resizing the Global array to prime it for copying data
Array.Copy(CombatLogNames, GlobalArr, CombatLogNames.Length) 'Just copying the array to make it global
End If
Loop
You CAN set the BaseStream to the desired reading position, you just cant set it to a specfic LINE (because counting lines requires to read the complete file)
Using sw As New StreamWriter("foo.txt", False, System.Text.Encoding.ASCII)
For i = 1 To 100
sw.WriteLine("the quick brown fox jumps ovr the lazy dog")
Next
End Using
Using sr As New StreamReader("foo.txt", System.Text.Encoding.ASCII)
sr.BaseStream.Seek(-100, SeekOrigin.End)
Dim garbage = sr.ReadLine ' can not use, because very likely not a COMPLETE line
While Not sr.EndOfStream
Dim line = sr.ReadLine
Console.WriteLine(line)
End While
End Using
For any later read attempt on the same file, you could simply save the final position (of the basestream) and on the next read to advance to that position before you start reading lines.
What worked for me was skipping first 4M lines (just a simple if counter > 4M surrounding everything inside the loop), and then adding background workers that did the filtering, and if important added the line to an array, while main thread continued reading the lines. This saved about third of the time at the end of a day.