C# 使用流读取大型TXT文本文件

打印 上一主题 下一主题

主题 603|帖子 603|积分 1809

一、前言
业务需要读取txt的内容,导入到数据库当中,博主百度了各种方法,大部分都会导致内存溢出异常,由此结合网上的各种方法,解决了该异常。
二、程序框架
.NET 4.5
WinForm
三、具体实现
1.1 TXT结构

 
 
 
 
 
 
可以看到该文件大小300多兆,里面的条数差不多60w左右,每行当中的数据使用Tab分割
1.2 代码
  1. private void NewInsert1306(string fileDir)
  2.         {
  3.             FileStream fs = new FileStream(fileDir, FileMode.Open, FileAccess.Read);//创建一个文件流 参数(文件位置,打开此文件(如果没有会抛异常),文件访问权限(只读))
  4.             StreamReader sr = new StreamReader(fs);//创建一个txt读取流,从字节流中读取字符 参数(流)
  5.             using (var db = new CFTech.His.Models.DbContext())
  6.             {
  7.                 try
  8.                 {
  9.                     Stopwatch sw = new Stopwatch();//计时器
  10.                     sw.Start();//开始计时
  11.                     int num = 0;//计算总条数
  12.                     db.BeginTransaction();<br>            //死循环,由于不知道到底有几行,跳出时机在循环体内部判断
  13.                     while (true)
  14.                     {
  15.                         var arrList = new List<string>();//存放读取的数据
  16.                         while (true)
  17.                         {
  18.                             var str = sr.ReadLine();//读取一行内容返回改行的字符串(一个换行符一行),fs有一个fs.position属性(流的位置),该属性在进行任何读取操作时会根据读取的实际情况进行移动,当该位置到达流的末尾时,此方法返回null,该位置也可手动设置fs.position=xxx(long类型)
  19.                             if (str == null)
  20.                                 break;//跳出时机就是读完的时候
  21.                             arrList.Add(str);
  22.                             if (arrList.Count > 10000)
  23.                                 break;//该跳出用于入库,博主这里10000条入一次库
  24.                         }
  25.                         if (arrList.Count == 0)
  26.                             break;//当存放数据的list条数为0时,循环就可以结束了
  27.                         num += arrList.Count();
  28.                         ResBase res = Insert1306(arrList);//该方法就是具体的入库操作了,可根据自己的实际情况去写
  29.                         if (res.ErrCode == -1)
  30.                         {
  31.                             MessageBox.Show(res.ErrMsg);
  32.                             return;
  33.                         }
  34.                     }
  35.                     db.CommitTransaction();
  36.                     fs.Close();//释放文件流
  37.                     sw.Stop();//停止计时
  38.                     MessageBox.Show("入库条数:" + num.ToString()+"------" + "耗时:" + sw.Elapsed);
  39.                     return;
  40.                 }
  41.                 catch (Exception e)
  42.                 {
  43.                     MessageBox.Show(e.Message);
  44.                     db.RollbackTransaction();
  45.                 }
  46.             }
  47.         }
复制代码
1.3效率(数据库:Oracle,orm框架:fireasy)
该方法为同步方法,全在主线程上操作,效率肯定没有异步快,UI会出现阻塞假死情况,以后在研究吧,差不多1分钟入库6w多,由于行业性质,勉强能接受吧

 
1.4遇到的坑

 
 这是同事之前用的方法,他也没想到会遇到这么大的txt,该方法读取文件中的所有行,并且将每行数据转换为数组,对于小文件很方便,但是当文件大于一定程度时,必定会抛内存溢出异常,至于到底支持多大的文件,就没有具体测试了(个人认为和内存无关,计算机为16G内存,运行此方法时还没开始跑内存就直接抛了异常,可能是框架原因,亲测在core里面,使用相同方法,读取同一个20w行的文本,framework直接抛异常,core成功运行)
 
 
 
 
 
END-----------------欢迎大家留言讨论

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

九天猎人

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表