菜菜的漲工資申請還在待審批中....數組
做爲一個技術人員,技術的問題仍是要解決。通過線上日誌的分析,日誌採用小時機制,一個小時一個日誌文件,同一個小時的日誌文件有多個,也就是說同一時間內的日誌有可能分散在多個日誌文件中,這也是Y總要合併的主要緣由。每一個日誌文件大約有500M,大約有100個。此時,若是你閱讀到此文章,該怎麼作呢?不如先靜心想2分鐘!!bash
要想實現Y總的需求其實仍是有幾個難點的:數據結構
那咱們該怎麼作呢?其中一個解決方案就是它:堆asp.net
堆(英語:heap)是計算機科學中一類特殊的數據結構的統稱。堆一般是一個能夠被看作一棵樹的數組對象。堆老是知足下列性質:測試
對於每一個節點的值都大於等於子樹中每一個節點值的堆,咱們叫做「大頂堆」。對於每一個節點的值都小於等於子樹中每一個節點值的堆,咱們叫做「小頂堆」。 ui
徹底二叉樹比較適合用數組來存儲(鏈表也能夠實現)。爲何這麼說呢?用數組來存儲徹底二叉樹是很是節省存儲空間的。由於咱們不須要存儲左右子節點的指針,單純地經過數組的下標,就能夠找到一個節點的左右子節點和父節點。 this
如下代碼通過少量修改甚至不修改的狀況下可直接在生產環境應用spa
/// <summary>
/// 小頂堆,T類型須要實現 IComparable 接口
/// </summary>
class MinHeap<T> where T : IComparable
{
private T[] container; // 存放堆元素的容器
private int capacity; // 堆的容量,最大能夠放多少個元素
private int count; // 堆中已經存儲的數據個數
public MinHeap(int _capacity)
{
container = new T[_capacity + 1];
capacity = _capacity;
count = 0;
}
//插入一個元素
public bool AddItem(T item)
{
if (count >= capacity)
{
return false;
}
++count;
container[count] = item;
int i = count;
while (i / 2 > 0 && container[i].CompareTo(container[i / 2]) < 0)
{
// 自下往上堆化,交換 i 和i/2 元素
T temp = container[i];
container[i] = container[i / 2];
container[i / 2] = temp;
i = i / 2;
}
return true;
}
//獲取最小的元素
public T GetMinItem()
{
if (count == 0)
{
return default(T);
}
T result = container[1];
return result;
}
//刪除最小的元素,即堆頂元素
public bool DeteleMinItem()
{
if (count == 0)
{
return false;
}
container[1] = container[count];
container[count] = default(T);
--count;
UpdateHeap(container, count, 1);
return true;
}
//從某個節點開始從上向下 堆化
private void UpdateHeap(T[] a, int n, int i)
{
while (true)
{
int maxPos = i;
//遍歷左右子樹,肯定那個是最小的元素
if (i * 2 <= n && a[i].CompareTo(a[i * 2]) > 0)
{
maxPos = i * 2;
}
if (i * 2 + 1 <= n && a[maxPos].CompareTo(a[i * 2 + 1]) > 0)
{
maxPos = i * 2 + 1;
}
if (maxPos == i)
{
break;
}
T temp = container[i];
container[i] = container[maxPos];
container[maxPos] = temp;
i = maxPos;
}
}
}
複製代碼
//由於須要不停的從log文件讀取內容,因此須要一個和log文件保持鏈接的包裝
class LogInfoIndex : IComparable
{
//標誌內容來自於哪一個文件
public int FileIndex { get; set; }
//具體的日誌文件內容
public LogInfo Data { get; set; }
public int CompareTo(object obj)
{
var tempInfo = obj as LogInfoIndex;
if (this.Data.Index > tempInfo.Data.Index)
{
return 1;
}
else if (this.Data.Index < tempInfo.Data.Index)
{
return -1;
}
return 0;
}
}
class LogInfo
{
//用int來模擬datetime 類型,由於用int 看的最直觀
public int Index { get; set; }
public string UserName { get; set; }
}
複製代碼
static void WriteFile()
{
int fileCount = 0;
while (fileCount < 10)
{
string filePath = $@"D:\log\{fileCount}.txt";
int index = 0;
while (index < 100000)
{
LogInfo info = new LogInfo() { Index = index, UserName = Guid.NewGuid().ToString() };
File.AppendAllText(filePath, JsonConvert.SerializeObject(info)+ "\r\n");
index++;
}
fileCount++;
}
}
複製代碼
文件內容以下: .net
static void Main(string[] args)
{
int heapItemCount = 10;
int startIndex = 0;
StreamReader[] allReader = new StreamReader[10];
MinHeap<LogInfoIndex> container = new MinHeap<LogInfoIndex>(heapItemCount);
//首先每一個文件讀取一條信息
while(startIndex< heapItemCount)
{
string filePath = $@"D:\log\{startIndex}.txt";
System.IO.StreamReader reader = new System.IO.StreamReader(filePath);
allReader[startIndex] = reader;
string content= reader.ReadLine();
var contentObj = JsonConvert.DeserializeObject<LogInfo>(content);
LogInfoIndex item = new LogInfoIndex() { FileIndex= startIndex , Data= contentObj };
container.AddItem(item);
startIndex++;
}
//而後開始循環出堆,入堆
while (true)
{
var heapFirstItem = container.GetMinItem();
if (heapFirstItem == null)
{
break;
}
container.DeteleMinItem();
File.AppendAllText($@"D:\log\total.txt", JsonConvert.SerializeObject(heapFirstItem.Data) + "\r\n");
var nextContent = allReader[heapFirstItem.FileIndex].ReadLine();
if (string.IsNullOrWhiteSpace( nextContent))
{
//若是其中一個文件已經讀取完畢 則跳過
continue;
}
var contentObj = JsonConvert.DeserializeObject<LogInfo>(nextContent);
LogInfoIndex item = new LogInfoIndex() { FileIndex = heapFirstItem.FileIndex, Data = contentObj };
container.AddItem(item);
}
//釋放StreamReader
foreach (var reader in allReader)
{
reader.Dispose();
}
Console.WriteLine("完成");
Console.Read();
}
複製代碼
結果以下: 3d
添加關注,查看更精美版本,收穫更多精彩