using System; using System.IO; using System.Threading; namespace XGame.Framework.Logger { internal class LogWriter : ILogWriter, IDisposable { private LogType _logType; private MMFile _mmfile; private ILogCompressor _compressor; public object _syncRoot; private object SyncRoot { get { if (this._syncRoot == null) { //如果_syncRoot和null相等,将new object赋值给 _syncRoot //Interlocked.CompareExchange方法保证多个线程在使用 syncRoot时是线程安全的 Interlocked.CompareExchange(ref this._syncRoot, new object(), null); } return this._syncRoot; } } public LogWriter(LogType logType, MMFile mmfile, ILogCompressor compressor) { _logType = logType; _mmfile = mmfile; _compressor = compressor; } #region 接口实现 public void Write(string contents) { lock (this.SyncRoot) { contents += '\n'; var buffer = System.Text.Encoding.UTF8.GetBytes(contents); WriteToCache(buffer, 0, buffer.Length); } } public void Flush() { lock (this.SyncRoot) { WriteToFile(); _mmfile.Reset(); } } public void Dispose() { _mmfile.Dispose(); _mmfile = null; } #endregion private void WriteToFile() { try { var header = _mmfile.ReadHeader(); if (header.position <= 0) return; var buffer = _mmfile.ReadAll(); if (_compressor != null) { buffer = _compressor.Compress(buffer); } // 每次写入的时候都进行判断文件夹是否存在 var dirPath = GetLogDirectory(); var logFilePath = $"{dirPath}/{DateTime.UtcNow}{LogDefine.FileExtension}"; File.WriteAllBytes(logFilePath, buffer); } catch (Exception ex) { UnityEngine.Debug.LogException(ex); } } private void WriteToCache(byte[] buffer, int offset, int length) { try { if (!_mmfile.Write(buffer, offset, length)) { WriteToFile(); _mmfile.Reset(); WriteToCache(buffer, offset, length); } } catch (Exception ex) { UnityEngine.Debug.LogException(ex); } } private string GetLogDirectory() { var dirPath = _logType == LogType.Code ? LogDefine.CodeLogPath : LogDefine.EventLogPath; if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } return dirPath; } } }