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 = ;
static void Main(string[] args)
{
//long ttargetRowNum = 39999999;
long ttargetRowNum = ;
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 + ;//目标行
long curRowNum = ;//当前行
FILE_SIZE = fs.Length;
using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(fs, "test", fs.Length, MemoryMappedFileAccess.ReadWrite, null, HandleInheritability.None, false))
{
long offset = ;
//int limit = 250;
int limit = ;
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 > )
sbDefineRowLine.Remove(, 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 - ;
}
}
}
测试截图:

欢迎大家提供更好的解决思路.
参考资料:
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
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在整个文件读取到内 ...
随机推荐
- 【淘淘】Spring整合Quartz框架
我在外面工作实习的时候,我们做的项目是一个日报子系统,也就是定时定点为公司生成一些报表数据还有一些数据反馈.这时候我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.当时,我做 ...
- QuickTest Professionar 快捷键
新建Test – New Test CTRL + N录制 – Record F3打开Test – Open Test CTRL + O新建业务组件 – Business Component > ...
- SOAPUI使用教程-MockOperations和响应
如前所述,一个MockService有多个MockOperations其中每个可以包含任意数量的MockResponse消息; 也就是说,一个MockService响应实际上包括若干预设响应之间发生变 ...
- 玩转AR,联想将在2017年推出第二款Tango AR手机
今年6月份,联想与谷歌合作推出了全球首款消费级AR手机Phab2 Pro,并获得很大的关注.作为谷歌Project Tango的一部分,这款手机的最大亮点是它搭载了三颗后置摄像头和多个传感器,机身背面 ...
- JS:事件处理程序
在JQuery中有个toggle事件,可以绑定两个或多个函数,可以轮流相应click事件,这两天学习到原来javascript中有两个方法(也可以说是四个)同样可以实现这个功能. #box{ marg ...
- .NET简谈接口
自从面向对象开发方式的出现,抽象的概念就开始日新月异的发展,面向对象编程.面向接口编程.面向组件编程等等:这一系列的概念都是软件工程所追求的思想范畴,高类聚低耦合. 今天我要简谈的是面向对象里面非常重 ...
- 阿里云分布式关系数据库DRDS笔记
1.Join左边的表查询数据越少,性能越好 2.广播表作为Join的驱动表 3.SQL的Limit优化 SELECT * FROM t_order o WHERE o.id IN ( SELECT i ...
- RunLoop和autorelease的一道面试题
有这么一道iOS面试题 以下代码有没有什么问题?如果有?如何解决? for (int i = 0; i < largeNumber; i++) { NSString *str = [NSStri ...
- EasyUI 页面分页
DAO package com.hanqi.dao; import java.util.ArrayList; import java.util.List; import org.hibernate.S ...
- windows php 5.5 执行exe 不是有效的win32程序
双击运行php-cgi.exe弹出对话框提示不是有效的win32应用程序.此为版本问题,PHP5.5版本 最低要运行于操作系统版本号最低要6.0 ,而WINDOWS 2003 系统为5.2 因此无法运 ...