【转】C#大文件读取和查询--内存映射
笔者最近需要快速查询日志文件,文件大小在4G以上。
需求如下:
1.读取4G左右大小的文件中的指定行,程序运行占用内存不超过500M。
2.希望查询1G以内容,能控制在20s左右.
刚开始觉得这个应该不难.研究一天之后,发现这个需要使用内存映射技术。
查阅了相关资料之后
发现还是有一定的复杂性.特别是需要对字符处理。
笔者自己写了一个Demo,希望实现
很遗憾,测试结果,查询1G左右的内容,花费时间在100s左右.
程序如下:
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Text; namespace ConsoleDemo
{
class Program
{
private const string TXT_FILE_PATH = @"E:\开源学习\超大文本文件读取\File\a.txt";
private const string SPLIT_VARCHAR = "囧";
private const char SPLIT_CHAR = '囧';
private static long FILE_SIZE = 0;
static void Main(string[] args)
{
//long ttargetRowNum = 39999999;
long ttargetRowNum = 10000000;
DateTime beginTime = DateTime.Now;
string line = CreateMemoryMapFile(ttargetRowNum);
double totalSeconds = DateTime.Now.Subtract(beginTime).TotalSeconds;
Console.WriteLine(line);
Console.WriteLine(string.Format("查找第{0}行,共耗时:{1}s", ttargetRowNum, totalSeconds));
Console.ReadLine();
} /// <summary>
/// 创建内存映射文件
/// </summary>
private static string CreateMemoryMapFile(long ttargetRowNum)
{
string line = string.Empty;
using (FileStream fs = new FileStream(TXT_FILE_PATH, FileMode.Open, FileAccess.ReadWrite))
{
long targetRowNum = ttargetRowNum + 1;//目标行
long curRowNum = 1;//当前行
FILE_SIZE = fs.Length;
using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(fs, "test", fs.Length, MemoryMappedFileAccess.ReadWrite, null, HandleInheritability.None, false))
{
long offset = 0;
//int limit = 250;
int limit = 200;
try
{
StringBuilder sbDefineRowLine = new StringBuilder();
do
{
long remaining = fs.Length - offset;
using (MemoryMappedViewStream mmStream = mmf.CreateViewStream(offset, remaining > limit ? limit : remaining))
//using (MemoryMappedViewStream mmStream = mmf.CreateViewStream(offset, remaining))
{
offset += limit;
using (StreamReader sr = new StreamReader(mmStream))
{
//string ss = sr.ReadToEnd().ToString().Replace("\n", "囧").Replace(Environment.NewLine, "囧");
string ss = sr.ReadToEnd().ToString().Replace("\n", SPLIT_VARCHAR).Replace(Environment.NewLine, SPLIT_VARCHAR);
if (curRowNum <= targetRowNum)
{
if (curRowNum < targetRowNum)
{
string s = sbDefineRowLine.ToString();
int pos = s.LastIndexOf(SPLIT_CHAR);
if (pos > 0)
sbDefineRowLine.Remove(0, pos); }
else
{
line = sbDefineRowLine.ToString();
return line;
}
if (ss.Contains(SPLIT_VARCHAR))
{
curRowNum += GetNewLineNumsOfStr(ss);
sbDefineRowLine.Append(ss);
}
else
{
sbDefineRowLine.Append(ss);
}
}
//sbDefineRowLine.Append(ss);
//line = sbDefineRowLine.ToString();
//if (ss.Contains(Environment.NewLine))
//{
// ++curRowNum;
// //curRowNum++;
// //curRowNum += GetNewLineNumsOfStr(ss);
// //sbDefineRowLine.Append(ss);
//}
//if (curRowNum == targetRowNum)
//{
// string s = "";
//} sr.Dispose();
} mmStream.Dispose();
}
} while (offset < fs.Length);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return line;
}
}
} private static long GetNewLineNumsOfStr(string s)
{
string[] _lst = s.Split(SPLIT_CHAR);
return _lst.Length - 1;
}
}
}
欢迎大家提供更好的解决思路.
参考资料:
https://msdn.microsoft.com/zh-cn/library/dd997372(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
http://blog.csdn.net/onejune2013/article/details/7577152
转自:http://www.cnblogs.com/lucky_hu/p/5345423.html
【转】C#大文件读取和查询--内存映射的更多相关文章
- C#大文件读取和查询--内存映射
笔者最近需要快速查询日志文件,文件大小在4G以上. 需求如下: 1.读取4G左右大小的文件中的指定行,程序运行占用内存不超过500M. 2.希望查询1G以内容,能控制在20s左右. 刚开始觉得这个应该 ...
- Java解决大文件读取的内存问题以及文件流的比较
Java解决大文件读取的内存问题以及文件流的比较 传统方式 读取文件的方式一般是是从内存中读取,官方提供了几种方式,如BufferedReader, 以及InputStream 系列的,也有封装好的如 ...
- linux大文件读取
在生产环境中有时候可能会遇到大文件的读取问题,但是大文件读取如果按照一般的手法.如cat这种都是对io的一个挑战,如果io扛得住还好,如果扛不住 造成的后果,如服务器内存奔溃,日志损坏 方法一: se ...
- PHP大文件读取操作
简单的文件读取,一般我们会使用 file_get_contents() 这类方式来直接获取文件的内容.不过这种函数有个严重的问题是它会把文件一次性地加载到内存中,也就是说,它会受到内存的限制.因此,加 ...
- python大文件读取
python大文件读取 https://stackoverflow.com/questions/8009882/how-to-read-a-large-file-line-by-line-in-pyt ...
- TCP协议传输大文件读取时候的问题
TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...
- Python读取大文件的"坑“与内存占用检测
python读写文件的api都很简单,一不留神就容易踩"坑".笔者记录一次踩坑历程,并且给了一些总结,希望到大家在使用python的过程之中,能够避免一些可能产生隐患的代码. 1. ...
- java 导出 excel 最佳实践,java 大文件 excel 避免OOM(内存溢出) excel 工具框架
产品需求 产品经理需要导出一个页面的所有的信息到 EXCEL 文件. 需求分析 对于 excel 导出,是一个很常见的需求. 最常见的解决方案就是使用 poi 直接同步导出一个 excel 文件. 客 ...
- 大文件读取方法(C#)
之前都是用StreamReader.ReadLine方法逐行读取文件,自从.NET4有了File.ReadLines这一利器,就再也不用为大文件发愁了. File.ReadLines在整个文件读取到内 ...
随机推荐
- 2016HUAS_ACM暑假集训4D - 计数,排列
一个错排公式的基础应用. 大致题意:求n个数的错误排列方式.(每个都要错) 在这里先贴一下错排公式:D(1)=0:D(2)=1:D(n)=(n-1)*(D(n-1)+D(n-2)) 它的推导也非常有意 ...
- 在chrome 总调试cordova出现Detached from the target. Remote debugging has been terminated with reason: Connection lost. Please re-attach to the new target
在chrome 总调试cordova出现如下错误: "Detached from the target. Remote debugging has been terminated with ...
- Python底层socket库
Python底层socket库将Unix关于网络通信的系统调用对象化处理,是底层函数的高级封装,socket()函数返回一个套接字,它的方法实现了各种套接字系统调用.read与write与Python ...
- C# WebApi 请求方式Post,返回Response
1.[FromBody]属性只能用在一个参数上,当Body中有多个参数要定义类型.一个参数的时候 key="",value="123",key为空才能取到值. ...
- Python>>>The Very First Step
Windows官网下载 python-2.7.13.amd64.msi 默认会安装pip,同是把设置环境变量也选中 安装第三方包: pip install pygame 确认已经正确安装的方法:1.完 ...
- Linux查看redis进程
命令: ps ef|grep redis 返回上一级cd ..
- Oracle索引失效问题:WHERE C1='' OR C2 IN(SubQuery),并发请求时出现大量latch: cache buffers chains等待
问题描述: 项目反馈某功能响应时间很长,高峰期时系统整体响应很慢... 获取相应的AWR,问题确实比较严重,latch: cache buffers chains等待,因为这些会话SQL执行时间太长, ...
- 【python】pickle模块
持久性的基本思想很简单.假定有一个 Python 程序,它可能是一个管理日常待办事项的程序,您希望在多次执行这个程序之间可以保存应用程序对象(待办事项).换句话说,您希望将对象存储在磁盘上,便于以后检 ...
- vlc 在ie11 中的addEventListener事件不触发
在vlc控件中触发一事件,在IE11之前的版本使用attachEvent注册一个回调函数后IE11可以捕获到事件,但IE11中提示attachEvent不支持.经查询发现IE11已经去掉了attach ...
- 将类数组arguments转化成数组
一.将arguments对象绑定到slice方法上 二. 例子: //闭包 二次封装函数 求和 function partialUsingArguments(fn) { var args = Arra ...