DelphiNewbie
DelphiNewbie

Reputation: 789

How read the content of file to a string in delphi XE

I'm migrating my application from delphi 2007 to delphi xe, but am having problems with a procedure which reads an ascii file and stores the content in a string.

This code worked in Delphi 2007

function LoadFileToStr(const FileName: TFileName): String;
var
  FileStream : TFileStream;
begin
  FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
     if FileStream.Size>0 then
     begin
      SetLength(Result, FileStream.Size);
      FileStream.Read(Pointer(Result)^, FileStream.Size);
     end;
    finally
     FileStream.Free;
    end;
end;

But when I execute this code in Delphi XE the result are just symbols like '????????'. I know that Delphi XE is unicode so I changed these lines

      SetLength(Result, FileStream.Size);
      FileStream.Read(Pointer(Result)^, FileStream.Size);

to

      SetLength(Result, FileStream.Size*2);
      FileStream.Read(Pointer(Result)^, FileStream.Size);

to store the content of the file in the unicode string but the result is the same.

how I can fix this procedure to read the content of this file?

Upvotes: 14

Views: 61351

Answers (4)

IceCold
IceCold

Reputation: 21124

You can achieve this with one line of code using ReadAllText function. Like this:

Uses IOUtils;

TFile.ReadAllText(FileName);

or

TFile.ReadAllText(FileName, s, TEncoding.ASCII) // if you want to force ASCII (other) encoding 

It will correctly detect ANSI, Unicode and binary files.

Upvotes: 23

user497849
user497849

Reputation:

I recommend using a TStringList to load the content of the file and then set the result to variable.Text, for example:

function LoadFileToStr(const FileName: TFileName): String;  
var LStrings: TStringList;  
begin  
    LStrings := TStringList.Create;
    try  
      LStrings.Loadfromfile(FileName);  
      Result := LStrings.text;  
    finally  
      FreeAndNil(LStrings);  
    end;  
end;

In this way you don't have to worry about anything, it will be backwards and future compatible IMHO.

EDIT: If you need to load from a TStream descendant, then replace LoadFromFile with LoadFromStream.

Upvotes: 6

kludg
kludg

Reputation: 27493

You should take encoding into account, for example:

function LoadFileToStr(const FileName: TFileName): String;
var
  FileStream : TFileStream;
  Bytes: TBytes;

begin
  Result:= '';
  FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    if FileStream.Size>0 then begin
      SetLength(Bytes, FileStream.Size);
      FileStream.Read(Bytes[0], FileStream.Size);
    end;
    Result:= TEncoding.ASCII.GetString(Bytes);
  finally
    FileStream.Free;
  end;
end;


//test
procedure TForm2.Button1Click(Sender: TObject);
begin
  ShowMessage(LoadFileToStr('C:\autoexec.bat'));
end;

Upvotes: 12

RRUZ
RRUZ

Reputation: 136391

you code does not work because you are reading the content of the file using a unicode string as buffer, so you are just moving bytes from the internal buffer of the TFileStream to the unicode string ignoring the encoding.

you can fix easily your procedure , just changing the result type to AnsiString

function LoadFileToStr(const FileName: TFileName): AnsiString;

but i will recommend you which you use the TFile.ReadAllText function instead which in a single line of code read the content of a file a also handle the encoding of the file.

Upvotes: 31

Related Questions