-1

我正在使用以下代码来读取和组合一个字符串中的文本数量:

            foreach (string path in filePaths)
            {


                StreamReader singfile = new StreamReader(path);

                string  file_text = singfile.ReadToEnd();
                combinetexts += file_text + "\n";

                fs.Close();

            }

据我所知,字符串 combinetexts 将复制文件路径数量的 n 倍。是否可以使用字符串生成器来执行该操作?我试过了,但没有。提前致谢。

4

6 回答 6

8

这是一个简短的 LINQ 方法:

string result = string.Join("\n", filePaths.Select(x => File.ReadAllText(x)));

或者使用 C# 4(它可以更好地处理类型推断 wrt 方法组转换):

string result = string.Join("\n", filePaths.Select(File.ReadAllText));

如果您使用的是 .NET 3.5,则需要创建一个字符串数组,因为string.Join那时没有那么多重载:

string result = string.Join("\n", filePaths.Select(x => File.ReadAllText(x))
                                           .ToArray());

诚然,这样做的缺点是在执行连接之前读取所有文件- 但它仍然比原始代码中的重复连接要好。它也可能比使用更有效StringBuilder- 这取决于string.Join实现。

请参阅我的文章,StringBuilder了解为什么原始代码确实效率低下。

编辑:请注意,这不包括末尾的尾随\n。如果你真的想添加它,你可以:)

于 2012-05-09T09:58:24.673 回答
1

当然可以,使用

StringBuilder combinetexts = new StringBuilder();
...

combinetexts.Append(file_text);
combinetexts.Append("\n");;
于 2012-05-09T09:56:25.063 回答
1

这是您使用 StringBuilder 而不是字符串的示例:

var sb = new StringBuilder();

foreach (string path in filePaths) 
    sb.AppendLine(File.ReadAllText(path)); 

string result = sb.ToString();

(我还冒昧地缩短/优化了您的代码。File.ReadAllText无需手动打开 StreamReader 即可读取文件的完整内容。此外,在末尾AppendLine自动添加一个。)\n

于 2012-05-09T09:58:13.523 回答
0

是的,可以使用 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();
}

最后我会使用using (...)而不是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 并切换到 usingFile.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 combinetexts = String.Join("\n", filePaths.Select(File.ReadAllText));

这将完成上述所有操作,它将:

  1. 读入所有文件
  2. String.Join 将计算保存整个字符串所需的总大小
  3. 然后它将合并所有文本,每个文本\n之间都有一个
于 2012-05-09T10:03:34.720 回答
0

使用 StringBuilder 来操作字符串更有效。

http://www.codeproject.com/Articles/14936/StringBuilder-vs-String-Fast-String-Operations-wit

此致

于 2012-05-09T09:57:19.180 回答
0

试试下面的代码:

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());
于 2012-05-09T09:58:37.327 回答