2012-05-09 4 views
-1

Я использую следующий код для чтения и объединить ряд текстов, в одной строке:быстрое чтение текста с #

  foreach (string path in filePaths) 
      { 


       StreamReader singfile = new StreamReader(path); 

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

       fs.Close(); 

      } 

и, как я знаю, струнное combinetexts будет копировать п раз столько, сколько числа путей файлов , возможно ли выполнить эту процедуру с помощью построителя строк? Я попытался, но это не так. благодарит заранее.

+1

«Это не« ... что-то делать? –

+0

выполнить ту же процедуру с помощью построителя строк, чтобы избежать копирования n раз –

ответ

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.

См. Мой article on StringBuilder, почему исходный код действительно неэффективен.

EDIT: Обратите внимание, что это не включает в себя завершающий \n в конце. Если вы действительно хотите добавить, что вы можете :)

+0

удивительный код. Спасибо. мне нужно пройти через пути к файлу? –

+0

@JoneMamni: Нет, LINQ делает это за вас. Это * все * код, необходимый для замены кода в вашем вопросе. –

+0

большое спасибо –

1

Конечно, это возможно, используйте

StringBuilder combinetexts = new StringBuilder(); 
... 

combinetexts.Append(file_text); 
combinetexts.Append("\n");; 
+0

мог бы использовать построитель строк лучше, чем мой старый код? –

+0

большое спасибо –

+2

Только для записи: StringBuilder - это ** не ** неизменяемый. – Heinzi

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 в конец.)

+0

не делает цель. –

+0

@JoneMamni: Почему бы и нет? – Heinzi

+0

О, извините, он работает. Спасибо. –

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()); 
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 немного больше и переключиться на использование 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 combinetexts = String.Join("\n", filePaths.Select(File.ReadAllText)); 

Это будет делать все из вышеперечисленного, то это будет:

  1. чтение всех файлов
  2. string.join будет рассчитать общий размер, необходимый для хранения всей строки
  3. Тогда это будет объединить все тексты с \n между каждым
+0

какой mazing код. Большое спасибо. –

Смежные вопросы