如何在C#中用File.ReadLines替代File.ReadAllLines实现文本行倒序显示
解决方案
方案1:基于File.ReadLines的简单实现(适合较大文件)
File.ReadLines返回延迟加载的IEnumerable<string>,无法直接通过索引访问,但可借助LINQ的Reverse()实现倒序。同时用StringBuilder替代字符串拼接,避免频繁创建字符串对象带来的性能损耗:
private void button2_Click(object sender, EventArgs e) { textBox1.Clear(); checkBox1.Visible = false; button1.Visible = false; textBox1.Multiline = true; textBox1.Height = 200; textBox1.Width = 600; button2.Visible = false; textBox1.ScrollBars = ScrollBars.Vertical; // 读取文件行(延迟加载)并倒序 var reversedLines = File.ReadLines(openFileDialog1.FileName).Reverse(); // 高效拼接文本 StringBuilder sb = new StringBuilder(); foreach (var line in reversedLines) { sb.AppendLine(line); } textBox1.Text = sb.ToString(); }
注意:
Reverse()会先枚举所有行并缓存,本质上仍会将所有行加载到内存,只是比File.ReadAllLines的数组形式内存占用稍低,适合较大但未达GB级的文件。
方案2:超大文件高效倒序读取(极低内存占用)
若需处理GB级超大文件,上述方案仍会占用过多内存。可直接操作文件流,从文件末尾向前定位换行符,逐行读取:
private void button2_Click(object sender, EventArgs e) { textBox1.Clear(); checkBox1.Visible = false; button1.Visible = false; textBox1.Multiline = true; textBox1.Height = 200; textBox1.Width = 600; button2.Visible = false; textBox1.ScrollBars = ScrollBars.Vertical; StringBuilder sb = new StringBuilder(); // 打开文件流,支持读写共享(避免文件被占用时无法读取) using (var fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { long position = fs.Length; byte[] buffer = new byte[1024]; // 每次读取1KB缓冲区 string currentLine = string.Empty; while (position > 0) { int bytesToRead = (int)Math.Min(buffer.Length, position); position -= bytesToRead; fs.Seek(position, SeekOrigin.Begin); fs.Read(buffer, 0, bytesToRead); // 从缓冲区末尾向前遍历,解析换行符 for (int i = bytesToRead - 1; i >= 0; i--) { if (buffer[i] == '\n') { if (!string.IsNullOrEmpty(currentLine)) { sb.AppendLine(currentLine); currentLine = string.Empty; } } else if (buffer[i] != '\r') // 跳过Windows换行符的\r { currentLine = Encoding.UTF8.GetString(new[] { buffer[i] }) + currentLine; } } } // 添加文件开头的最后一行 if (!string.IsNullOrEmpty(currentLine)) { sb.AppendLine(currentLine); } } textBox1.Text = sb.ToString(); }
这种方法仅占用固定大小的缓冲区内存,不会将整个文件加载到内存,适合处理任意大小的文本文件。
内容的提问来源于stack exchange,提问作者U.Deniz A.
相关产品推荐
相关产品推荐

