C# 文件的高级读取
我相信我们都很熟悉,可能会使用书籍、在线等提供的大量代码来使用C#读取文件。简单到C# 文件的高级读取,c#,io,backgroundworker,C#,Io,Backgroundworker,我相信我们都很熟悉,可能会使用书籍、在线等提供的大量代码来使用C#读取文件。简单到 StringBuilder fiContents = new StringBuilder(); using (StreamReader fi = new StreamReader(@"C:\a_file.txt")) { while (!fi.EndOfStream) { fiContents.Append(fi.ReadLine); } } 或者是像…这样短的东西 u
StringBuilder fiContents = new StringBuilder();
using (StreamReader fi = new StreamReader(@"C:\a_file.txt"))
{
while (!fi.EndOfStream)
{
fiContents.Append(fi.ReadLine);
}
}
或者是像…这样短的东西
using (StreamReader fi = new StreamReader(@"C:\a_file.txt"))
fiContents.Append(fi.ReadToEnd());
现在,让我们去Super Saiyan玩一会儿,做一些非常有趣的事情,比如有一个BackgroundWorker
,它可以让我们显示加载图像(我将使用这个),提供一个进程倒计时计时器或ProgressBar
public void ReadFile(string filename)
{
BackgroundWorker procFile = new BackgroundWorker();
// Progress 1: If we want to show the progress we need to enable the following property
// procFile.WorkerReportsProgress = true;
profile.DoWork += new DoWorkEventHandler((object obj, DoWorkEventArgs ev) =>
{
StringBuilder fiContents = new StringBuilder();
using (StreamReader fi = new StreamReader(filename))
{
while (!fi.EndOfStream)
{
// Progress 2: Report the progress, this will be dealt with by the respective handler (below).
// procFile.ReportProgress((int)(fi.BaseStream.Length / fi.BaseStream.Position) / 100);
fiContents.Append(fi.ReadLine);
}
}
ev.Result = fiContents;
}
/* Progress 3: The handler below will take care of updating the progress of the file as it's processed.
procFile.ProgressChanged += new ProgressChangedEventHandler((object obj, ProgressChangedEventArgs ev) =>
{
// Progress 4: Do something with the value, such as update a ProgressBar.
// ....
}
*/
procFile.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object obj, RunWorkerCompletedEventArgs ev) =>
{
// Do something with the result (ev.Result), bearing in mind, it is a StringBuilder and the ev.Result is an object.
StringBuilder result = ev.Result as StringBuilder;
// ....
}
}
++++++++++++++++++++++++++
是时候回答实际问题了。。。上述内容是一个热身活动,旨在展示当前的理解水平,因此我不会将其视为未来的答案
我几乎是在做上面给出的最后一个代码示例(即使用BackgroundWorker
),并将读取的内容转储到RichTextBox
。简单的东西
然而,我面临的问题是处理大文件(例如~222MB)。该案例只是获取一个.txt,读取它,将通过StringBuilder
构建的结果推送到RichTextBox
中。它无法加载文件,我得到一个OutOfMemoryException
。解决这个问题的一种方法是迭代字符串并从文件StringBuilder
中添加每个字符(作为char
),这需要相当多的时间(并且仍然不会加载文件)
public void ReadFile(string filename)
{
BackgroundWorker procFile = new BackgroundWorker();
// Progress 1: If we want to show the progress we need to enable the following property
// procFile.WorkerReportsProgress = true;
profile.DoWork += new DoWorkEventHandler((object obj, DoWorkEventArgs ev) =>
{
StringBuilder fiContents = new StringBuilder();
using (StreamReader fi = new StreamReader(filename))
{
while (!fi.EndOfStream)
{
// Progress 2: Report the progress, this will be dealt with by the respective handler (below).
// procFile.ReportProgress((int)(fi.BaseStream.Length / fi.BaseStream.Position) / 100);
fiContents.Append(fi.ReadLine);
}
}
ev.Result = fiContents;
}
/* Progress 3: The handler below will take care of updating the progress of the file as it's processed.
procFile.ProgressChanged += new ProgressChangedEventHandler((object obj, ProgressChangedEventArgs ev) =>
{
// Progress 4: Do something with the value, such as update a ProgressBar.
// ....
}
*/
procFile.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object obj, RunWorkerCompletedEventArgs ev) =>
{
// Do something with the result (ev.Result), bearing in mind, it is a StringBuilder and the ev.Result is an object.
StringBuilder result = ev.Result as StringBuilder;
// ....
}
}
我总是使用最基本和最直接的方法来读取文件(如上面给出的示例),但是有人对如何改进这一点有任何指导吗?处理超大文件的方法?等等
即使作为一篇讨论文章,我也欢迎你的想法
++++++++++++++++++++++++++
编辑1(@TaW):尝试将字符串
放入RichTextBox
时引发异常
FileProcessing.RunWorkerCompleted += new RunWorkerCompletedEventArgs((object obj, RunWorkerCompletedEventArgs e) =>
{
// 'Code' is the RichTextBox in question...
Code.Text = "";
if (e.Result is StringBuilder)
{
Code.Text = (e.Result as StringBuilder).ToString();
}
}
你试过,它对于处理大文件非常有用是否有限制要求您使用RichTextBox作为控件来显示内容?此控件未虚拟化,将导致性能(以及从外观上看内存错误)问题
有一系列更适合显示大型文档。根据您的需要存在各种控件(固定、通过页面流动或滚动)。此外,您还可以使用搜索、打印、缩放和其他一些功能查看大型文档。这不是关于高级阅读,而是关于达到(Winforms)控件的容量限制。也许您可以让它在WPF中工作,但在Winforms中,RichTextBox和TextBox都不能容纳如此多的行/文本
我建议您重新设计它,将数据以较小的块呈现给用户。这并不是说他们想滚动超过100.000行。在内存中处理它们不是问题;这里200MB根本不算大;例如,你可以很容易地在内存中搜索它等等。就我个人而言,我只使用
File.ReadAllText(filename)
,但我很懒。简单的回答是,要加载一个内存太大的文件,你不能一次加载所有文件。只加载滚动控件中当前显示的部分文件是一种常见的解决方案。读取200MB文件所需的时间应该很短,以至于进度条和后台工作人员的工作量过大。@Will:没问题!;)我认为富文本框不存在虚拟化,因为虚拟化最适合IList,而不是IEnumerable(字符串可以被认为是IEnumerable)。在幕后,虚拟化使用索引器,因此不需要迭代整个集合就可以到达给定位置(我们要显示的部分)。想象一下,尝试在IEnumerable中向后滚动…如果不从头开始,这是不可能的。我实际上正在开发一个脚本编辑器(带有高亮显示和intelli sense),它现在已经完成,并且需要一个RichTextBox,这样我就可以实现高亮显示和其他功能。因此,它们将是纯文本文件。当我通过一个问题(实际上是WinForm控件的局限性)被问到时,我提出的问题是使用C#的文件I/O中的进一步技术和讨论。因此,我提供了许多代码示例,以演示我熟悉的一些技术,以及大多数其他人可能使用的技术。我完全同意你的第二点。