应用场景
在通讯中,收发数据都应该先放到队列中,避免堵塞通讯,最好做持久化,避免因队列满或程序退出造成丢数,就像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

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

被折叠的 条评论
为什么被折叠?



