问题
Summary: In .net When locking a record in a random access file we cannot access records ahead of the locked record in the file.
To demonstrate the issue I have written two simple programs one opens and locks a record and the other tries to read through.
The results are that when locking record number 9 out of the 10 in the first program we are able to read records 1 and 2 but no more! The expectation (And this is our experience with VB6) is that you should be able to read all the records apart from the one you have locked.
Has anyone seen this problem? Am I doing something strange? Any work around?
Demo Code:
Program 1 Create/Open/Lock
Sub Main()
Dim FileName As String = "test.a"
Dim ListofName() As String = {"Name1", "Name2", "Name3", "Name4",
"Name5", "Name6", "Name7", "Name8", "Name9", "Name10"}
Try
Dim FileNumber1 As Integer = FreeFile()
FileOpen(FileNumber1, FileName, OpenMode.Random,
OpenAccess.ReadWrite, OpenShare.Shared, 600)
FileGet(FileNumber1, People, 1)
'Create File if needs be
If People.Name = "" Then
For A = 1 To 10
People.Name = ListofName(A - 1)
FilePut(FileNumber1, People, A)
Next
End If
'Lock the recoard we want for testing
Lock(FileNumber1, 9)
Catch ex As Exception
FileClose()
End Try
FileClose()
End Sub
_
Program 2 Open and try and read
Sub Main()
Dim FileName As String = "C:\**Location of first program file**\test.a"
Try
Dim FileNumber1 As Integer = FreeFile()
FileOpen(FileNumber1, FileName, OpenMode.Random,
OpenAccess.ReadWrite, OpenShare.Shared, 600)
FileGet(FileNumber1, People, 2)
'See how much of the file we can read
For A = 1 To 10
FileGet(FileNumber1, People, A)
System.Diagnostics.Debug.WriteLine(People.Name.ToString)
Next
Catch ex As Exception
FileClose()
End Try
FileClose()
End Sub
Edit 0.1: We have found that the deeper an individual record is locked within the file the more bytes/records are inaccessible before the locked one.
回答1:
Thanks all for your comments.
Posted the same question over on MSDN here and managed to get the answer.
So the conclusion is that with .net if you use FileGet or (e.g. System.IO.BinaryReader.ReadDouble()) the reader not only reads what you want but also buffers content meaning that a locked record ahead within the file is hit causing read failure.
But when using System.IO.FileStream.Read() and specifying exactly the number of bytes you want the buffer is not created allowing you to read all the records in a file except the locked one
Code example:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)>
Structure Person
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=600)>
<VBFixedString(600)>
Dim name As String
End Structure
. . .
Using fs = New FileStream(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, Marshal.SizeOf(People))
For A = 1 To 10
Try
Console.WriteLine("Trying " & A & "...")
Dim b() As Byte
ReDim b(Marshal.SizeOf(People) - 1)
fs.Seek((A - 1) * Marshal.SizeOf(People), SeekOrigin.Begin)
fs.Read(b, 0, b.Length)
Dim h = GCHandle.Alloc(b, GCHandleType.Pinned)
People = Marshal.PtrToStructure(Of Person)(h.AddrOfPinnedObject())
h.Free()
Console.WriteLine(People.name.Trim())
Catch ex As Exception
Console.WriteLine("ERROR " & A & " " & ex.Message)
End Try
Next
End Using
来源:https://stackoverflow.com/questions/45106245/net-file-random-access-recoard-locking