如何将文本文件保存到指定文件夹

3
我创建了一个具有登录系统的程序,用户输入信息后,程序将检查连接到其数据库的结果是否匹配,然后登录用户。我想为每次用户登录创建一个日志文件。该日志文件的名称应包含用户的用户名和用户登录的日期和时间。我正在使用以下代码来检查用户凭据并将其详细信息写入日志文件。另外,我希望文件名中的日期是像2013年1月23日这样的格式。所以相关的代码应该在“with dmPredictGame do…”之前。
 sDate := DateToStr(Date());
 sTime := TimeToStr(Time());

  iYear := StrToInt(Copy(sDate,1,4));
  iDay := StrToInt(Copy(sDate,9,2));
  K := StrToInt(Copy(sDate,6,2));

 Case K of
    1 : sMonth := 'January';
    2 : sMonth := 'February';
    3 : sMonth := 'March';
    4 : sMonth := 'April';
    5 : sMonth := 'May';
    6 : sMonth := 'June';
    7 : sMonth := 'July';                      //Check for the     current month
    8 : sMonth := 'August';
    9 : sMonth := 'September';
    10 : sMonth := 'Oktober';
    11 : sMonth := 'November';
    12 : sMonth := 'December';
  end;

  sTime1 := copy(sTime,1,2);
  sTime2 := copy(sTime,4,2);
  sLoginTime := sTime1 + ';' + sTime2;    //Use ; because windows does not allow : in file names
  sLoginDate := IntToStr(iDay) + ' ' + sMonth + ' ' + IntToStr(iYear);


with dmPredictGame do
  begin
    if tblUserInfo.Locate('Username', edtUsername.Text,  []) AND ((edtPassword.Text) = tblUserInfo['Password'])  then         //Check if the username and password is  correct.
     begin
        MessageDlg('Login was successful! Welcome back ' + edtUsername.Text, mtInformation, [mbOK],0);
      edtUsername.Text := tblUserInfo['Username'];
      begin
        sUsername := edtUsername.Text;
        sPassword := tblUserInfo['Password'];
        sName := tblUserInfo['Name'];
        sSurname := tblUserInfo['Surname'];
        assignFile(UserLogFile, 'Log ' + sUsername + ' (' + sLoginDate + ') ' + sLoginTime + '.txt');
        Rewrite(UserLogFile);
        writeln(UserLogFile, 'Username: ' + sUsername);
        writeln(UserLogFile, 'Password: ' + sPassword);
        writeln(UserLogFile, 'Name: ' + sName);
        writeln(UserLogFile, 'Surname: ' + sSurname);
        writeln(UserLogFile, 'Date Logged In: ' + sDate);
        writeln(UserLogFile, 'Time Logged In: ' + sTime);
        closeFile(UserLogFile);
      end;

现在我的问题是:如何在程序所在的当前目录之外的一个不同目录中创建文本文件?我有一个名为“Logs”的文件夹,它位于程序本身所在的相同文件夹中。当日志文件被创建时,我希望将其保存到该文件夹中。
有什么建议吗?

@JerryDodge,相对路径。顺便说一下,如果当前工作目录已经正确设置,相对路径也可以使用。 - Free Consulting
2
我建议您重新考虑将日志写入应用程序文件夹的子目录。这是导致程序不必要地需要提升权限的原因之一。推荐的替代方案是使用Shell API获取适当的“用户文档”或“AppData”文件夹。 - Disillusioned
@Craig 或许这是一个便携式应用程序,旨在存储在存储器棒上,并将其设置随身携带。 - David Heffernan
@DavidHeffernan OP说的是日志文件,而不是设置。我更加谨慎地写日志文件直接存储到USB上。(尽管描述暗示只有少量日志记录。)OP可以继续追求当前的路径。我只是警告可能会遇到的潜在陷阱,并提出了一个不同的方法,这个方法可能没有被考虑过,但仍然可能是合适的。 - Disillusioned
@Craig 好的。再次阅读后,与数据库的连接并不意味着可移植应用程序。 - David Heffernan
1个回答

11

首先,需要获取应用程序的路径,然后将\Log\和文件名添加到路径中,最后提供完整的路径给AssignFile

(当然,以下所有内容都假定您实际上有写入应用程序目录的权限。请注意,如果您的应用程序安装在Windows的%ProgramFiles%文件夹中,则通常无法写入安装文件夹。)

var
  LogFile: string;
begin
  // ... other code
  LogFile := ExtractFilePath(Application.ExeName);
  LogFile := IncludeTrailingPathDelimiter(LogFile) + 'Logs';
  LogFile := IncludeTrailingPathDelimiter(LogFile);
  LogFile := LogFile +
             'Log ' +
             sUserName +
             ' (' + sLoginDate
             + ') ' + sLoginTime + '.txt';
  AssignFile(UserLogFile, LogFile);
  // Write to log and other code
end;

如果您正在使用更现代的Delphi版本,您可以使用TPath中的功能使这个过程变得更容易:

uses
  IOUtils;          // For TPath

var
  LogFile: string;
begin
  LogFile := TPath.Combine(ExtractFilePath(ParamStr(0)), 'Log');
  LogFile := TPath.Combine(LogFile, 
                           'Log ' +
                           sUserName +
                         ' (' + sLoginDate
                         + ') ' + sLoginTime + '.txt';
  AssignFile(UserLogFile, LogFile);
end;

对于文件名的部分,我更喜欢使用Format而不是所有的连接操作:

const
  LogFileTemplate = 'Log %s(%s)%s.txt';

...
var
  LogFile: string;
begin
  LogFile := TPath.Combine(ExtractFilePath(ParamStr(0)), 'Log');
  LogFile := TPath.Combine(LogFile,
                           Format(LogFileTemplate,
                                  [sUserName, sLoginDate, sLoginTime]));
  AssignFile(UserLogFile, LogFile);
  // Other code
end;

针对您的文件命名问题(日期/时间部分),您所做的方法完全错误。 :-) 您正在进行过多的工作:

var
  sDate: string;

  sDate := FormatDateTime('(dd mmmm yyyy) hhmm', Now); 
  // Run now on my system shows (22 November 2013) 1645
  ShowMessage(sDate);

这意味着你的文件名被简化了。用单个sTimeStamp: string;替换sLoginDatesLoginTime,然后使用类似于以下的内容:

sTimeStamp := FormatDateTime('(dd mmmm yyyy) hhmm', Now);
LogFile := LogFile + 
           'Log ' + 
           sUserName + 
           sTimeStamp +
           '.txt';

3
我建议使用 ISO 日期格式(yyyy-mm-dd),因为这样如果文件夹中有大量日志文件,它们将按名称自然排序。 - Disillusioned

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