热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#读取大文本出现System.OutOfMemoryException,两种解决方案

问题:读取一个444M的文本文件,出现内存溢出方案1:利用FileStream读取byte,利用换行符次数为间隔区间,依次读取(边读边处理):优缺点:速度快,不适合读取指定行(

问题:读取一个444M的文本文件,出现内存溢出


方案1:利用FileStream读取byte,利用换行符次数为间隔区间,依次读取(边读边处理):

优缺点:速度快,不适合读取指定行(因为是用遍历的,所以读取指定行会比较慢)

解决思路:获取区间数组中最后一个换行符(\n的byte字节),以此为分界点,该换行符以后的数据,留给下一个区间来组装;

代码:

///


/// 通过给定的文件流,判断文件的编码类型
///

/// 文件流
/// 文件的编码类型
public Encoding GetType(Stream fs) {byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOMEncoding reVal = Encoding.Default;BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);int i;int.TryParse(fs.Length.ToString(), out i);byte[] ss = r.ReadBytes(i);if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)) {reVal = Encoding.UTF8;} else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00) {reVal = Encoding.BigEndianUnicode;} else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41) {reVal = Encoding.Unicode;}r.Close();return reVal;
}///
/// 通过给定的文件流,判断文件的编码类型
///

/// 文件流
/// 文件的编码类型
public Encoding GetType2(byte[] ss)
{Encoding reVal = Encoding.Default;if ((ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF) || IsUTF8Bytes(ss)){reVal = Encoding.UTF8;}else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00){reVal = Encoding.BigEndianUnicode;}else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41){reVal = Encoding.Unicode;}return reVal;
}///
/// 获取文件编码
///

///
///
public Encoding GetEncoding(string filePath) {FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);Encoding r = GetType(fs);fs.Close();return r;
}///
/// FileStream读取文件文本
///

///
/// 间隔多少个换行符读取一次
///
public void FSLimitReadFileText(string filePath,int txtCount)
{if (!File.Exists(filePath)){return;}FileTool ft = new FileTool();byte rn = new UTF8Encoding(false).GetBytes("\n")[0];using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)){Encoding encoding = null;List bList = new List();string text;int rnCount = 0;int cnt, m;m = 0;cnt = fs.ReadByte();byte by;while (cnt != -1){if (!isRuning){break;}by = Convert.ToByte(cnt);bList.Add(by);if (by == rn){rnCount++;}if (rnCount >= txtCount){rnCount = 0;if (encoding == null){encoding = ft.GetType2(bList.ToArray());if (encoding is UTF8Encoding){encoding = new UTF8Encoding(false);}}text = encoding.GetString(bList.ToArray());//这里就可以执行你的任务了//...............//最后这里清空byte列表,否则下一次会数据会重复bList.Clear();}cnt = fs.ReadByte();}if (bList.Count > 0){if (encoding == null){encoding = ft.GetType2(bList.ToArray());if (encoding is UTF8Encoding){encoding = new UTF8Encoding(false);}}text = encoding.GetString(bList.ToArray());//这里就可以执行你的任务了//...............bList.Clear();}}}



方案2:利用IEnumerable进行迭代获取

优缺点:几乎不怎么占内存,速度遍历的话速度比较慢

如果是只需要取其中几行的话可以考虑用这个,如果是要全部读取,那么不推荐,

同一个444M的文件,利用IEnumerable迭代完毕需要4分多钟,方案一也就13秒钟

(这里我是需要将数据变成字符串,依次进行处理,所以会比较慢,如果是文件的粘贴复制之类的,建议用BufferStream)

public string ReadFileLineText(string filePath)
{if (!File.Exists(filePath)){return null;}int limit = 5000;//每次读取5000行string text = null;Encoding encoding = GetEncoding(filePath); //GetEncoding方法参考方案1if (encoding is UTF8Encoding){encoding = new UTF8Encoding(false);}IEnumerable lines = File.ReadLines(filePath, encoding);int size = lines.Count();//遍历// IEnumerable tempLines;// IEnumerator iter;// for (int i = 0; i = size ? size % limit : limit;// tempLines = lines.Skip(i).Take(max);// iter = tempLines.GetEnumerator();// while (iter.MoveNext())// {// string dataStr = iter.Current;// //SetLog(dataStr);// }// }// }//取第994400后面的5000行数据(不包含994400行)lines = lines.Skip(994400).Take(limit);IEnumerator iter = lines.GetEnumerator();while (iter.MoveNext()){string dataStr = iter.Current;SetLog(dataStr);}return text;
}



推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
author-avatar
张梦蒙4428
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有