使用IEnumerators检查反序列化的进度

时间:2017-05-01 13:23:53

标签: c# unity3d deserialization binaryformatter

public static object Deserialize(string path)
{
    using (Stream stream = File.Open(path, FileMode.Open))
    {
        BinaryFormatter bformatter = new BinaryFormatter();
        return bformatter.Deserialize(stream);
    }
}
SomeClass someObject = (SomeClass)Deserialize(savePath);

我想创建一个包含自身进度的反序列化过程。 所以可能某种IEnumerator每帧更新我的进度字段。 是否可以在读取文件时跟踪Formatter的位置?

当我反序列化大文件时,我想知道它是怎么回事......

1 个答案:

答案 0 :(得分:6)

我认为最简单的方法是通过包装正在反序列化的Stream来跟踪它,并在Formatter读取它时跟踪位置。

public class ReadProgressStream : ContainerStream
    {
        private int _lastProgress = 0;

        public ReadProgressStream(Stream stream) : base(stream) 
        {
            if (stream.Length <= 0 || !stream.CanRead) throw new ArgumentException("stream");
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int amountRead = base.Read(buffer, offset, count);
            if (ProgressChanged != null)
            {
                int newProgress = (int)(Position * 100.0 / Length);
                if (newProgress > _lastProgress)
                {
                    _lastProgress = newProgress;
                    ProgressChanged(this, new ProgressChangedEventArgs(_lastProgress, null));
                }
            }
            return amountRead;
        }

        public event ProgressChangedEventHandler ProgressChanged;
    }

用法:

public static T Deserialize<T>(
  Stream stream, ProgressChangedEventHandler callback)
{
  using (ReadProgressStream rps = new ReadProgressStream(stream))
  using (BufferedStream bs = new BufferedStream(rps))
  {
    rps.ProgressChanged += callback;
    BinaryFormatter formatter = new BinaryFormatter();
    return (T)formatter.Deserialize(bs);
  }
}

ContainerStream:

public abstract class ContainerStream : Stream
    {
        private Stream _stream;

        protected ContainerStream(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            _stream = stream;
        }

        protected Stream ContainedStream { get { return _stream; } }

        public override bool CanRead { get { return _stream.CanRead; } }

        public override bool CanSeek { get { return _stream.CanSeek; } }

        public override bool CanWrite { get { return _stream.CanWrite; } }

        public override void Flush() { _stream.Flush(); }

        public override long Length { get { return _stream.Length; } }

        public override long Position
        {
            get { return _stream.Position; }
            set { _stream.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return _stream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return _stream.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            _stream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _stream.Write(buffer, offset, count);
        }
    }