C# 读取和剪切文件的有效方法
我需要做的是,我有几个文件(txt)约2GB的每个。我需要剪切DOS文件,比如说每当出现“%%XGF NEW_SET”标记时,我需要创建新文件并存储它。我认为这个标记大约每隔40-50行出现一次。每行大约有4-20个字符。 因此,我需要将大文件切割成数千个小文件,然后在以后处理它们。我想到了这样一个示例代码C# 读取和剪切文件的有效方法,c#,.net,file-io,performance,C#,.net,File Io,Performance,我需要做的是,我有几个文件(txt)约2GB的每个。我需要剪切DOS文件,比如说每当出现“%%XGF NEW_SET”标记时,我需要创建新文件并存储它。我认为这个标记大约每隔40-50行出现一次。每行大约有4-20个字符。 因此,我需要将大文件切割成数千个小文件,然后在以后处理它们。我想到了这样一个示例代码 DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"])
DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]);
var files = di.GetFiles();
int count = 0;
bool hasObject = false;
StringBuilder sb = new StringBuilder();
string line = "";
foreach (var file in files)
{
using (StreamReader sr = new StreamReader(file.FullName,Encoding.GetEncoding(1250)))
{
while ((line = sr.ReadLine()) != null)
{
//when new file starts
if (line.Contains("%%XGF NEW_SET"))
{
//when new file existed I need to store old one
if (hasObject)
{
File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString());
sb.Length = 0;
sb.Capacity = 0;
}
//setting exist flag
hasObject = true;
}
//when there is no new object
else
//when object exists adding new lines
if (hasObject)
sb.AppendLine(line);
}
//when all work done saving last object
if (hasObject)
{
File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString());
sb.Length = 0;
sb.Capacity = 0;
}
}
}
}
所以我的样品看起来像那样,但我需要高效率。有什么办法可以改进我的解决方案吗?谢谢与当前代码相比,您需要什么样的效率
就我个人而言,我可能会做得稍有不同——让一个读者和一个作者一直处于打开状态,并写下你读到的每一行,除非是“剪切”行,在这种情况下,你只需关闭现有的作者,然后开始新的一行。不过,我并不特别希望在效率上有什么不同。我会创建一个输出文件流,直到下一个对象出现时才写入其中,从而完全消除对StringBuilder的需求。然后切换到新对象上的新文件流。谢谢所有提示。考虑到这一点,我将我的代码修改为如下内容:
DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]);
//getting all files from dir
var files = di.GetFiles();
int count = 0;
bool hasObject = false;
string line = "";
StreamWriter sw = null;
foreach (var file in files)
{
using (StreamReader sr = new StreamReader(file.FullName, Encoding.GetEncoding(1250)))
{
while ((line = sr.ReadLine()) != null)
{
//when new file starts
if (line.Contains("%%XGF NEW_SET"))
{
//when new file existed I need to store old one
if (hasObject)
{
sw.Close();
}
else
{
//creating new file and setting exist flag
hasObject = true;
sw = new StreamWriter(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name));
//Bill bill = new Bill();
}
}
else
//when object exists adding new lines
if (hasObject)
sw.WriteLine(line);
}
//when all work done saving last object
if (hasObject)
{
sw.Close();
hasObject = false;
}
}
}
sw.Dispose();
你觉得那样的事怎么样
我还需要做一件事:
我的大文件可以存储不同的文档。他们都有不同的开始标记。
假设有20种文档。有时会有相同的标记开始,但在文档内部有一些额外的标记,允许我识别文档类型。我的意思是,例如,2个文档具有相同的标记开始,如“%%XGF NEW_SET”,但其中一个文档具有后一个标记开始,如“BILL_A”,而另一个文档则没有。我必须为每个剪切文件创建一个文件,其中包含文档中的一些索引和一个包含类型的字符串。所以基本上,在保存StreamWriter之前,我必须提取所有这些索引和文档类型,这是我对StringBuilder的看法。所以,当我需要这种高效率时,它是下一个地方。有什么好的提示吗?在.NET中有许多不同的读取和写入文件的方法。我已经编写了一个基准测试程序,并在我的博客中给出了结果: 如果需要性能,我建议使用Windows ReadFile和WriteFile方法。避免使用任何异步方法,因为我的基准测试结果表明,使用同步I/O方法可以获得更好的性能—至少对于FileStream来说是这样,FileStream是在中读取文件最快的.NET类。我用C#编写了一个类,它封装了ReadFile和WriteFile的功能,这使得它非常容易使用 另一个有趣的结果是,它观察了一些事情,比如读台词。以每个65536字节的块读取数据并将其解析为行。事实证明,在程序中以块的形式读取数据,然后将其解析为行更有效。我的下载中有一些如何做到这一点的例子 如果你能下载并试用它,然后在这里报告,或者在我的博客上留言,如果它比StreamReader快的话,我会很高兴的。根据我有限的基准,它的速度要快得多 提高程序性能的另一个方法是创建多个线程,并让每个线程处理一个文件。既然你说你有几个大文件,我就把它分解,这样每个大文件都有一个单独的线程 如果您正在使用字符串进行大量工作,那么您肯定应该使用StringBuilder。但是,也许更有效的方法是将数据读入字节数组,然后构建一个字节数组用于输出。如果这不比使用StringBuilder更有效,我会感到惊讶
Bob Bryan MCSD分割线上唯一的东西是
%%XGF NEW\u SET
吗?如果没有,您将丢失其他信息,因为您正在丢弃这一行。您的方法是:从原始文件中打开一个流,在每个分节时写入一个新文件。除了在代码可读性方面的一些小优化和减少对stringbuilder的需要之外,我不知道如何使其更快。我所能想到的就是,在您从不同的驱动器重新登录和写入时,将写操作线程化到工作线程可能会有所帮助。