用Delphi从下到上读取文本到TStringList?现有反转代码求解析
文本文件反向读取到TStringList的代码解析与优化方案
一、现有反转代码逻辑解析
这段代码的核心思路是先把文件所有内容加载到TStringList,再通过交换首尾对应位置的行实现整体反转,具体逻辑拆解如下:
代码重现
var datalist : TStringList; lines,i : Integer; saveLine : String; begin datalist := TStringList.Create; datalist.LoadFromFile(filename); //loads file lines := datalist.Count; for i := lines-1 downto (lines div 2) do begin saveLine := datalist[lines-i-1]; datalist[lines-i-1] := datalist[i]; datalist[i] := saveLine; end; end;
逐逻辑拆解
- 加载文件:通过
LoadFromFile把文件所有行读取到datalist,此时datalist的顺序和文件从上到下的行顺序完全一致。 - 确定循环范围:
lines是总行数,lines-1是最后一行的索引(TStringList索引从0开始)。lines div 2是总行数的整数半值,比如总行数为5时结果是2,总行数为6时结果是3。
- 交换首尾对应行:
循环从最后一行索引开始,倒序遍历到中间位置,每次交换datalist[i]和datalist[lines-i-1]的内容:- 举个例子:总行数为5时,循环i取4、3、2:
- i=4:交换索引0和4的行(第一行和最后一行)
- i=3:交换索引1和3的行(第二行和倒数第二行)
- i=2:交换索引2和2的行(中间行,无实际变化)
循环结束后,datalist的顺序就变成了文件从下到上的行顺序。
- 举个例子:总行数为5时,循环i取4、3、2:
二、更高效的直接从底部读取的方法
上述方法需要先加载整个文件到内存再做交换,大文件场景下内存占用高、效率低。更优的方案是直接从文件末尾向前读取字符,逐行拼接后加入TStringList,无需加载整个文件,也省去二次反转操作。
实现代码示例
var FileStream: TFileStream; datalist: TStringList; Buffer: array[0..1023] of Char; ReadBytes: Integer; CurrentLine: string; i: Integer; begin datalist := TStringList.Create; try FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try CurrentLine := ''; // 从文件末尾向前逐块读取 while FileStream.Position > 0 do begin // 每次读取最多1KB数据,平衡读取效率和内存占用 ReadBytes := Min(SizeOf(Buffer), FileStream.Position); FileStream.Position := FileStream.Position - ReadBytes; FileStream.ReadBuffer(Buffer, ReadBytes); // 逆序处理读取到的字符,拼接行 for i := ReadBytes - 1 downto 0 do begin case Buffer[i] of #10: // Unix/LF换行 begin if CurrentLine <> '' then begin datalist.Add(CurrentLine); CurrentLine := ''; end; // 跳过前一个CR字符(处理Windows/CRLF换行) if (i > 0) and (Buffer[i-1] = #13) then Dec(i); end; #13: // 旧Mac/单独CR换行 begin if CurrentLine <> '' then begin datalist.Add(CurrentLine); CurrentLine := ''; end; end; else CurrentLine := Buffer[i] + CurrentLine; // 向前拼接字符 end; end; end; // 添加文件开头的最后一行 if CurrentLine <> '' then datalist.Add(CurrentLine); finally FileStream.Free; end; except datalist.Free; raise; end; end;
优势说明
- 内存占用低:仅用固定大小的缓冲区和临时字符串存储当前行,无需一次性加载整个文件。
- 效率更高:直接生成反向顺序的行列表,省去加载后交换的二次操作。
- 兼容性好:支持LF、CRLF、CR三种常见的换行格式。
内容的提问来源于stack exchange,提问作者user41758
相关产品推荐
相关产品推荐

