Как лучше всего прочитать файл в списке <string>
Я использую список, чтобы ограничить размер файла, так как цель ограничена на диске и ram.
Это то, что я делаю сейчас, но есть ли более эффективный способ?
readonly List<string> LogList = new List<string>();
...
var logFile = File.ReadAllLines(LOG_PATH);
foreach (var s in logFile) LogList.Add(s);
Ответы
Ответ 1
var logFile = File.ReadAllLines(LOG_PATH);
var logList = new List<string>(logFile);
Так как logFile
- это массив, вы можете передать его конструктору List<T>
. Это устраняет ненужные накладные расходы при итерации по массиву или с использованием других классов ввода-вывода.
Фактическая реализация конструктора:
public List(IEnumerable<T> collection)
{
...
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0)
{
_items = _emptyArray;
}
else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
}
...
}
Ответ 2
Небольшое обновление для Эвана Мулавского, чтобы сделать его короче
List<string> allLinesText = File.ReadAllLines(fileName).ToList()
Ответ 3
Почему бы не использовать генератор вместо этого?
private IEnumerable<string> ReadLogLines(string logPath) {
using(StreamReader reader = File.OpenText(logPath)) {
string line = "";
while((line = reader.ReadLine()) != null) {
yield return line;
}
}
}
Затем вы можете использовать его, как если бы вы использовали список:
var logFile = ReadLogLines(LOG_PATH);
foreach(var s in logFile) {
// Do whatever you need
}
Конечно, если вам нужно иметь List<string>
, вам нужно будет хранить все содержимое файла в памяти. На самом деле это не так.
Ответ 4
[изменить]
Если вы делаете это, чтобы обрезать начало файла журнала, вы можете избежать загрузки всего файла, выполнив что-то вроде этого:
// 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
}
}
Ответ 5
Не храните его, если это возможно. Просто прочитайте его, если вы ограничены памятью. Вы можете использовать StreamReader:
using (var reader = new StreamReader("file.txt"))
{
var line = reader.ReadLine();
// process line here
}
Это может быть завернуто в метод, который дает строки для каждой строки, если вы хотите использовать LINQ.
Ответ 6
//this is only good in .NET 4
//read your file:
List<string> ReadFile = File.ReadAllLines(@"C:\TEMP\FILE.TXT").ToList();
//manipulate data here
foreach(string line in ReadFile)
{
//do something here
}
//write back to your file:
File.WriteAllLines(@"C:\TEMP\FILE2.TXT", ReadFile);
Ответ 7
List<string> lines = new List<string>();
using (var sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
lines.Add(sr.ReadLine());
}
Я бы предложил это... ответа Гроо.
Ответ 8
string inLine = reader.ReadToEnd();
myList = inLine.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
Я также использую Environment.NewLine.toCharArray, но обнаружил, что не работал над двумя файлами, которые закончились в \r\n. Попробуйте один, и я надеюсь, что он хорошо работает для вас.
Ответ 9
строка inLine = reader.ReadToEnd(); myList = inLine.Split (новая строка [] {"\ r\n"}, StringSplitOptions.None).ToList();
Этот ответ не соответствует первоначальной точке, которая заключалась в том, что они получали ошибку OutOfMemory. Если вы продолжите работу с вышеуказанной версией, вы обязательно нажмете на нее, если в вашей системе нет подходящего НЕПРЕРЫВНОГО доступного ОЗУ для загрузки файла.
Вы просто должны разбить его на части и хранить в виде List или String [] в любом случае.
Ответ 10
Вы можете просто читать таким образом.
List<string> lines = System.IO.File.ReadLines(completePath).ToList();