c# 二进制文件读取助手

可以快速读写二进制文件

调用示例如下

 static void Main(string[] args)
        {

            string targetFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.b2f");

            using (var writer = new IdxInfoWriter(targetFile))
            {

                for (int i = 0; i < 10; i++)
                {
                    writer.AppendItem(new IdxInfo
                    {
                        DataLength = i + 100,
                        Offset = 0,
                        Time = DateTime.Now,
                    });
                }
            }


            using (var reader = new IdxInfoReader(targetFile))
            {
                var all = reader.GetFileResult();
                all?.ForEach(f =>
                {
                    Console.WriteLine($"Time:{f.Time},offset:{f.Offset},Datalength:{f.DataLength}");
                });
            }
        }

        class IdxInfoWriter : BaseBinaryFileWriter<IdxInfo>
        {
            public IdxInfoWriter(string file) : base(file)
            {
            }
        }
        class IdxInfoReader : BaseBinaryFileReader<IdxInfo>
        {
            public IdxInfoReader(string file) : base(file)
            {
            }
        }


        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct IdxInfo
        {
            public DateTime Time { set; get; }
            public long Offset { set; get; }
            public int DataLength { set; get; }

        }

 

读取类:::

 public abstract class BaseBinaryFileReader<T> : IDisposable where T : struct
    {
        protected uint HeaderSize { set; get; }

        protected BinaryReader m_BinaryReader;
        protected readonly uint m_ItemSize;
        public uint ItemSize { get { return m_ItemSize; } }

        protected readonly string m_File;

        public BaseBinaryFileReader(string file, bool isReadOnly = false)
        {
            if (string.IsNullOrEmpty(file) || !File.Exists(file))
            {
                throw new FileNotFoundException($"{file}");
            }
            m_BinaryReader = new BinaryReader(GetFileStream(file, isReadOnly));
            if (m_BinaryReader == null)
            {

                throw new ArgumentNullException();
            }
            m_ItemSize = (uint)Marshal.SizeOf(typeof(T));
            m_File = file;
        }

        public BaseBinaryFileReader(string file, uint headSize, bool isReadOnly = false) : this(file, isReadOnly)
        {
            HeaderSize = headSize;
        }

        public static Stream GetFileStream(string sourceFile, bool isOnlyRead = false)
        {
            if (string.IsNullOrEmpty(sourceFile))
            {
                throw new ArgumentNullException();
            }
            
            try
            {
                if (isOnlyRead)
                {
                    //只读文件
                    return new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
                }
                else
                {
                    //可读取正在写入的文件
                    return new FileStream(sourceFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
                }
            }
            catch (Exception)
            {

                //只读文件
                return new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            }
        }

        /// <summary>
        /// 获取点的总数量
        /// </summary>
        /// <returns></returns>
        public uint GetTotalPoint()
        {
            if (m_BinaryReader == null)
            {
                return 0;
            }
            return (uint)((m_BinaryReader.BaseStream.Length - HeaderSize) / m_ItemSize);
        }

        protected const int PatchReadMinCount = 100;

        /// <summary>
        /// 按文件实际数量读取
        /// </summary>
        /// <param name="skipCount">跳过的点数</param>
        /// <param name="takeCount">要取到的点数</param>
        /// <param name="totalCount">总点数</param>
        /// <returns></returns>
        public virtual List<T> GetFileResult(uint skipCount = 0, uint takeCount = uint.MaxValue)
        {
            var res = new List<T>();

            var totalCount = GetTotalPoint();

            if (skipCount < totalCount)
            {
                ReadItems(res, skipCount, takeCount);
            }
            return res;
        }

        public virtual List<BinaryItemDetail<T>> GetFileResultDetail(uint skipCount, uint takeCount)
        {
            var res = new List<BinaryItemDetail<T>>();

            var totalCount = GetTotalPoint();

            if (skipCount < totalCount)
            {
                ReadItems(res, skipCount, takeCount);
            }

            return res;
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="res"></param>
        /// <param name="skipCount">跳过的点数</param>
        /// <param name="takeCount">要取的点数</param>
        protected virtual void ReadItems(List<BinaryItemDetail<T>> res, uint skipCount, uint takeCount)
        {
            if (takeCount == 0)
            {
                return;
            }
            long tarPos = HeaderSize;
            tarPos += m_ItemSize * skipCount;

            if (!CanReadNext(tarPos))
            {
                return;
            }

            int buffSize = (int)(m_ItemSize * Math.Min(PatchReadMinCount, takeCount));
            byte[] buffArr = new byte[buffSize];

            var fs = m_BinaryReader.BaseStream;
            fs.Position = tarPos;
            while (true)
            {
                if (res.Count >= takeCount)
                {
                    break;
                }
                if (!CanReadNext(fs.Position))
                {
                    break;
                }
                var startPos = m_BinaryReader.BaseStream.Position;
                var readLen = m_BinaryReader.Read(buffArr, 0, buffSize);
                if (readLen == 0)
                {
                    break;
                }

                var items = ByteHelper.BytesToStruct<T>(buffArr, 0, readLen);
                foreach (var item in items)
                {
                    res.Add(new BinaryItemDetail<T> { Offset = startPos, Content = item });
                    if (res.Count >= takeCount)
                    {
                        break;
                    }
                    startPos += m_ItemSize;
                }
            }
        }

        protected virtual void ReadItems(List<T> res, uint skipCount, uint takeCount)
        {
            if (takeCount == 0)
            {
                return;
            }
            long tarPos = HeaderSize;
            tarPos += m_ItemSize * skipCount;

            if (!CanReadNext(tarPos))
            {
                return;
            }

            int buffSize = (int)(m_ItemSize * Math.Min(PatchReadMinCount, takeCount));
            byte[] buffArr = new byte[buffSize];

            var fs = m_BinaryReader.BaseStream;
            fs.Position = tarPos;
            while (true)
            {
                if (res.Count >= takeCount)
                {
                    break;
                }
                if (!CanReadNext(fs.Position))
                {
                    break;
                }

                var readLen = m_BinaryReader.Read(buffArr, 0, buffSize);
                if (readLen == 0)
                {
                    break;
                }

                var items = ByteHelper.BytesToStruct<T>(buffArr, 0, readLen);
                foreach (var item in items)
                {
                    res.Add(item);
                    if (res.Count >= takeCount)
                    {
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// 从当前位置开始读取
        /// </summary>
        /// <returns></returns>
        public virtual T? ReadItem()
        {
            if (CanReadNext(m_BinaryReader.BaseStream.Position))
            {
                T item;
                if (ByteHelper.ReadStruct(m_BinaryReader, out item))
                {
                    return item;
                }
            }
            return null;
        }

        /// <summary>
        /// 从指定位置开始读取
        /// </summary>
        /// <param name="offset"></param>
        /// <returns></returns>
        public virtual T? ReadItem(long offset)
        {
            if (CanReadNext(offset))
            {
                m_BinaryReader.BaseStream.Position = offset;
                T item;
                if (ByteHelper.ReadStruct(m_BinaryReader, out item))
                {
                    return item;
                }
            }
            return null;
        }

        protected bool CanReadNext(long offset)
        {
            return offset + m_ItemSize <= m_BinaryReader.BaseStream.Length;
        }

        protected virtual BinaryItemDetail<T> ReadFirst()
        {
            long tarPos = HeaderSize;
            var res = ReadItem(tarPos);

            if (res != null)
            {
                return new BinaryItemDetail<T> { Offset = tarPos, Content = res.Value };
            }

            return null;
        }

        protected virtual BinaryItemDetail<T> ReadLast(ref uint acutalTotal)
        {
            var index = GetTotalPoint();
            if (index <= 0)
            {
                return null;
            }

            T? res = null;
            long tarPos = 0;
            while (true)
            {
                index--;
                if (index < 0)
                {
                    break;
                }
                tarPos = HeaderSize + index * m_ItemSize;
                if (tarPos < 0)
                {
                    break;
                }
                res = ReadItem(tarPos);
                if (res != null)
                {
                    break;
                }
            }
            if (index >= 0)
            {
                acutalTotal = index + 1;
            }
            if (res != null)
            {
                return new BinaryItemDetail<T> { Offset = tarPos, Content = res.Value };
            }
            return null;
        }

        protected int GetIndex(BinaryItemDetail<T> item)
        {
            if (item != null)
            {
                var res = (item.Offset - HeaderSize) / m_ItemSize;
                return (int)res;
            }

            return -1;
        }


        protected virtual void ResetFilePostion()
        {
            if (m_BinaryReader != null)
            {
                m_BinaryReader.BaseStream.Position = 0;
            }
        }

        public void Dispose()
        {
            m_BinaryReader?.Close();
        }
        
    }
    
    public class BinaryItemDetail<T> where T : struct
    {
        public long Offset { set; get; }
        public T Content { set; get; }
    }
 

 

写入类

 public class BaseBinaryFileWriter<T> : IDisposable where T : struct
    {
        protected readonly string m_TargetFile;

        protected BinaryWriter m_MVIdxBinaryWriter;
        protected Random rdm = new Random();

        public BaseBinaryFileWriter(string file)
        {
            if (string.IsNullOrEmpty(file))
            {
                throw new ArgumentNullException();
            }
            m_TargetFile = file;

            if (File.Exists(file))
            {
                File.Delete(file);
            }

            var fileInfo = new FileInfo(file);
            Directory.CreateDirectory(fileInfo.DirectoryName);

            var m_SyncIdxFileStream = new FileStream(m_TargetFile, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite);
            m_MVIdxBinaryWriter = new BinaryWriter(m_SyncIdxFileStream);

            WriteContent(WriterHeader);
        }

        protected virtual void WriterHeader()
        {
         
        }

        protected void WriteContent(Action act, bool needRefreshToDisk = true)
        {
            if (needRefreshToDisk)
            {
                var fs = (m_MVIdxBinaryWriter.BaseStream as FileStream);
                act?.Invoke();
                fs.Flush(true);
            }
            else
            {
                act?.Invoke();
            }
        }

        public virtual void AppendItems(List<T> dtItems)
        {
            WriteContent(() =>
            {
                dtItems?.ForEach(f =>
                {
                    m_MVIdxBinaryWriter.Write(ByteHelper.StructToBytes(f));
                });
            });
        }
        public virtual void AppendItem(T f)
        {
            AppendItems(new List<T> { f });
        }
        public virtual void Close()
        {
            m_MVIdxBinaryWriter?.Close();
        }

        public void Dispose()
        {
            Close();
        }
    }

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值