C#快速随机按行读取大型文本文件
下面是我实现的一个数据文件随机读取类,可以随机读取大型文本文件的某一行。在我机器上对一个130MB的文本文件,读取第200000的速度从传统做法的400ms提高到了3ms。
一般对文本文件进行读取时,一般采用ReadLine()进行逐行读取。在这种情况下,C#内的FileStream和BufferedStream类处理绰绰有余了。它不会将整个文件全部读入,而是有缓冲的读。但是,要想随机读取某一行,在行数据长度不统一的情况下,如果每次这样遍历到指定行,其效率显然是很低下的。
当然,代价也是有的,引入了第一次打开文件的打开时间,且占用了少部分内存(占用多少是可以设置的,当然占得越小速度也越慢,但最大值也比全部读入要小很多)。
(对网络代码进行部分改写) using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;
using System.IO;
namespace DataBuffer
{
public static class FileConfig
{
public static int STREAM_BUFFER_SIZE = 1024000;
public static int MAP_DISTANCE = 10;
}
public class DataFile
{
///
/// 数据文件名
///
public string fileName = "";
///
/// 初始化读取完标志
///
public bool done = false;
///
/// 当前流位置
///
public long Position = 0;
///
/// 文件头部信息
///
private Hashtable head = new Hashtable();
public Hashtable Head { get { return head; } set { head = value; } }
///
/// 文件地图
///
private ArrayList map = new ArrayList();
public ArrayList Map { get { return map; } set { map = value; } }
///
/// 文件数据行行数
///
private long lines = 0;
public long Lines { get { return lines; } set { lines = value; } }
}
public class DataBuffer
{
private FileStream fs = null;
private BufferedStream bs = null;
private StreamReader sr = null;
private StreamWriter sw = null;
///
/// 文件信息数据结构
///
public DataFile dataFile = new DataFile();
public DataBuffer(string name)
{
dataFile.fileName = name;
}
///
/// 打开文件
///
public bool Open()
{
try
{
//初始化各流
fs = new FileStream(dataFile.fileName, FileMode.Open, FileAccess.ReadWrite);
bs = new BufferedStream(fs, FileConfig.STREAM_BUFFER_SIZE);
sr = new StreamReader(fs);
sw = new StreamWriter(fs);
Thread initFile = new Thread(new ThreadStart(InitDataFile));
initFile.Start();
return true;
}
catch (Exception ee)
{
ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, "文件打开");
return false;
}
}
private void InitDataFile()
{
//另开一个读取流
BufferedStream bs = new BufferedStream(fs);
StreamReader sr = new StreamReader(bs);
//读入数据文件头信息。共14行
string thisLine = NextLine(ref sr);
dataFile.Head.Add("Subject", thisLine.Substring(11));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Date", thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Time", thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Channels", thisLine.Substring(12));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Rate", thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Type", thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add("Rows", thisLine.Substring(8));
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
dataFile.Head.Add("Electrode Labels", thisLine);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
//降低自己的优先级
Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
//数行数,建立地图
long lines = 1;
//在地图中加入首条数据的位置信息
dataFile.Map.Add(dataFile.Position);
//顺序建立文件地图
while (!sr.EndOfStream)
{
thisLine = NextLine(ref sr);
if ((++lines) % FileConfig.MAP_DISTANCE == 0)
{
dataFile.Map.Add(dataFile.Position);
}
}
dataFile.Lines = lines;
dataFile.done = true;
}
///
/// 文件关闭
///
public bool Close()
{
try
{
//顺序关闭各流
sw.Close();
sr.Close();
bs.Close();
fs.Close();
return true;
}
catch (Exception ee)
{
ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, "文件关闭");
return false;
}
}
///
/// 顺序读取下一行。效率低不建议大规模使用,只在打开文件的时候使用一次
///
///
public string NextLine(ref StreamReader sr)
{
string next = sr.ReadLine();
//+2是指Windows换行回车。Linux下要改为+1
dataFile.Position += next.Length + 2;
return next;
}
//指定的目标行内容
public string ReadLine(long line)
{
try
{
//如果载入完毕
if (dataFile.done)
{
//确定数据块索引号
int index = (int)line / FileConfig.MAP_DISTANCE;
//移动到指定位置
bs.Seek(long.Parse(dataFile.Map[index].ToString()), SeekOrigin.Begin);
//创建流读取器
sr = new StreamReader(bs);
//移动到指定行
for (int i = 1; i <= (line - index * FileConfig.MAP_DISTANCE); i++)
{
sr.ReadLine();
}
//返回指定行的值
return sr.ReadLine();
}
else
{
return "";
}
}
catch (Exception ee)
{
ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, "文件读取");
return "";
}
}
}
}
C#快速随机按行读取大型文本文件的更多相关文章
- PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
CSV大文件的读取已经在前面讲述过了(PHP按行读取.处理较大CSV文件的代码实例),但是如何快速完整的操作大文件仍然还存在一些问题. 1.如何快速获取CSV大文件的总行数? 办法一:直接获取文件内容 ...
- Java中文本文件的读取(按行读取)
在之前的学习过程中,经常会遇到将文本文件中的数据读取到数组或其他数据结构中.每次遇到,总是在网上搜索代码解决,解决之后并没有总结复习,因此在下一次遇到同样的问题时,又重复之前的过程.这样周而复始,并没 ...
- 关于一些对map和整行读取文件操作
public static void main(String[] args) { Map<String, String> map = new HashMap<String, Stri ...
- J2SE 8的输入输出--读取/写入文本文件和读取/写入二进制数据
读取/写入文本文件 // 1. 文本输入 // (1) 短小文本直接转入字符串 String string = new String(Files.readAllBytes(Paths.get(&quo ...
- C++按行读取和写入文件
按行读取: 假设有一个文本文件,如下所示: 1 2 32 3 43 4 55 6 77 8 9 文件名为split.txt 目的:按照行读取数据,并一个个的显示出来. 代码如下: #include & ...
- c/c++ 按照行读取文件
本文代码都在Windows/VC++6.0下测试过, 在linux/g++下也没有问题. 但是请一定注意linux和Windows文件格式的区别,比如: 1. 当linux上的代码读取Windows文 ...
- 性能测试--Jmeter随机生成/随机选取/csv读取关键字
Jmeter随机生成/随机选取/csv读取关键字 一.随机生成关键字 随机生成关键字,需要组件:随机变量配置元件(Random Variable) 该组件的作用是生成字符+随机数字格式的字符串,并保 ...
- Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式
昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册. 下面将会通过几个部分简单的介绍CLI在应用中的使用场景. 昨天已经联系过几个基本的命令行参数 ...
- asp.net 读取一个文本文件,并输出到网页显示 通过 一般处理程序实现
asp.net 读取一个文本文件,并输出到网页显示 通过 一般处理程序实现 用这个可以做模板首页进行输出,也可以自已自定义进行扩展 //得到读取到的文本到string中 string resultTe ...
随机推荐
- 【SSH之旅】一步学习的步Struts1相框(三):分析控制Struts1示例
部分博客,,先后实施了Struts抽样.现在我们来分析这个样本.具体解释Struts1. Struts1的几个核心组件是值得我们注意的: (1)ActionServlet(核心控制器). (2)Act ...
- Spark1.0.0 学习路径
2014-05-30 Spark1.0.0 Relaease 经过11次RC后最终公布.尽管还有不少bug,还是非常令人振奋. 作为一个骨灰级的老IT,经过非常成一段时间的消沉,再次被点燃 ...
- 【DataStructure】Some useful methods for arrays
Last night it took me about two hours to learn arrays. For the sake of less time, I did not put emph ...
- MOCK.JS 生成随机数据,拦截 Ajax 请求
mock.js 的用处 前后端分离 :让前端攻城师独立于后端进行开发. 增加单元测试的真实性 :通过随机数据,模拟各种场景. 开发无侵入 :不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响 ...
- ORACLE 根据上表不同的字段值的统计
select p.id comperitorId,p.compcorp competitorName, sum(case when c.kindname = 'ATM' then c.num else ...
- [POJ 3311]Hie with the Pie——谈论TSP难题DP解决方法
主题连接: id=3311">http://poj.org/problem?id=3311 题目大意:有n+1个点,给出点0~n的每两个点之间的距离,求这个图上TSP问题的最小解 ...
- linux_根据关键词_路径下递归查找code
1:进入想查找的项目根目录 2:根据关键词查找 find . -name "*" |xargs grep -F '10.26'
- hibernate 一对多关联关系(具体分析)
在领域模型中, 类与类之间最普遍的关系就是关联关系. 在 UML 中, 关联是有方向的. 以 Customer 和 Order 为例: 一个用户能发出多个订单, 而一个订单仅仅能属于一个客户. 从 ...
- tcp接收队列
对于接收数据包,内核维护如下几个队列:1>全局 backlog 队列,驱动程序调用 netif_rx 将接收到的数据包缓存于该队列中.2>sock 结构中 back_log 队列,网络层在 ...
- Webbrowser代理支持
原文:Webbrowser代理支持 1 通过设置注册表,再用InternetSetOption发送INTERNET_OPTION_SETTINGS_CHANGED与INTERNET_OPTION_RE ...