3

How would I go about reading a text file from a file on disk into an array in memory?

Also, I noticed using ReadLn only shows the first line (seems kind of obvious, since it is ReadLn, but how would I go about reading the whole text document?)

Johan
  • 74,508
  • 24
  • 191
  • 319
coder101
  • 51
  • 1
  • 1
  • 3
  • Edited because the use of "write" was confusing, when the user meant "read". – Warren P Sep 02 '11 at 12:43
  • coder101; please note that the accepted answer is using something called a List, and that this is the Right way to go. But since you used the word "array" specifically please be aware that Arrays and Lists are different (but similar) things in Delphi. – Warren P Sep 02 '11 at 12:46
  • Possible duplicate of http://stackoverflow.com/questions/4193483/how-to-save-string-into-text-files-in-delphi (based on the accepted answer) – Jens Mühlenhoff Sep 02 '11 at 15:01

2 Answers2

8
function ReadFile(const FileName: string): string;
var
  Strings: TStringList;    
begin
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);
    Result := Strings.Text;
  finally
    Strings.Free;
  end;
end;

That returns the file's contents in a string which can be indexed and so could be considered to be an array.

Or perhaps you want an array of strings rather than an array of characters, in which case it's easiest just to use the string list directly:

var
  Strings: TStringList;    
...
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);
    //can now access Strings[0], Strings[1], ..., Strings[Strings.Count-1]
  finally
    Strings.Free;
  end;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 3
    File is not really a good name, though, since that is a reserved word in Delphi. – Rudy Velthuis Sep 02 '11 at 00:37
  • @Rudy Er thanks, and procedures don't have return values either! – David Heffernan Sep 02 '11 at 07:47
  • @David: in the implementation section of a unit, they can, IIRC. – Rudy Velthuis Sep 02 '11 at 08:17
  • @David: Can't check, but I have seen code where a method was declared like `function X(...): SomeType;` and in the implementation section it was declared `procedure X;` and it returned a value. – Rudy Velthuis Sep 02 '11 at 08:22
  • @Rudy D2010: [DCC Error]: E2037 Declaration of 'X' differs from previous declaration – David Heffernan Sep 02 '11 at 08:24
  • That is why I wanted to check it. I have seen it in older versions. – Rudy Velthuis Sep 02 '11 at 08:29
  • While it is more idiomatic to read into a String List, than into an array, the OP used the word array, so I think it important to point out that RRUZ's answer is more "pedantically correct", for those who care about it, there is a distinction between an Array and a List. But if it was me, I'd be doing it exactly as shown above by David. – Warren P Sep 02 '11 at 12:45
  • @Warren What Delphi RTL/VCL and indeed .net framework refer to as a list is really an array, in CS terms. Lists are linked lists in CS terms. – David Heffernan May 28 '14 at 20:58
7

Starting with Delphi XE 2010 you can use the IOUtils.TFile.ReadAllLines function to read the content of text file in a single line of code.

class function ReadAllLines(const Path: string): TStringDynArray;
class function ReadAllLines(const Path: string;  const Encoding: TEncoding): TStringDynArray; overload; static;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 3
    This is present in D2010 too. Astoundingly, it loads the text into a string list but then populates the dynamic array in a loop with SetLength(Result, Length(Result+1))! – David Heffernan Sep 01 '11 at 23:44
  • @David, sounds similar to how dynamic arrays are made in .Net. Make a List then convert to array! I wonder what's the advantage with that method... – Sam Sep 02 '11 at 06:05
  • 1
    @sam it's not advantageous here and has poor performance characteristics – David Heffernan Sep 02 '11 at 06:42
  • @David: can't check that (no Delphi here), but that sounds terrible. I'd guess one SetLength(StringList.Count) would do. – Rudy Velthuis Sep 02 '11 at 08:19
  • @Rudy Why would you need to check it? Do you think I can't read Delphi source code?! Yes, one `SetLength(StringList.Count)` would suffice. That entire unit is littered with the Length := Length + 1 anti-pattern. I guess what could be checked is if the code has improved since my D2010. – David Heffernan Sep 02 '11 at 08:20
  • @David: I meant check if this is still so in XE and XE2. And I always like to see such things myself. – Rudy Velthuis Sep 02 '11 at 08:26
  • @DavidHeffernan yeah, I was just stunned to discover that suboptimal code myself right now. – John Kaster May 28 '14 at 20:49
  • @John As well as the lame perf, the function fails to return `TArray` making it hard to compose with other code. – David Heffernan May 28 '14 at 20:59
  • @DavidHeffernan yes, there was that issue as well. I guess it's an "opportunity" :) – John Kaster May 29 '14 at 19:36