You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用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;

逐逻辑拆解

  1. 加载文件:通过LoadFromFile把文件所有行读取到datalist,此时datalist的顺序和文件从上到下的行顺序完全一致。
  2. 确定循环范围:
    • lines是总行数,lines-1是最后一行的索引(TStringList索引从0开始)。
    • lines div 2是总行数的整数半值,比如总行数为5时结果是2,总行数为6时结果是3。
  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的顺序就变成了文件从下到上的行顺序。

二、更高效的直接从底部读取的方法

上述方法需要先加载整个文件到内存再做交换,大文件场景下内存占用高、效率低。更优的方案是直接从文件末尾向前读取字符,逐行拼接后加入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:10:31