我正在尝试一些不同的方法来访问二进制文件,而我尝试使用的方法之一是针对以下问题:
How can I quickly read bytes from a memory mapped file in .NET?
我对F#的翻译如下:
let memMapRead2 (fileName: String, offset: int64, size: int) =
use mmf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, "mappedFile", 0L, MemoryMappedFileAccess.Read)
use view= mmf.CreateViewAccessor(offset, 0L, MemoryMappedFileAccess.Read)
let buf = Array.zeroCreate<byte> size
let mutable pptr: byte = 0uy
let ptr: nativeint = NativePtr.toNativeInt<byte> &&pptr
let bptr: nativeptr<byte> = ptr |> NativePtr.ofNativeInt<byte>
view.SafeMemoryMappedViewHandle.AcquirePointer(ref bptr)
Marshal.Copy(IntPtr.Add(ptr, 0), buf, 0, size)
view.SafeMemoryMappedViewHandle.ReleasePointer()
buf
我最终试图从文件中读取所有字节,但是我想看看是否可以比FileStream或MemoryMappedStream(它们两者似乎都进行类似的基准测试)更快地进行读取。但是,以上代码引发以下异常:
Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
at FSI_0007.memMapRead2(String fileName) in C:\Users\******************************\Reader.fs:line 30
at <StartupCode$FSI_0008>.$FSI_0008.main@()
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.execEntryPtFun@2123.Invoke(Tuple`2 tupledArg, Unit unitVar2)
at Microsoft.FSharp.Compiler.Interactive.Shell.clo@1088-286.Invoke(FSharpFunc`2 exec)
at Microsoft.FSharp.Primitives.Basics.List.iter[T](FSharpFunc`2 f, FSharpList`1 x)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.ProcessInputs(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, FSharpList`1 inputs, Boolean showTypes, Boolean isIncrementalFragment, Boolean isInteractiveItExpr, FSharpList`1 prefixPath)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.EvalParsedDefinitions(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, Boolean showTypes, Boolean isInteractiveItExpr, FSharpList`1 defs)
at Microsoft.FSharp.Compiler.Interactive.Shell.clo@1899-294.Invoke(FsiDynamicCompilerState istate)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.InteractiveCatch[b](ErrorLogger errorLogger, FSharpFunc`2 f, b istate)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.execParsedInteractions(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate, FSharpOption`1 action, ErrorLogger errorLogger, FSharpOption`1 lastResult)
at Microsoft.FSharp.Compiler.Interactive.Shell.clo@2078-297.Invoke(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.mainThreadProcessAction[a,b](a ctok, FSharpFunc`2 action, b istate)
at Microsoft.FSharp.Compiler.Interactive.Shell.res@2141-18.Invoke(ErrorLogger errorLogger, Tuple`2 tupledArg)
at Microsoft.FSharp.Compiler.Interactive.Shell.clo@1831-292.Invoke(Unit unitVar0)
at Sample.Microsoft.FSharp.Compiler.Interactive.Main.Microsoft-FSharp-Compiler-Interactive-Shell-Settings-IEventLoop-Invoke@104.Invoke()
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Sample.Microsoft.FSharp.Compiler.Interactive.Main.WinFormsEventLoop.Microsoft-FSharp-Compiler-Interactive-Shell-Settings-IEventLoop-Run()
at Microsoft.FSharp.Compiler.Interactive.Shell.runLoop@2383(FsiConsoleOutput fsiConsoleOutput, FsiEvaluationSessionHostConfig fsi, Unit unitVar0)
at Microsoft.FSharp.Compiler.Interactive.Shell.FsiEvaluationSession.Run()
at Sample.Microsoft.FSharp.Compiler.Interactive.Main.evaluateSession(String[] argv)
at Sample.Microsoft.FSharp.Compiler.Interactive.Main.MainMain(String[] argv)
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssemblyByName(AssemblyName assemblyName, String[] args)
at System.AppDomain.ExecuteAssemblyByName(AssemblyName assemblyName, String[] args)
at Sample.Microsoft.FSharp.Compiler.Interactive.Main.MainMain(String[] argv)
Session termination detected. Press Enter to restart.
FSI从来没有对我这么生气过-到底发生了什么?我应该在此代码块中使用某种SecurityCritical属性吗?我知道F#具有用于处理指针的fixed关键字,但我认为不需要在这里使用(尽管可能是错误的)。
答案 0 :(得分:2)
我测试了以下内容,并且可以正常工作:
let memMapReadFile fname offset size =
use mmf =
MemoryMappedFile.CreateFromFile (fname, FileMode.Open,
"mappedFile", 0L,
MemoryMappedFileAccess.Read)
use view = mmf.CreateViewAccessor (offset, 0L,
MemoryMappedFileAccess.Read)
let buf = Array.zeroCreate<byte> size
let ptr =
let p = ref (NativePtr.ofNativeInt 0n)
view.SafeMemoryMappedViewHandle.AcquirePointer p
!p
Marshal.Copy (NativePtr.toNativeInt ptr, buf, 0, size)
view.SafeMemoryMappedViewHandle.ReleasePointer ()
buf