如何最好的将文件读入列表<string>

我使用一个列表来限制文件大小,因为目标在磁盘和内存中是有限的。 这是我现在正在做的,但是有没有更有效的方法?

readonly List<string> LogList = new List<string>(); ... var logFile = File.ReadAllLines(LOG_PATH); foreach (var s in logFile) LogList.Add(s); 
 var logFile = File.ReadAllLines(LOG_PATH); var logList = new List<string>(logFile); 

由于logFile是一个数组,你可以将它传递给List<T>构造函数。 当迭代数组或使用其他IO类时,这消除了不必要的开销。

实际的构造函数实现 :

 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; } } ... } 

埃文·穆拉夫斯基(Evan Mulawski)的一个小小更新使其缩短

List<string> allLinesText = File.ReadAllLines(fileName).ToList()

为什么不使用发电机呢?

 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> ,那么你需要将整个文件内容保存在内存中。 这真的没有办法。

如果可能,不要存储它。 如果你受到内存限制,请仔细阅读。 您可以使用StreamReader:

 using (var reader = new StreamReader("file.txt")) { var line = reader.ReadLine(); // process line here } 

如果你想使用LINQ,这可以被包装在一个每行读取string的方法中。

[编辑]

如果你这样做是为了修剪一个日志文件的开始,你可以避免像下面这样加载整个文件:

 // 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数组( string[] )中,所以复制到列表是多余的。

其次,你必须明白一个List是使用dynamic数组实现的。 这意味着CLR将需要分配和复制几个数组,直到它可以容纳整个文件。 由于该文件已经在磁盘上,因此可以考虑交换内存的速度,并直接处理磁盘数据,或者以较小的块处理它。

  1. 如果你需要在内存中完全加载它,至less要试着离开一个数组:

      string[] lines = File.ReadAllLines("file.txt"); 
  2. 如果真的需要成为一个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); 
  3. 更好的是,避免将整个文件存储在内存中,并“即时”处理它:

      using (var sr = new StreamReader("file.txt")) { string line; while (line = sr.ReadLine() != null) { // process the file line by line } } 
 List<string> lines = new List<string>(); using (var sr = new StreamReader("file.txt")) { while (sr.Peek() >= 0) lines.Add(sr.ReadLine()); } 

我会build议这个Groo的答案。

 //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); 
 string inLine = reader.ReadToEnd(); myList = inLine.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList(); 

我也使用了Environment.NewLine.toCharArray,但是发现它不能用于一些以\ r \ n结尾的文件。 尝试任何一个,我希望它适合你。