C# 用一个文件实现对象的二进制序列化和缓存

本文介绍了一种固定大小的循环文件队列实现方案,该方案可在文件达到预设大小时从头开始覆盖,适用于数据缓存和持久化场景。

应用场景

    在通讯中,收发数据都应该先放到队列中,避免堵塞通讯,最好做持久化,避免因队列满或程序退出造成丢数,就像RabbitMQ这类中间件那样,这里我们手搓一个用于做对象持久化到文件的辅助类。

实现思路

    开辟一个文件,同时支持读和写,设置大小上限,当文件达到上限时从头覆盖写入,如此往复,如果文件大小足够大,就能够在无法转发那段时间把数据都缓存起来,并记录转发的断点,当通讯恢复时继续转发。

关键点

    1. 在一个FileStream中同时记录读位置和写位置,而流本身只有一个Position,因此算法需要小心处理读写位置的计算;

    2.不允许读位置先于写位置,即当读位置等于写位置时停止读;

    3.当写覆盖了未读数据时,要将读位置向前移动,即丢弃未读的旧数据,发生这种情况意味着文件大小不足以缓存无法转发的所有数据;

    4.关闭流之前,在文件的末尾保存读位置和写位置。

实现代码

using System;
using System.IO;

namespace Arim.DataX.Core
{
    /// <summary>
    /// 固定大小的文件,当写到底时从头开始覆盖.
    /// </summary>
    public class FixLengthFile
    {
        private readonly long maxLength;
        private readonly string fileName;
        private readonly object lockthis;
        private System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter;
        public FixLengthFile(string name, long length)
        {
            fileName = name;
            maxLength = length;
            lockthis = new object();
            formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        }

        //读写位置.
        private BinaryWriter writer;
        private BinaryReader reader;
        private bool opened = false;
        private const int TAIL16 = 16;//文件尾保留16字节存储readpos和writepos.
        private long readPos = 0, writePos = 0;
        public void Open()
        {
            if (!opened)
            {
                lock (lockthis)
                {
                    var stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                    writer = new BinaryWriter(stream);
                    reader = new BinaryReader(stream);
                    var length = reader.BaseStream.Le
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值