[Редактировать]
Если вы делаете это, чтобы обрезать начало файла журнала, вы можете избежать загрузки всего файла, выполнив что-то вроде этого:
// count the number of lines in the file
int count = 0;
using (var sr = new StreamReader("file.txt"))
{
while (sr.ReadLine() != null)
count++;
}
// skip first (LOG_MAX - count) lines
count = LOG_MAX - count;
using (var sr = new StreamReader("file.txt"))
using (var sw = new StreamWriter("output.txt"))
{
// skip several lines
while (count > 0 && sr.ReadLine() != null)
count--;
// continue copying
string line = "";
while (line = sr.ReadLine() != null)
sw.WriteLine(line);
}
Прежде всего, поскольку File.ReadAllLines
загружает весь файл в массив строк (string[]
), копирование в список является избыточным.
Во-вторых, вы должны понимать, что List
реализован с использованием динамического массива под капотом.Это означает, что CLR потребуется выделить и скопировать несколько массивов, пока он не сможет вместить весь файл.Поскольку файл уже находится на диске, вы можете подумать о скорости обмена для памяти и непосредственной работе с данными на диске, или обрабатывать его небольшими кусками.
Если вам необходимо полностью загрузить его в память, по крайней мере, попытайтесь оставить в массиве:
string[] lines = File.ReadAllLines("file.txt");
Если это действительно должно быть List
, загрузите строки одну за другой:
List<string> lines = new List<string>();
using (var sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
lines.Add(sr.ReadLine());
}
Примечание: List<T>
имеет конструктор, который принимает параметр емкости.Если вы знаете количество строк заранее, вы можете предотвратить многократное выделение, предварительно выделив массив:
List<string> lines = new List<string>(NUMBER_OF_LINES);
Еще лучше, избегайте сохранения всего файла в памяти и обрабатывайте его"на лету":
using (var sr = new StreamReader("file.txt"))
{
string line;
while (line = sr.ReadLine() != null)
{
// process the file line by line
}
}