快速文本阅读器c#
我使用以下代码读取并组合一个字符串中的文本数:快速文本阅读器c#,c#,c#-4.0,C#,C# 4.0,我使用以下代码读取并组合一个字符串中的文本数: foreach (string path in filePaths) { StreamReader singfile = new StreamReader(path); string file_text = singfile.ReadToEnd(); combinetexts += file_tex
foreach (string path in filePaths)
{
StreamReader singfile = new StreamReader(path);
string file_text = singfile.ReadToEnd();
combinetexts += file_text + "\n";
fs.Close();
}
正如我所知,字符串combinetexts将复制文件路径数的n倍。是否可以使用字符串生成器执行此操作?我试过了,但没有。
提前感谢。当然可以,使用
StringBuilder combinetexts = new StringBuilder();
...
combinetexts.Append(file_text);
combinetexts.Append("\n");;
使用StringBuilder操纵字符串更有效
致以最诚挚的问候以下是您使用StringBuilder而不是字符串的示例:
var sb = new StringBuilder();
foreach (string path in filePaths)
sb.AppendLine(File.ReadAllText(path));
string result = sb.ToString();
(我还冒昧地缩短/优化了您的代码。无需手动打开StreamReader即可读取文件的完整内容。此外,
AppendLine
会在末尾自动添加一个\n
。以下是一个简单的LINQ方法:
string result = string.Join("\n", filePaths.Select(x => File.ReadAllText(x)));
或者使用C#4(它可以更好地处理类型推断wrt方法组转换):
若您使用的是.NET 3.5,则需要创建一个字符串数组,因为string.Join
并没有那个么多重载:
string result = string.Join("\n", filePaths.Select(x => File.ReadAllText(x))
.ToArray());
无可否认,这有一个缺点,即在执行串联之前读取所有文件,但它仍然比原始代码中的重复串联要好。它也可能比使用StringBuilder
更有效-这取决于string.Join
实现
请参阅my,了解原始代码效率低下的原因
编辑:请注意,这不包括结尾处的尾随\n
。如果您真的想添加,您可以:)尝试以下代码:
StringBuilder strBuilder= new StringBuilder();
foreach (string path in filePaths)
{
StreamReader singfile = new StreamReader(path);
string file_text = singfile.ReadToEnd();
strBuilder.AppendLine(file_text);
fs.Close();
}
Console.WriteLine(strBuilder.ToString());
是的,可以使用StringBuilder,有多种方法“优化”此代码 TL;DR:请跳到本文的最后一部分,了解最佳方法 以下是对代码的第1阶段更改:
StringBuilder combinetexts = new StringBuilder();
foreach (string path in filePaths)
{
StreamReader fs = new StreamReader(path);
string file_text = fs.ReadToEnd();
combinetexts.Append(file_text).Append("\n");
fs.Close();
}
其次,在构建StringBuilder
之前,您可以计算实际需要的空间,这将进一步减少复制字符串的机会:
long totalSize = 0;
foreach (string path in filePaths)
totalSize += new FileInfo(path).Length + 1; // +1 = \n
StringBuilder sb = new StringBuilder(Convert.ToInt32(totalSize));
foreach (string path in filePaths)
{
StreamReader fs = new StreamReader(path);
string file_text = fs.ReadToEnd();
combinetexts.Append(file_text).Append("\n");
fs.Close();
}
最后,我将使用使用(…)
而不是fs.Close()代码>呼叫:
long totalSize = 0;
foreach (string path in filePaths)
totalSize += new FileInfo(path).Length + 1; // +1 = \n
StringBuilder sb = new StringBuilder(Convert.ToInt32(totalSize));
foreach (string path in filePaths)
{
using (StreamReader fs = new StreamReader(path))
{
string file_text = fs.ReadToEnd();
combinetexts.Append(file_text).Append("\n");
}
}
然后我会更多地使用LINQ,并切换到使用File.ReadAllText
而不是显式的StreamReader
,然后稍微组合代码行:
long totalSize = filePaths.Sum(path => new FileInfo(path).Length + 1);
StringBuilder sb = new StringBuilder(Convert.ToInt32(totalSize));
foreach (string path in filePaths)
{
combinetexts.Append(File.ReadAllText(path)).Append("\n");
}
然而,事实证明,有一种更好的方法可以做到这一点:
string combinetexts = String.Join("\n", filePaths.Select(path => File.ReadAllText(path)));
或者在C#4.0中,可以更好地推断处理方法组转换的正确方法:
string result = string.Join("\n", filePaths.Select(File.ReadAllText));
string combinetexts = String.Join("\n", filePaths.Select(File.ReadAllText));
这将实现上述所有功能,它将:
读入所有文件
Join将计算保存整个字符串所需的总大小
然后它将合并所有文本,每个文本之间有一个\n
使用字符串生成器执行相同的过程,以避免复制代码。非常感谢。我需要在文件路径中循环吗?@Jonemanni:不,LINQ会帮你做的。这就是替换问题中的代码所需的全部代码。请记住:StringBuilder不是一成不变的。