How to save a string to a .txt file in Delphi?
Asked Answered
H

4

25

I need to make a program that generates a password that is saved in a text file format in a specific destination I set and the user needs to open the .txt to get the password to 'unlock' another program.

I have already got the code to generate the password in the string sPass and now I need to use the SaveToFile function to save it into the text file I created called Password.txt but I cannot find the general form to use the SaveTo File Function in Delphi and I do not know where to put the sPass and Password.txt in the function.

It should be something like : SaveToFile(...) but I do not know how to save sPass in Password.txt

Edit :

Just one more question, how do you delete what is previously stored in Password.txt before you add the string to it so that Password.txt is blank before the string is added ? Thanks

Higa answered 13/10, 2011 at 9:47 Comment(0)
B
27

The modern way is to create a stringlist and save that to file.

procedure MakeAStringlistAndSaveThat;
var
  MyText: TStringlist;
begin
  MyText:= TStringlist.create;
  try
    MyText.Add('line 1');
    MyText.Add('line 2');
    MyText.SaveToFile('c:\folder\filename.txt');
  finally
    MyText.Free
  end; {try}
end;

Note that Delphi already has a related class that does everything you want: TInifile.
It stores values and keys in a key = 'value' format.

passwordlist:= TInifile.Create;
try
  passwordlist.LoadFromFile('c:\folder\passwords.txt');
  //Add or replace a password for `user1`
  passwordlist.WriteString('sectionname','user1','topsecretpassword');
  passwordlist.SaveToFile('c:\folder\passwords.txt');
finally
  passwordlist.Free;
end; {try}

Warning
Note that saving unecrypted passwords in a textfile is a security-leak. It's better to hash your passwords using a hashfunction, see: Password encryption in Delphi
For tips on how to save passwords in a secure way.

Bottrop answered 13/10, 2011 at 10:2 Comment(8)
With "MyText.SaveToFile('c:\folder\filename.txt');" , I cant use that since I cant find out which directory it will stay in as I will be using multiple computers to test this on and the directory for my flashdrive (which I will be storing it on) will be different each time i.e it could be E once , then F on the other pc , then G on another etcHiga
So you have to check the folder location from which the application is started. That should not be too difficult!Luxate
TIniFile is not a descendent of TStrings.Conscionable
I used the TStringList way and it worked perfectly after I found the directory my program exe was in . Thanks guys , you all are always very very helpful !Higa
Application.ExeName Contains the path to the exe file.Androecium
Just one more question, how do you delete what is previously stored in Password.txt before you add the string to it so that Password.txt is blank before the string is added ? ThanksHiga
@Nyt, stringlist1.clear, see: docwiki.embarcadero.com/VCL/en/Classes.TStringListBottrop
@Androecium Instead of Application.ExeName I prefer ParamStr(0) as it does not use the huge Forms unit.Restaurant
J
44

The Modern Modern way is to use TFile.WriteAllText in IOUtils (Delphi 2010 and up)

procedure WriteAllText(const Path: string; const Contents: string); overload; static;

Creates a new file, writes the specified string to the file, and then closes the file. If the target file already exists, it is overwritten.

Jaysonjaywalk answered 14/10, 2011 at 3:9 Comment(2)
This is very interesting, I was not aware of such function. Thx!Stickney
May have some bugs... #35709327Maker
B
27

The modern way is to create a stringlist and save that to file.

procedure MakeAStringlistAndSaveThat;
var
  MyText: TStringlist;
begin
  MyText:= TStringlist.create;
  try
    MyText.Add('line 1');
    MyText.Add('line 2');
    MyText.SaveToFile('c:\folder\filename.txt');
  finally
    MyText.Free
  end; {try}
end;

Note that Delphi already has a related class that does everything you want: TInifile.
It stores values and keys in a key = 'value' format.

passwordlist:= TInifile.Create;
try
  passwordlist.LoadFromFile('c:\folder\passwords.txt');
  //Add or replace a password for `user1`
  passwordlist.WriteString('sectionname','user1','topsecretpassword');
  passwordlist.SaveToFile('c:\folder\passwords.txt');
finally
  passwordlist.Free;
end; {try}

Warning
Note that saving unecrypted passwords in a textfile is a security-leak. It's better to hash your passwords using a hashfunction, see: Password encryption in Delphi
For tips on how to save passwords in a secure way.

Bottrop answered 13/10, 2011 at 10:2 Comment(8)
With "MyText.SaveToFile('c:\folder\filename.txt');" , I cant use that since I cant find out which directory it will stay in as I will be using multiple computers to test this on and the directory for my flashdrive (which I will be storing it on) will be different each time i.e it could be E once , then F on the other pc , then G on another etcHiga
So you have to check the folder location from which the application is started. That should not be too difficult!Luxate
TIniFile is not a descendent of TStrings.Conscionable
I used the TStringList way and it worked perfectly after I found the directory my program exe was in . Thanks guys , you all are always very very helpful !Higa
Application.ExeName Contains the path to the exe file.Androecium
Just one more question, how do you delete what is previously stored in Password.txt before you add the string to it so that Password.txt is blank before the string is added ? ThanksHiga
@Nyt, stringlist1.clear, see: docwiki.embarcadero.com/VCL/en/Classes.TStringListBottrop
@Androecium Instead of Application.ExeName I prefer ParamStr(0) as it does not use the huge Forms unit.Restaurant
S
21

You can use the TFileStream class to save a string to a file:

uses
  Classes;

procedure StrToFile(const FileName, SourceString : string);
var
  Stream : TFileStream;
begin
  Stream:= TFileStream.Create(FileName, fmCreate);
  try
    Stream.WriteBuffer(Pointer(SourceString)^, Length(SourceString));
  finally
    Stream.Free;
  end;
end;

and to read

function FileToStr(const FileName : string):string;
var
  Stream : TFileStream;
begin
  Stream:= TFileStream.Create(FileName, fmOpenRead);
  try
    SetLength(Result, Stream.Size);
    Stream.Position:=0;
    Stream.ReadBuffer(Pointer(Result)^, Stream.Size);
  finally
    Stream.Free;
  end;
end;
Singe answered 13/10, 2011 at 10:25 Comment(0)
B
8

Fastest and simplest way, no need to declare any variables:

with TStringList.Create do
 try
  Add(SomeString);
  SaveToFile('c:\1.txt');
 finally
  Free;
 end;
Blackjack answered 26/12, 2013 at 12:41 Comment(4)
If the file "c:\1.txt" is not writeable, you will get an exception and the free will not execute, so you might want to use try finally construct.Kozlowski
Agree, added try..finally block.Blackjack
The use of with adds much more evil than the lack of local vars gains. -1Bottrop
I use such construct for debugging purposes mostly, it's fast to insert into the code, on any place. Also, if it's short and you do not do additional work in with block, there is no problem with it. For big blocks I don't like with too, because it can lead to unpredictable situations very easy.Blackjack

© 2022 - 2024 — McMap. All rights reserved.