【问题标题】:Opening/Manipulating/Saving TextFile in Delphi在 Delphi 中打开/操作/保存文本文件
【发布时间】:2014-08-12 19:16:58
【问题描述】:

我是 Delphi Noob,我已经搜索并逐步浏览了我的代码,但不明白为什么会输出一个没有内容的文本文件。它应该在有效的对话框中打开一个文本文件,它分配所选文件origFile,然后我想将该文件分配给另一个名为myFile 的文件,这样我就可以在不改变实际原始文件的情况下进行操作,然后我想将myFile 保存为(sOrigFileName + 'B.BACKWARDS.TXT'),但它会跳过while not Eof(origFile) do 并转到CloseFile。我在下面发布我的代码。

要求是使用TextFileTStringList,否则我会使用TStringList 完成此操作。另一个问题是它指出myFile 没有找到,我认为assignFile(myFile, sOrigFileName); 正在创建myFile....

procedure TForm1.btnOpenFileCClick(Sender: TObject);
var
    origFile, myFile : TextFile;
    OpenDialog1 : TOpenDialog;
    sOrigFileName, sNewFileName, sLine, sNewLine : String;

begin
    //Selects txt File of the users choosing
    OpenDialog1 := TOpenDialog.Create(self);
    OpenDialog1.Filter := '*.txt';

    if OpenDialog1.Execute then
    begin
      //AssignFile(origFile, OpenDialog1.FileName);
      sOrigFileName := OpenDialog1.FileName;
      AssignFile(origFile, sOrigFileName);
    end;

    //BACKWARDS
    sNewFileName := sOrigFileName + '.B.BACKWARDS.TXT';
    DeleteFile(sNewFileName);  //Delete old File if exists
    AssignFile(myFile, sNewFileName);

    Reset(origFile);

    while not Eof(origFile) do
    begin
       Rewrite(myFile);
       Readln(origFile, sLine); //takes line into a string Var
       sNewLine := AnsiReverseString(sLine); //reverses and places to  new Var
       WriteLn(myFile,sNewLine);
    end;

    //Clean up
    CloseFile(OrigFile);
    CloseFile(myFile);

【问题讨论】:

  • Chiastic-Security 提到将 ReWrite 移动到 Reset(OrigFile) 下,这修复了 myFile not found 问题。最后仍然得到一个空白文本文件与内容已被反转的文本文件
  • 你为什么使用旧的 Pascal 风格?使用 TStringList,正如 Remy 演示的那样。这是最简单的,除非您的文件非常大(TStringList 会将其完全加载到内存中,并且在此过程中,它还需要一些额外的内存)。

标签: delphi text-files


【解决方案1】:

试试这个:

procedure TForm1.btnOpenFileCClick(Sender: TObject);
var
  origFile, myFile : TextFile;
  OpenDialog1 : TOpenDialog;
  sOrigFileName, sNewFileName, sLine, sNewLine : String;
begin
  OpenDialog1 := TOpenDialog.Create(nil);
  try
    OpenDialog1.Filter := '*.txt';
    if not OpenDialog1.Execute then
      Exit;
    sOrigFileName := OpenDialog1.FileName;
  finally
    OpenDialog1.Free;
  end;

  sNewFileName := sOrigFileName + '.B.BACKWARDS.TXT';
  DeleteFile(sNewFileName);

  AssignFile(origFile, sOrigFileName);
  try
    Reset(origFile);

    AssignFile(myFile, sNewFileName);
    try
      Rewrite(myFile);

      while not Eof(origFile) do
      begin
        Readln(origFile, sLine);
        sNewLine := AnsiReverseString(sLine);
        WriteLn(myFile, sNewLine);
      end;
    finally
      CloseFile(myFile);
    end;
  finally
    CloseFile(OrigFile);
  end;
end;

我不知道您为什么需要使用TextFile,这是一种非常古老的学校方法,一点也不现代。如果您有权访问它们,则应使用TStreamReader/Writer

procedure TForm1.btnOpenFileCClick(Sender: TObject);
var
  origFile: TStreamReader;
  myFile : TStreamWriter;
  OpenDialog1 : TOpenDialog;
  sOrigFileName, sNewFileName, sLine, sNewLine : String;
begin
  OpenDialog1 := TOpenDialog.Create(nil);
  try
    OpenDialog1.Filter := '*.txt';
    if not OpenDialog1.Execute then
      Exit;
    sOrigFileName := OpenDialog1.FileName;
  finally
    OpenDialog1.Free;
  end;

  sNewFileName := sOrigFileName + '.B.BACKWARDS.TXT';
  DeleteFile(sNewFileName);

  origFile := TStreamReader.Create(sOrigFileName);
  try
    myFile := TStreamWriter.Create(sNewFileName, False, origFile.CurrentEncoding);
    try
      while not origFile.EndOfStream do
      begin
        sLine := origFile.ReadLine;
        sNewLine := AnsiReverseString(sLine);
        myFile.WriteLine(sNewLine);
      end;
    finally
      myFile.Free;
    end;
  finally
    OrigFile.Free;
  end;
end;

否则,请改用TStringList

procedure TForm1.btnOpenFileCClick(Sender: TObject);
var
  myFile : TStringList;
  OpenDialog1 : TOpenDialog;
  sOrigFileName, sNewFileName, sLine, sNewLine : String;
  I: Integer;
begin
  OpenDialog1 := TOpenDialog.Create(nil);
  try
    OpenDialog1.Filter := '*.txt';
    if not OpenDialog1.Execute then
      Exit;
    sOrigFileName := OpenDialog1.FileName;
  finally
    OpenDialog1.Free;
  end;

  sNewFileName := sOrigFileName + '.B.BACKWARDS.TXT';
  DeleteFile(sNewFileName);

  myFile := TStringList.Create;
  try
    myFile.LoadFromFile(sOrigFileName);

    for I := 0 to myFile.Count-1 do
    begin
      sLine := myFile[I];
      sNewLine := AnsiReverseString(sLine);
      myFile[I] := sNewLine;
    end;

    myFile.SaveToFile(sNewFileName);
  finally
    myFile.Free;
  end;
end;

【讨论】:

  • 我会使用 TStringList 方法。这是迄今为止最方便的文本操作方式。
  • @RudyVelthuis:很方便,但对于大文件效率不高,尤其是在 D2009+ 中,因为它甚至在开始解析文件数据之前就浪费了大量内存(高达文件大小的 3 倍!)。对于 D2009+,我会更倾向于 TStreamReader/TStreamWriter,因为它们的内存占用较少。
  • 不,不适用于大文件。我知道开销。但对于不太大的文件非常方便。
  • @RudyVelthuis 我已经成功地使用了 TStringList 方法,谢谢,这些是我需要为我工作的公司编写的培训应用程序。我们仍然有一些老式的应用程序,我认为这就是为什么我们需要使用不同的对象做同样的事情。
【解决方案2】:

在我看来,您好像需要将 Rewrite(myFile) 放在循环之外,紧跟在 Reset(origFile) 之后。

【讨论】:

  • 这确实纠正了我的文件未找到问题,但是我仍然得到一个空白文本文档与具有反转文本的原始文件。它跳过了 Eof(origFile) 语句
  • 如果OpenDialog1.Execute() 返回 False,您应该退出您的过程,而不是继续访问一个从未打开过的文件。您还每次都创建一个新的TOpenDialog,并且在应用程序退出之前永远不会释放它,因此您正在浪费内存。要么每次重用相同的TOpenDialog 对象,要么每次都释放它。
  • @RemyLebeau 不确定你的意思我每次都在创建一个新的 TOpenDialog。稍后在代码中我会释放它。但是当用户单击 btn 时,我只看到一个 TOpenDialog。如果我错过了您打算指出的内容,请告诉我您的意思是我想知道的。仅供参考,原始文本文件是空白的,有人意外删除了它的内容(甚至我自己),这就是为什么它最后返回一个空白文本文件。
  • @DelphiNoob:每次调用btnOpenFileCClick(),它都会执行TOpenDialog.Create(),从而创建一个对话框组件的新实例。您显示的btnOpenFileCClick() 代码不会调用OpenDialog1.Free()。如果它确实在您的项目中调用了Free(),则您省略了该部分。但是您没有 try/finally 块来保护它,并且您确实显示的某些代码区域可能会引发异常,因此如果发生文件 I/O 错误,则会绕过 Free()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多