本工具可实现的效果:

1.读取大文件(大于1GB)

2.根据分隔符分割后的列分组

3.速度快。

4.处理过程中,可以随时停止处理,操作不卡死。

5.有对当前内存的实时监测,避免过多占用内存,影响系统运行。

6.实时显示处理的行数。

处理类代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text; namespace DaZhongLogTool
{ // 定义事件的参数类
public class ValueEventArgs : EventArgs
{
public int Value { set; get; }
}
// 定义事件使用的委托
public delegate void ValueChangedEnentHandler(object sender, ValueEventArgs e); public class BigFileTongJiJobs
{
long ALLOW_MAX_USED_MEMORY = 1024 * 1024 * 1024; //允许使用的最大内存,超过则结束 public bool StartFlag { get; set; } // 定义一个事件来提示界面工作的进度
public event ValueChangedEnentHandler ValueChanged; public void OnValueChange(ValueEventArgs e)
{
if (ValueChanged != null)
{
ValueChanged(this, e);
}
} /// <summary>
///
/// </summary>
/// <param name="paramsInfo"></param>
/// <returns>-1:未开始,就失败了;-2:文件不存在;-3,异常;大于0,处理成功</returns>
public int StartAnalyseBigFile(TongjiParamsInfoStruct paramsInfo)
{
int handleLine = -1; string sTmpFile = paramsInfo.outputPath;
if (File.Exists(sTmpFile))
{
File.Delete(sTmpFile);
} if (!System.IO.File.Exists(sTmpFile))
{
FileStream fs;
fs = File.Create(sTmpFile);
fs.Close();
} if (!File.Exists(paramsInfo.inputPath))
{
handleLine = -2;
return handleLine;
} FileStream streamInput = System.IO.File.OpenRead(paramsInfo.inputPath);
FileStream streamOutput = System.IO.File.OpenWrite(sTmpFile); int iRowCount = 0;
int iRowCharCount = 0;
List<byte> rowByteData = new List<byte>();//行字节List
Dictionary<string, int> tongjiDict = new Dictionary<string, int>(); //统计字典
string rowStr = ""; //获取当前进程对象
Process cur = Process.GetCurrentProcess();
//为获取当前进程使用的内存大小做准备
PerformanceCounter curpc = new PerformanceCounter("Process", "Working Set", cur.ProcessName);
string memoryUsedSize = "";
try
{
ValueEventArgs e;
int result; //根据当前进程使用内存的大小,决定是否继续分析日志文本
memoryUsedSize = string.Format("分析开始,本进程使用内存大小:{0} KB,Date:{1}", curpc.NextValue() / 1024, DateTime.Now);
streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes(memoryUsedSize), 0, System.Text.UTF8Encoding.UTF8.GetBytes(memoryUsedSize).Length);
streamOutput.WriteByte(13); //换行符 while ((result = streamInput.ReadByte()) != -1)
{ if (StartFlag == false)
{
streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes("强制停止分析"), 0, System.Text.UTF8Encoding.UTF8.GetBytes("强制停止分析").Length);
streamOutput.WriteByte(13);
break;
} if (result == 10)
continue;
iRowCharCount++;
rowByteData.Add((byte)result);
if (result == 13) //一行
{ //写入一次或者处理一次
rowStr = GetSpecificInfoFromLineText(rowByteData, paramsInfo.separator, paramsInfo.columnNum);
if (!string.IsNullOrEmpty(rowStr))
{
rowStr = rowStr.Length > 300 ? rowStr.Substring(0, 300) : rowStr;
if (tongjiDict.ContainsKey(rowStr))
tongjiDict[rowStr] = tongjiDict[rowStr] + 1;
else
tongjiDict[rowStr] = 1;
} if (iRowCount % 10000 == 0 || iRowCount<100) //不频繁的更新UI可以极大的提高处理的效率,如果每条都更新UI,将会非常慢
{
//占用内存大于1GB,则结束本次的分析
if (curpc.NextValue() > ALLOW_MAX_USED_MEMORY)//当前进程使用内存的大小大于1个GB,停止分析
{
break;
} e = new ValueEventArgs() { Value = iRowCount };
this.OnValueChange(e);
} iRowCount++; //统计处理的行数
iRowCharCount = 0;//本行的字符数
rowByteData.Clear();//清空本行数据
}
} if (tongjiDict.Count> 1)
{
//根据当前进程使用内存的大小,决定是否继续分析日志文本
memoryUsedSize = string.Format("分析结束:本进程使用内存大小:{0} KB,Date:{1},分组个数:{2}", curpc.NextValue() / 1024, DateTime.Now,tongjiDict.Count);
streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes(memoryUsedSize), 0, System.Text.UTF8Encoding.UTF8.GetBytes(memoryUsedSize).Length);
streamOutput.WriteByte(13); //换行符
} streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes("本次处理的文本对象是"), 0, System.Text.UTF8Encoding.UTF8.GetBytes("本次处理的文本对象是").Length);
streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes(paramsInfo.inputPath), 0, System.Text.UTF8Encoding.UTF8.GetBytes(paramsInfo.inputPath).Length);
streamOutput.WriteByte(13); string temLine;
foreach (var item in tongjiDict.OrderByDescending(t => t.Value))
{
temLine = string.Format("统计次数Value:{0}\t Key: {1}", item.Value, item.Key);
streamOutput.Write(System.Text.UTF8Encoding.UTF8.GetBytes(temLine), 0, System.Text.UTF8Encoding.UTF8.GetBytes(temLine).Length);
streamOutput.WriteByte(13); //换行符
}
//更新处理到最后一条的文字提示状态
e = new ValueEventArgs() { Value = iRowCount };
this.OnValueChange(e);
}
finally
{
streamInput.Dispose();
streamOutput.Dispose();
} return iRowCount;
} //从文本行中提取特定信息
private string GetSpecificInfoFromLineText(List<byte> lineArr, string separator, int columnNum)
{
string result;
try
{
string lineStr;
string[] columnArr;
lineStr = System.Text.UTF8Encoding.UTF8.GetString(lineArr.ToArray());
//把文本中的 "\t",替换为分隔符 "\\t",原因是:输入的分隔符是:“\t”,为了避免被转移,系统自动把输入的分隔符变成了:“\\t”
//去掉\r后面或者前面的\n,避免输出的文本中根据\n换行
columnArr = lineStr.Replace("\t", "\\t").Replace('\n', ' ').Split(new string[] { separator }, StringSplitOptions.None);
if (columnArr.Length < columnNum)
{
return "";
}
result = columnArr[columnNum - 1];
}
catch (Exception)
{
result = "ExceptionLine";
//throw;
}
return result;
} } public struct TongjiParamsInfoStruct
{
public string inputPath { get; set; }
public string outputPath { get; set; }
public string separator { get; set; }
public int columnNum { get; set; } }
}

  调用代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace DaZhongLogTool
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
} Color originalTongJiButtonColor;
string originalTongJiButtonText; BigFileTongJiJobs tongjiJobs = new BigFileTongJiJobs(); private void btnTongJi_Click(object sender, EventArgs e)
{
if (tongjiJobs.StartFlag)
{
MessageBox.Show("正在处理中...,如需停止,请单击停止");
return;
} string errmsg;
if(string.IsNullOrEmpty(txtSeparator.Text))
{
MessageBox.Show("请输入分隔符");
return;
}
if (numericUpDown1.Value<1)
{
MessageBox.Show("请输入按照分隔符分割的待统计内容的对应的列数,从1开始");
return;
} string inputPath = txtInputPath.Text.Trim();
if (string.IsNullOrEmpty(inputPath))
{
MessageBox.Show("请输入等待统计的文本路径");
return;
}
if(!File.Exists(inputPath))
{
MessageBox.Show("待统计的文本文件不存在,请重新输入");
return;
} TongjiParamsInfoStruct paramsInfo = new TongjiParamsInfoStruct();
paramsInfo.inputPath = inputPath;
paramsInfo.outputPath = System.IO.Path.GetDirectoryName(inputPath)+@"\"+DateTime.Now.ToString("yyyyMMdd_HHmm")+"_result.log";
paramsInfo.separator = txtSeparator.Text;
paramsInfo.columnNum = (int)numericUpDown1.Value; originalTongJiButtonColor = this.btnTongJi.BackColor;
originalTongJiButtonText = this.btnTongJi.Text; ////开始分析前,改变按钮颜色及文字
//this.btnTongJi.Enabled = false;
//this.btnTongJi.BackColor = Color.Gray;
//this.btnTongJi.Text = "处理中……"; tongjiJobs.StartFlag = true;
tongjiJobs.ValueChanged += new ValueChangedEnentHandler(Line_ValueChange); Func<TongjiParamsInfoStruct, int> hander = new Func<TongjiParamsInfoStruct, int>(tongjiJobs.StartAnalyseBigFile);
hander.BeginInvoke(paramsInfo, new AsyncCallback(AsyncCallback1), hander); } // 结束异步操作
private void AsyncCallback1(IAsyncResult ar)
{
// 标准的处理步骤
Func<TongjiParamsInfoStruct, int> handler = ar.AsyncState as Func<TongjiParamsInfoStruct, int>;
int result= handler.EndInvoke(ar); if (result>0)
{
MessageBox.Show("本次成功处理了" + result + "行数据", "成功");
}
else if (result == -2)
{
MessageBox.Show("文件不存在,请重新选择");
}
toolStripStatusLabel1.Text = "上次任务处理完毕,等待下次开始。" + DateTime.Now.ToString(); tongjiJobs.StartFlag = false;//处理过程停止 //恢复按钮颜色及文字
//this.btnTongJi.Enabled = true;
//this.btnTongJi.BackColor = originalTongJiButtonColor;
//this.btnTongJi.Text = originalTongJiButtonText; } private void Line_ValueChange(object sender ,ValueEventArgs e)
{
toolStripStatusLabel1.Text = string.Format("统计中……,已处理了{0}行日志,时间:{1}", e.Value, DateTime.Now);
} private void btnSelectFile_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Multiselect = false;
fileDialog.Filter = "(*.*)|*.*";
fileDialog.RestoreDirectory = false; if (fileDialog.ShowDialog() == DialogResult.OK)
{
try
{
txtInputPath.Text=fileDialog.FileName;
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
} private void btnStopTongJi_Click(object sender, EventArgs e)
{
//点击停止按钮
tongjiJobs.StartFlag = false;
} } }

  该工具,是来自于实际工作的需求,用于根据某一列统计次数。简单实用。

源代码下载:【源码大文件分组统计简单工具          【EXE】大文件分组统计简单工具

需要的小伙伴尽管拿走,不要忘记推荐一下,谢谢

【.Net】 大文件可使用的文本分组统计工具(附带源码,原创)的更多相关文章

  1. 一篇文章看懂TPCx-BB(大数据基准测试工具)源码

    TPCx-BB是大数据基准测试工具,它通过模拟零售商的30个应用场景,执行30个查询来衡量基于Hadoop的大数据系统的包括硬件和软件的性能.其中一些场景还用到了机器学习算法(聚类.线性回归等).为了 ...

  2. 鸿蒙内核源码分析(文件句柄篇) | 深挖应用操作文件的细节 | 百篇博客分析OpenHarmony源码 | v69.01

    百篇博客系列篇.本篇为: v69.xx 鸿蒙内核源码分析(文件句柄篇) | 深挖应用操作文件的细节 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说 ...

  3. java 导出 excel 最佳实践,java 大文件 excel 避免OOM(内存溢出) excel 工具框架

    产品需求 产品经理需要导出一个页面的所有的信息到 EXCEL 文件. 需求分析 对于 excel 导出,是一个很常见的需求. 最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件. 客 ...

  4. arcgis api 3.x for js 解决 textSymbol 文本换行显示(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  5. 鸿蒙内核源码分析(源码结构篇) | 内核每个文件的含义 | 百篇博客分析OpenHarmony源码 | v18.04

    百篇博客系列篇.本篇为: v18.xx 鸿蒙内核源码分析(源码结构篇) | 内核每个文件的含义 | 51.c.h .o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...

  6. iOS富文本组件的实现—DTCoreText源码解析 数据篇

    本文转载 http://blog.cnbang.net/tech/2630/ DTCoreText是个开源的iOS富文本组件,它可以解析HTML与CSS最终用CoreText绘制出来,通常用于在一些需 ...

  7. 分享一个文件查找、替换制定的字符或数字之CS程序、附带源码

    首先就上操作流程图: 图--登陆界面.登陆密码:alidoing.com 图--界面说明(一看就懂) 图--文件查找到再替换 图--文件替换成功 图--替换后的文件 代码开始: 登陆的代码就非常简单. ...

  8. 图解DevExpress RichEditControl富文本的使用,附源码及官方API

    9点半了,刚写到1.2.   该回家了,明天继续写完. 大家还需要什么操作,留言说一下,没有的我明天继续加. 好久没有玩DevExpress了,今天下载了一个玩玩,发现竟然更新到14.2.5了..我去 ...

  9. Python对文本读写的操作方法【源码】

    Dear ALL 今天给大家分享的是 TXT文本读写方式,也是文件操作最常用的一种方式,主要内容有: 文件写方法 文件读方法 with open() as f 方法 话不多说,码上见: ''' 标题: ...

随机推荐

  1. 什么是FPGA的HP,HR I/O

    什么是FPGA的HP,HR I/O HP接口为高速接口,用于存储器或者芯片与芯片之间的接口,HR可以接受很宽的电平标准.

  2. 学习笔记之Python爬虫

    Python 爬虫介绍 | 菜鸟教程 http://www.runoob.com/w3cnote/python-spider-intro.html https://blog.csdn.net/sina ...

  3. [UE4]UMG小结

    一.当没有需要的UI怎么办?先别急着自己定制,可以到虚幻商城去看看,各种类型的UI都有,而且价格都不贵. 二.推荐一个比较有参考价值的UI:User Interface Kit,里面的UI很多,还有小 ...

  4. Linux报错:bash: pip: command not found

    $ wget https://bootstrap.pypa.io/get-pip.py$ python get-pip.py$ pip -V #查看pip版本 接下来就可以随便pip安装东西了

  5. Android控件使用FragmentTabHost,切换Fragment;

    大部分APP的主界面都很类似,要么底部导航的,要么就是侧滑菜单,还有底部导航+侧滑菜单的:底部导航实现大概有几种方式: TabHost+Fragment RadioGroup+Fragment Fra ...

  6. day34进程相关

    进程1 什么是进程    进程指的是一个正在进行/运行的程序,进程是用来描述程序执行过程的虚拟概念    进程vs程序    程序:一堆代码    进程:程序的执行的过程    进程的概念起源于操作系 ...

  7. windows:plsql配置oracle连接

    1.plsql安装 此处省略,后续添加 2.plsql连接oracle: (1) 下载Instant client:http://www.oracle.com/technetwork/cn/topic ...

  8. python中的第三方日志模块logging

    基本上每个系统都有自己的日志系统,可以使自己写的,也可以是第三方的.下面来简单介绍一下python中第三方的日志模块,入手还是比较简单的,但是也很容易给自己埋雷. 下面是我参考的资料链接 入手demo ...

  9. Tomcat的目录结构详细介绍(超全)

    打开tomcat的解压之后的目录可以看到如下的目录结构:  1.bin: bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(w ...

  10. Lock的实现原理

    1. Lock 的简介及使用 Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制.本质上Lock仅仅是一个接口(位于源码包中的java\util\concurrent\l ...