Delphi 2010有LoadTextFromFile函数吗?

5

在将一些代码从Delphi 7移植到Delphi 2010时,我正在重写我的LoadTextFromFile()函数。

function LoadTextFromFile(const aFullFileName: string): string;
var
  lBuffer:     TBytes;
  lEncoding:   TEncoding;
  lFileStream: TFileStream;
  lSize:       Integer;

begin

  if not FileExists(aFullFileName) then
  begin
    raise Exception.Create('File "' + aFullFileName + '" not found.');
  end;

  lFileStream := TFileStream.Create(aFullFileName, fmOpenRead + fmShareDenyNone);
  try

    if lFileStream.Size <= 0 then
    begin
      Result := '';
    end
    else
    begin

      lSize := lFileStream.Size - lFileStream.Position;

      SetLength(lBuffer, lSize);

      // Read file into TBytes buffer
      lFileStream.Read(lBuffer[0], lSize);

      // Read encoding from buffer
      TEncoding.GetBufferEncoding(lBuffer, lEncoding);

      // Get string from buffer
      Result := lEncoding.GetString(lBuffer);

    end;

  finally
    lFileStream.Free;
  end;

end;

当我思考时,突然想到标准库中一定有类似的函数。很多用户都想将文本文件读入字符串中,但我却找不到这样的标准函数。最接近的方法是使用TStringlist加载文本。但是A)创建TStringlist看起来是不必要的,B)我不想承受TStringlist带来的额外开销。
问题:Delphi 2010中是否有标准的LoadTextFromFile函数?

即使在 Delphi 7 中,您也不必这样做。使用 TStringStream 而不是 TFileStream,并使用 Marco 的答案。另外,我很好奇:在什么情况下,您曾经发现 Position 属性在创建流后不是零,以至于您需要从 Size 中减去它才能计算 lSize - Rob Kennedy
嗨,Rob,在Delphi 7中,我需要能够加载/保存UTF8文件。更重要的是,我不知道TStringStream。位置不需要在那里。它在那里是因为我从TStrings.Loadfromstream方法中复制了一些代码,其中包含了该位置。我的代码还有另一个错误,它不能处理带BOM的文件。因此,任何考虑使用我的示例的人:不要这样做。请改用TFile.ReadAllText。 - Jan Derk
4个回答

14

Delphi 2010中存在一个名为ReadAllText的函数,它属于IOUtils单元中声明的TFile记录。请参考此声明

class function ReadAllText(const Path: string): string; overload; inline; static;
class function ReadAllText(const Path: string; const Encoding: TEncoding): string; overload; inline; static;

查看这个示例

program Project80;

{$APPTYPE CONSOLE}

uses
  IOUtils,
  SysUtils;
Var
 Content : string;
begin
  try
    Content:=TFile.ReadAllText('C:\Downloads\test.css'); //load the text of the file in a single line of code
    //Content:=TFile.ReadAllText('C:\Downloads\test.css',TEncoding.UTF8); //you can an encoding too.
    Writeln(Content);
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

谢谢,这正是我在寻找的。出于好奇:IOUtils和TFile是什么时候添加到Delphi中的? - Jan Derk
2
我注意到TFile.ReadAllText在读取文件时会对其进行独占锁定。我更喜欢使用fmShareDenyWrite锁定。 - Jan Derk

4

TStringStream.LoadFromStream / file?无论如何,非常大的字符串总是有点浪费。您必须非常小心,以免意外复制它。


2
我尝试了同样的解决方案,但是将 lEncoding 设为类变量以使其持久化,这样我就可以将文件保存到与读取相同的编码中。然而,如果 lEncoding 已经被设置为某些内容(例如前一个文件的编码),则调用 GetBufferEncoding 就不起作用了。因此,我首先尝试释放它,但这导致访问违规问题。现在我只是在进行第二次调用之前将其设置为 nil,这似乎有效。

像这样:

if Assigned(lEncoding) then begin
  lEncoding := nil;
end;
GetBufferedEncoding(buffer, lEncoding);

1
一个快速的方法是使用TStringList.LoadFromFile()。然后使用TStringlist.Text将数据作为一个大字符串访问。不要忘记创建/释放,最好使用try..finally块。

2
这种方法需要文件大小的多倍,我不建议在处理大文件时使用它。 - Marco van de Voort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接