Read all contents of memory mapped file or Memory Mapped View Accessor without knowing the size of it
我需要类似于readtoend或readallbytes的东西来使用mappedviewaccessor读取memoryMapped文件的所有内容。如果我不知道它的大小,我该怎么做?
我已经搜索过了,我看到了这个问题,但这不是我要找的:
如何从.NET中的内存映射文件快速读取字节?
编辑:
有一个问题,(int)stream.length没有给出正确的长度,而是给出了所使用的内部缓冲区的大小!我需要重新回答这个问题,因为它非常紧迫。
而是使用流:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static Byte[] ReadMMFAllBytes(string fileName) { using (var mmf = MemoryMappedFile.OpenExisting(fileName)) { using (var stream = mmf.CreateViewStream()) { using (BinaryReader binReader = new BinaryReader(stream)) { return binReader.ReadBytes((int)stream.Length); } } } } |
这是很难回答的,因为你的申请还有很多细节,但我认为Guffa和Amer的回答仍然部分正确:
- memoryMappedFile的内存大于文件;它是内存中4KB页的序列。因此,stream.length实际上会提供所有字节(没有"内部缓冲区大小"),但它可能会提供比预期更多的字节,因为该大小总是四舍五入到4KB边界。
- "文件"语义来自将memoryMappedFile关联到真正的文件系统文件。假设创建文件的过程总是调整文件大小,那么您可以通过文件系统获得文件的精确大小。
如果以上所有内容都适合您的应用程序,那么以下内容应该有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | static byte[] ReadMemoryMappedFile(string fileName) { long length = new FileInfo(fileName).Length; using (var stream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite)) { using (var mmf = MemoryMappedFile.CreateFromFile(stream, null, length, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false)) { using (var viewStream = mmf.CreateViewStream(0, length, MemoryMappedFileAccess.Read)) { using (BinaryReader binReader = new BinaryReader(viewStream)) { var result = binReader.ReadBytes((int)length); return result; } } } } } |
号
要写入数据,可以使用以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private static void WriteData(string fileName, byte[] data) { using (var stream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { using (var mmf = MemoryMappedFile.CreateFromFile(stream, null, data.Length, MemoryMappedFileAccess.ReadWrite, null, HandleInheritability.Inheritable, true)) { using (var view = mmf.CreateViewAccessor()) { view.WriteArray(0, data, 0, data.Length); } } stream.SetLength(data.Length); // Make sure the file is the correct length, in case the data got smaller. } } |
但是,当您完成上述所有操作时,您也可以直接使用文件并避免内存映射。如果无法将其映射到文件系统,那么Guffa对数据本身的长度(或结束标记)进行编码的答案可能是最好的。
你不能那样做。
视图访问器是以最小系统页面大小创建的,这意味着它可能大于实际文件。视图流只是访问器的流形式,因此它也将提供相同的行为。
"views are provided in units of system pages, and the size of the view
is rounded up to the next system page size"
号
http://msdn.microsoft.com/en-us/library/dd267577.aspx
访问器很乐意在实际文件之外读写,而不会引发异常。读取时,文件之外的任何字节都将为零。写入时,只忽略文件外写入的字节。
要从与原始文件大小完全相同的内存映射文件中读取文件,必须知道该大小。
使用fileinfo类获取长度,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | using System.Data; using System.IO; using System.IO.Compression; using System.IO.MemoryMappedFiles; // ... public void WriteToMemoryMap(DataSet ds, string key, string fileName) { var bytes = CompressData(ds); using (MemoryMappedFile objMf = MemoryMappedFile.CreateFromFile(fileName, FileMode.OpenOrCreate, key, bytes.Length)) { using (MemoryMappedViewAccessor accessor = objMf.CreateViewAccessor()) { accessor.WriteArray(0, bytes, 0, bytes.Length); } } } public DataSet ReadFromMemoryMap(string fileName) { var fi = new FileInfo(fileName); var length = (int)fi.Length; var newBytes = new byte[length]; using (MemoryMappedFile objMf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open)) { using (MemoryMappedViewAccessor accessor = objMf.CreateViewAccessor()) { accessor.ReadArray(0, newBytes, 0, length); } } return DecompressData(newBytes); } public byte[] CompressData(DataSet ds) { try { byte[] data = null; var memStream = new MemoryStream(); var zipStream = new GZipStream(memStream, CompressionMode.Compress); ds.WriteXml(zipStream, XmlWriteMode.WriteSchema); zipStream.Close(); data = memStream.ToArray(); memStream.Close(); return data; } catch (Exception) { return null; } } public DataSet DecompressData(byte[] data) { try { var memStream = new MemoryStream(data); var unzipStream = new GZipStream(memStream, CompressionMode.Decompress); var objDataSet = new DataSet(); objDataSet.ReadXml(unzipStream, XmlReadMode.ReadSchema); unzipStream.Close(); memStream.Close(); return objDataSet; } catch (Exception) { return null; } } |
。
我想从memoryStream.toArray()方法中得到一些返回所有字节的内容,下面的代码对我有用:
1 2 3 4 5 6 7 8 9 10 11 | using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(MemoryMappedName)) { using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { using (MemoryStream memStream = new MemoryStream()) { stream.CopyTo(memStream); return memStream.ToArray(); } } } |
干杯!
只需将@amer sawan解决方案翻译为vb.net:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ' Usage Example: ' Dim ReadBytes As Byte() = ReadMemoryMappedFile(Name:="My MemoryMappedFile Name") ' Read the byte-sequence from memory. ' Dim Message As String = System.Text.Encoding.ASCII.GetString(ReadBytes.ToArray) ' Convert the bytes to String. ' Message = Message.Trim({ControlChars.NullChar}) ' Remove null chars (leading zero-bytes) ' MessageBox.Show(Message,"", MessageBoxButtons.OK) ' Show the message. ' ' ''' <summary> ''' Reads a byte-sequence from a <see cref="IO.MemoryMappedFiles.MemoryMappedFile"/> without knowing the exact size. ''' Note that the returned byte-length is rounded up to 4kb, ''' this means if the mapped memory-file was written with 1 byte-length, this method will return 4096 byte-length. ''' </summary> ''' <param name="Name">Indicates an existing <see cref="IO.MemoryMappedFiles.MemoryMappedFile"/> assigned name.</param> ''' <returns>System.Byte().</returns> Private Function ReadMemoryMappedFile(ByVal Name As String) As Byte() Try Using MemoryFile As IO.MemoryMappedFiles.MemoryMappedFile = IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(Name, IO.MemoryMappedFiles.MemoryMappedFileRights.ReadWrite) Using Stream = MemoryFile.CreateViewStream() Using Reader As New BinaryReader(Stream) Return Reader.ReadBytes(CInt(Stream.Length)) End Using ' Reader End Using ' Stream End Using ' MemoryFile Catch exNoFile As IO.FileNotFoundException Throw Return Nothing Catch ex As Exception Throw End Try End Function |
。