MemoryMappedFile的初级应用
1 public class SyncMemoryList<T>: SyncList<T>, IDisposable 2 { 3 private MemoryCache<T> _memoryCache = new MemoryCache<T>(); 4 5 public new void Add(T item) 6 { 7 string json = $"{ToJson(item)}\n"; 8 WriteCache(json); 9 10 base.Add(item); 11 } 12 13 private string ToJson(T item) 14 { 15 Type type = typeof(T); 16 if (type.IsClass) 17 return JsonExtensions.ToJson(item); 18 else 19 return item.ToString(); 20 } 21 22 private void WriteCache(string text) 23 { 24 byte[] bytes = Encoding.UTF8.GetBytes(text); 25 if (_memoryCache.IsAllowWrite(bytes.Length)) 26 { 27 _memoryCache.Write(bytes); 28 } 29 else 30 { 31 _memoryCache.Dispose(); 32 _memoryCache = new MemoryCache<T>(); 33 _memoryCache.Write(bytes); 34 } 35 } 36 37 #region IDisposable Support 38 private bool disposedValue = false; // 要检测冗余调用 39 40 protected virtual void Dispose(bool disposing) 41 { 42 if (!disposedValue) 43 { 44 if (disposing) 45 { 46 // TODO: 释放托管状态(托管对象)。 47 } 48 49 _memoryCache?.Dispose(); 50 disposedValue = true; 51 } 52 } 53 54 // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。 55 // ~SyncMemoryList() { 56 // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 57 // Dispose(false); 58 // } 59 60 // 添加此代码以正确实现可处置模式。 61 public void Dispose() 62 { 63 // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。 64 Dispose(true); 65 // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。 66 // GC.SuppressFinalize(this); 67 } 68 #endregion 69 } 70 71 internal class MemoryCache<T>:IDisposable 72 { 73 private readonly MemoryMappedFile _memoryMapped = null; 74 private readonly MemoryMappedViewStream _stream = null; 75 private static readonly long _defaultSize = 1024 * 1024; 76 private readonly long _capatity = 0; 77 public MemoryCache() 78 { 79 string mapname = $"{typeof(T).Name}"; 80 string fileName = $"{typeof(T).Name}_{DateTime.Now:yyyy_M_d}.dat"; 81 long maxlen = 0; 82 if (File.Exists(fileName)) 83 { 84 (long size,long offset) = (0, 0); 85 FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); 86 (size,offset) = GetFileInfo(stream); 87 //stream.Close(); 88 maxlen = size + _defaultSize; 89 _memoryMapped = MemoryMappedFile.CreateFromFile(stream, mapname, maxlen, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false); 90 _stream = _memoryMapped.CreateViewStream(); 91 _stream.Position = offset == 0 ? 16 : offset; 92 } 93 else 94 { 95 maxlen = _defaultSize + 16; 96 _memoryMapped = MemoryMappedFile.CreateFromFile(fileName, FileMode.OpenOrCreate, mapname, maxlen, MemoryMappedFileAccess.ReadWrite); 97 _stream = _memoryMapped.CreateViewStream(); 98 _stream.Position = 16; 99 } 100 101 _capatity = maxlen - 16; 102 } 103 104 public long Position => _stream.Position; 105 106 private (long, long) GetFileInfo(Stream stream) 107 { 108 try 109 { 110 byte[] byteSize = new byte[8]; 111 byte[] byteOffset = new byte[8]; 112 113 stream.Read(byteSize, 0, byteSize.Length); 114 stream.Read(byteOffset, 0, byteOffset.Length); 115 116 return (BitConverter.ToInt64(byteSize, 0), BitConverter.ToInt64(byteOffset, 0)); 117 } 118 catch (Exception e) 119 { 120 return (_defaultSize, 0); 121 } 122 } 123 124 public bool IsAllowWrite(long size) 125 { 126 return _capatity - _stream.Position > size; 127 } 128 129 public void WriteLength(long offset) 130 { 131 byte[] byteSize = BitConverter.GetBytes(_capatity); 132 byte[] byteOffset = BitConverter.GetBytes(offset); 133 _stream.Position = 0; 134 _stream.Write(byteSize, 0, byteSize.Length); 135 _stream.Write(byteOffset, 0, byteOffset.Length); 136 } 137 138 public void Write(byte[] bytes) 139 { 140 var _offset = _stream.Position; 141 WriteLength(_offset + bytes.Length); 142 _stream.Position = _offset; 143 _stream.Write(bytes, 0, bytes.Length); 144 } 145 146 public void Dispose() 147 { 148 _memoryMapped?.Dispose(); 149 _stream?.Dispose(); 150 } 151 }