C# 在c中替换大量文本时提高性能#
我有以下代码,我试图用从文件夹中的文本文件列表读取的文本文件中的C# 在c中替换大量文本时提高性能#,c#,winforms,C#,Winforms,我有以下代码,我试图用从文件夹中的文本文件列表读取的文本文件中的逗号替换无序的空格 private void button1_Click(object sender, EventArgs e) { FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); DialogResult result = folderBrowserDialog.ShowDialog(); va
逗号
替换无序的空格
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
DialogResult result = folderBrowserDialog.ShowDialog();
var files = from file in Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories)
from line in File.ReadLines(file)
select new
{
File = file,
Line = line
};
string newPath = folderBrowserDialog.SelectedPath;
if (!Directory.Exists(newPath))
{
System.IO.Directory.CreateDirectory(newPath + @"\Test");
}
foreach (var f in files)
{
string path = f.File.ToString();
string filename = Path.GetFileName(path);
string s = string.Empty;
using (StreamReader reader = new StreamReader(path, true))
{
s = reader.ReadToEnd();
reader.Close();
}
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
using (File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{ }
using (StreamWriter sw = File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{
string output = string.Empty;
foreach (string st in parts)
{
output += st + ",";
}
sw.Write(output);
}
}
}
当我运行这个程序并输入一个包含54个文件(每个大小1MB)的文件夹时,这个过程开始了,但已经花了一个多小时。我点击了
Debug All
并检查了输出,它显示它正在处理,但我不清楚代码是否正确,因为我希望从代码中读取第一个文件,进行更改,并将第一个文件保存在文件夹Test
中,然后获取下一个文件并对其执行相同的操作。到目前为止,它已经花费了1个多小时的处理时间,但是我没有看到在Test
文件夹中创建的任何输出文件。程序肯定正在运行,并且正在处理数据,正如它在Debug All
模式中显示的那样-没有任何错误。没有语法错误,但如果有任何逻辑错误,我需要帮助 使用此代码可以提高性能
var files = Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories);
System.IO.Directory.CreateDirectory(newPath + @"\Test");
foreach (var path in files)
{
string filename = Path.GetFileName(path);
using (var sw = File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{
foreach(var s in File.ReadLines(path))
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string st in parts)
{
sw.Write(st);
sw.Write(",");
}
}
}
}
你的主要问题就在这里
output += st + ",";
由于字符串是不可变的,这会导致大量内存浪费,并迫使垃圾收集器收集大量垃圾,从而显著降低性能
var files = Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories);
System.IO.Directory.CreateDirectory(newPath + @"\Test");
foreach (var path in files)
{
string filename = Path.GetFileName(path);
using (var sw = File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{
foreach(var s in File.ReadLines(path))
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string st in parts)
{
sw.Write(st);
sw.Write(",");
}
}
}
}
拆分大文本不是一个好主意。因此,逐行读取每个文件以减少负载。使用此代码可以提高性能
var files = Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories);
System.IO.Directory.CreateDirectory(newPath + @"\Test");
foreach (var path in files)
{
string filename = Path.GetFileName(path);
using (var sw = File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{
foreach(var s in File.ReadLines(path))
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string st in parts)
{
sw.Write(st);
sw.Write(",");
}
}
}
}
你的主要问题就在这里
output += st + ",";
由于字符串是不可变的,这会导致大量内存浪费,并迫使垃圾收集器收集大量垃圾,从而显著降低性能
var files = Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories);
System.IO.Directory.CreateDirectory(newPath + @"\Test");
foreach (var path in files)
{
string filename = Path.GetFileName(path);
using (var sw = File.CreateText(Path.Combine(newPath + @"\Test", filename + ".txt")))
{
foreach(var s in File.ReadLines(path))
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string st in parts)
{
sw.Write(st);
sw.Write(",");
}
}
}
}
拆分大文本不是一个好主意。因此,逐行读取每个文件以减少负载。除了字符串串联之外,此代码中的一个大问题是文件和行的笛卡尔乘积:
from file in Directory.EnumerateFiles(...)
from line in File.ReadLines(file)
select new
{
File = file,
Line = line
};
糟透了
请尝试此代码:
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
DialogResult result = folderBrowserDialog.ShowDialog();
string path = folderBrowserDialog.SelectedPath;
foreach (var file in Directory.EnumerateFiles(path, "*.chunk*", SearchOption.AllDirectories))
{
string filename = Path.GetFileName(file);
string newPath = path + @"\Test";
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
using (var reader = new StreamReader(file, true))
using (var writer = File.CreateText(Path.Combine(newPath, filename + ".txt")))
{
string s;
while ((s = reader.ReadLine()) != null)
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string part in parts)
{
writer.Write(part);
writer.Write(',');
}
writer.WriteLine();
}
}
}
除了字符串串联之外,此代码中的一个大问题是文件和行的笛卡尔乘积:
from file in Directory.EnumerateFiles(...)
from line in File.ReadLines(file)
select new
{
File = file,
Line = line
};
糟透了
请尝试此代码:
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
DialogResult result = folderBrowserDialog.ShowDialog();
string path = folderBrowserDialog.SelectedPath;
foreach (var file in Directory.EnumerateFiles(path, "*.chunk*", SearchOption.AllDirectories))
{
string filename = Path.GetFileName(file);
string newPath = path + @"\Test";
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
using (var reader = new StreamReader(file, true))
using (var writer = File.CreateText(Path.Combine(newPath, filename + ".txt")))
{
string s;
while ((s = reader.ReadLine()) != null)
{
string[] parts = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string part in parts)
{
writer.Write(part);
writer.Write(',');
}
writer.WriteLine();
}
}
}
这是我用一些额外的
const string testFolder = @"\Test";
var folderBrowserDialog = new FolderBrowserDialog();
folderBrowserDialog.ShowDialog();
var path = folderBrowserDialog.SelectedPath;
if (!Directory.Exists(path)) { return; }
if (!Directory.Exists(path + testFolder)) { Directory.CreateDirectory(path + testFolder); }
var fileList = from file in Directory.GetFiles(path) where file.Contains(".txt") select file;
foreach (var f in fileList)
{
var fileLines = File.ReadLines(f);
foreach (var ps in fileLines.Select(l => l.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)))
{
var fname = Path.GetFileName(f);
using (var wf = File.CreateText(path + testFolder + @"\" + fname))
{
foreach (var p in ps)
{
wf.Write(p);
wf.Write(',');
}
wf.WriteLine();
}
}
}
这是我用一些额外的
const string testFolder = @"\Test";
var folderBrowserDialog = new FolderBrowserDialog();
folderBrowserDialog.ShowDialog();
var path = folderBrowserDialog.SelectedPath;
if (!Directory.Exists(path)) { return; }
if (!Directory.Exists(path + testFolder)) { Directory.CreateDirectory(path + testFolder); }
var fileList = from file in Directory.GetFiles(path) where file.Contains(".txt") select file;
foreach (var f in fileList)
{
var fileLines = File.ReadLines(f);
foreach (var ps in fileLines.Select(l => l.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)))
{
var fname = Path.GetFileName(f);
using (var wf = File.CreateText(path + testFolder + @"\" + fname))
{
foreach (var p in ps)
{
wf.Write(p);
wf.Write(',');
}
wf.WriteLine();
}
}
}
到目前为止,还没有人真正了解这段代码中性能问题的真正原因。他们肯定已经接近了,但有一个坏问题,我认为如果你删除了,你会发现你的代码要快得多 主要问题由以下代码引起:
var files =
from file in Directory.EnumerateFiles(
folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories)
from line in File.ReadLines(file)
select new
{
File = file,
Line = line
};
如果您有1000个文件,每个文件有1000行,那么此代码意味着文件
将有1000000个元素
然后在foreach(varf in files)
中迭代每个文件,这意味着该foreach
将运行每个文件的行数倍
您多次读取和写入每个文件
我确实同意字符串串联会降低代码的速度,但值得一看的是,通过这样做,您可以获得什么样的性能改进:
foreach (var f in Directory.EnumerateFiles(folderBrowserDialog_SelectedPath, "*.chunk*", SearchOption.AllDirectories))
{
...
}
当然,现在最好解决所有的代码问题。我建议像这样尝试:
private void button1_Click(object sender, EventArgs e)
{
var folderBrowserDialog = new FolderBrowserDialog();
var result = folderBrowserDialog.ShowDialog();
var newPath = Path.Combine(folderBrowserDialog.SelectedPath, @"\Test");
if (!Directory.Exists(newPath))
{
System.IO.Directory.CreateDirectory(newPath);
}
foreach (var file in Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories))
{
var newFile = Path.Combine(newPath, Path.GetFileName(file) + ".txt");
var content = File.ReadAllText(file);
content = String.Join(",", content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
File.WriteAllText(newFile, content);
}
}
到目前为止,还没有人真正了解这段代码中性能问题的真正原因。他们肯定已经接近了,但有一个坏问题,我认为如果你删除了,你会发现你的代码要快得多 主要问题由以下代码引起:
var files =
from file in Directory.EnumerateFiles(
folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories)
from line in File.ReadLines(file)
select new
{
File = file,
Line = line
};
如果您有1000个文件,每个文件有1000行,那么此代码意味着文件
将有1000000个元素
然后在foreach(varf in files)
中迭代每个文件,这意味着该foreach
将运行每个文件的行数倍
您多次读取和写入每个文件
我确实同意字符串串联会降低代码的速度,但值得一看的是,通过这样做,您可以获得什么样的性能改进:
foreach (var f in Directory.EnumerateFiles(folderBrowserDialog_SelectedPath, "*.chunk*", SearchOption.AllDirectories))
{
...
}
当然,现在最好解决所有的代码问题。我建议像这样尝试:
private void button1_Click(object sender, EventArgs e)
{
var folderBrowserDialog = new FolderBrowserDialog();
var result = folderBrowserDialog.ShowDialog();
var newPath = Path.Combine(folderBrowserDialog.SelectedPath, @"\Test");
if (!Directory.Exists(newPath))
{
System.IO.Directory.CreateDirectory(newPath);
}
foreach (var file in Directory.EnumerateFiles(folderBrowserDialog.SelectedPath, "*.chunk*", SearchOption.AllDirectories))
{
var newFile = Path.Combine(newPath, Path.GetFileName(file) + ".txt");
var content = File.ReadAllText(file);
content = String.Join(",", content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
File.WriteAllText(newFile, content);
}
}
您是否尝试过使用单个文件运行它并单步执行代码?您要浏览到哪个目录进行测试?您的查询结果不是文件,而是文件行。因为您正在将整个文件读取到内存中。拆分如此大的字符串会导致问题。另外,您的主要问题是这里的
output+=st+“,”这会导致大量的垃圾和内存浪费。您需要使用StringBuilder
。我还建议逐行阅读每个文件并进行拆分。@M.kazemAkhgary您能告诉我如何改进它吗?谢谢你试着用一个文件运行它,并逐步完成代码?你要浏览到哪个目录进行测试?你的查询结果不是文件,而是文件行。因为你正在将整个文件读入内存。拆分如此大的字符串会导致问题。另外,您的主要问题是这里的output+=st+“,”这会导致大量的垃圾和内存浪费。您需要使用StringBuilder
。我还建议逐行阅读每个文件并进行拆分。@M.kazemAkhgary您能告诉我如何改进它吗?谢谢这可不是一回事。您的StringBuilder
建议是正确的。谢谢您的回答。但也有拼写错误。请帮我纠正一下<无法使用foreach中的code>s
(reader.ReadLines()中的var s)
,因为它正在string s=string.Empty中使用代码>。另外,sw.Write中的output
(output.Replace(“,”,”)代码>从未定义过?谢谢。@RehanKhan我已经更新了答案。抱歉出错。为什么要使用StringBuilder
而不直接写入StreamWriter
?@M.kazemAkhgaryStreamReader
中没有对ReadLines()
行foreach(reader.ReadLines()中的变量s)的定义
。你是说ReadLine()
吗?这可不是一回事。您的StringBuilder
建议正确