Создать и / или записать в файл - PullRequest
21 голосов
/ 20 октября 2011

Я чувствую, что это должно быть легко, но Google на данный момент полностью меня подводит. Я хочу открыть файл или создать его, если он не существует, и записать в него.

следующие

AssignFile(logFile, 'Test.txt');
Append(logFile);

выдает ошибку во второй строке, когда файл еще не существует, что, я полагаю, ожидается. Но я действительно не могу понять, как а) проверить, существует ли файл и б) создать его при необходимости.

К вашему сведению, работает в Delphi XE.

Ответы [ 5 ]

36 голосов
/ 20 октября 2011

Вы можете использовать функцию FileExists и затем использовать Append, если существует, или Rewrite, если нет.

    AssignFile(logFile, 'Test.txt');

    if FileExists('test.txt') then
      Append(logFile)
    else
      Rewrite(logFile);

   //do your stuff

    CloseFile(logFile); 
24 голосов
/ 20 октября 2011

Любое решение, использующее FileExists для выбора способа открытия файла, имеет условие состязания.Если существование файла изменяется между временем, когда вы его тестируете, и временем, когда вы пытаетесь открыть файл, ваша программа потерпит неудачу.Delphi не предоставляет способа решить эту проблему с помощью собственных процедур ввода / вывода файлов.

Если ваша версия Delphi достаточно новая, чтобы предложить ее, вы можете использовать TFile.Openс открытым режимом fmOpenOrCreate, который делает именно то, что вы хотите;он возвращает TFileStream.

В противном случае вы можете использовать функцию Windows API CreateFile, чтобы открыть файл.Задайте для параметра dwCreationDisposition значение OPEN_ALWAYS, что говорит о необходимости создания файла, если он еще не существует.

10 голосов
/ 20 октября 2011

Вы должны использовать вместо TFileStream. Вот пример, который создаст файл, если он не существует, или запишет в него, если он существует:

var
  FS: TFileStream;
  sOut: string;
  i: Integer;
  Flags: Word;
begin
  Flags := fmOpenReadWrite;
  if not FileExists('D:\Temp\Junkfile.txt') then
    Flags := Flags or fmCreate;
  FS := TFileStream.Create('D:\Temp\Junkfile.txt', Flags);
  try
    FS.Position := FS.Size;  // Will be 0 if file created, end of text if not
    sOut := 'This is test line %d'#13#10;
    for i := 1 to 10 do
    begin
      sOut := Format(sOut, [i]);
      FS.Write(sOut[1], Length(sOut) * SizeOf(Char)); 
    end;

  finally
    FS.Free;
  end;
end;
5 голосов
/ 20 октября 2011

Вы также можете использовать функцию загрузки / сохранения в TStringList для решения вашей проблемы.

Это может быть плохим решением, поскольку весь файл будет загружен в память, изменен в памяти и затем сохранен на диск. (В отличие от вашего решения, где вы просто пишете прямо в файл). Очевидно, это плохое решение для многопользовательских ситуаций.

Но этот подход подходит для небольших файлов, с ним легко работать и легко понять.

const
  FileName = 'test.txt';
var
  strList: TStringList;
begin
  strList := TStringList.Create;

  try
    if FileExists(FileName) then
      strList.LoadFromFile(FileName);

    strList.Add('My new line');

    strList.SaveToFile(FileName);
  finally
    strList.Free;
  end;
end;
4 голосов
/ 20 октября 2011

Если вы просто делаете что-то простое, IOUtils Unit намного проще.Он имеет множество утилит для записи в файлы.

например

процедура WriteAllText (const Path: string; const Contents Contents: string);перегрузки;static;

Создает новый файл, записывает указанную строку в файл и затем закрывает файл.Если целевой файл уже существует, он перезаписывается.

...