web-dev-qa-db-fra.com

Créer et / ou écrire dans un fichier

Je pense que cela devrait être facile, mais Google me manque totalement en ce moment. Je veux ouvrir un fichier, ou le créer s'il n'existe pas, et y écrire.

Le suivant

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

jette une erreur sur la deuxième ligne lorsque le fichier n'existe pas encore, ce qui, je suppose, est attendu. Mais je n'arrive vraiment pas à découvrir comment a) tester si le fichier existe et b) le créer en cas de besoin.

FYI, travaillant dans Delphi XE.

21
Eric G

Vous pouvez utiliser la fonction FileExists puis utiliser Append si elle existe ou Rewrite si non.

    AssignFile(logFile, 'Test.txt');

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

   //do your stuff

    CloseFile(logFile); 
36
RRUZ

Toute solution qui utilise FileExists pour choisir comment ouvrir le fichier a une condition de concurrence critique. Si l'existence du fichier change entre le moment où vous le testez et le moment où vous essayez d'ouvrir le fichier, votre programme échouera. Delphi ne fournit aucun moyen de résoudre ce problème avec ses routines d'E/S de fichiers natifs.

Si votre version Delphi est suffisamment nouvelle pour l'offrir, vous pouvez utiliser le TFile.Open avec le mode ouvert fmOpenOrCreate, qui fait exactement ce que vous voulez; il renvoie un TFileStream.

Sinon, vous pouvez utiliser la fonction API Windows CreateFile pour ouvrir votre fichier à la place. Définissez le paramètre dwCreationDisposition sur OPEN_ALWAYS, qui lui dit de créer le fichier s'il n'existe pas déjà.

24
Rob Kennedy

Vous devriez plutôt utiliser TFileStream. Voici un exemple qui va créer un fichier s'il n'existe pas, ou y écrire si c'est le cas:

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;
10
Ken White

Vous pouvez également utiliser la fonction de chargement/enregistrement dans un TStringList pour résoudre votre problème.

Cela peut être une mauvaise solution, car tout le fichier sera chargé en mémoire, modifié en mémoire puis enregistré sur le disque. (Par opposition à votre solution où vous écrivez simplement directement dans le fichier). C'est évidemment une mauvaise solution pour les situations multi-utilisateurs.

Mais cette approche est OK pour les fichiers plus petits, et elle est facile à utiliser et à comprendre.

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;
5

Si vous faites simplement quelque chose de simple, l'unité IOUtils est beaucoup plus facile. Il a beaucoup d'utilitaires pour écrire dans des fichiers.

par exemple.

procedure WriteAllText (const Chemin: chaîne; const Contenu: chaîne); surcharge; statique;

Crée un nouveau fichier, écrit la chaîne spécifiée dans le fichier, puis ferme le fichier. Si le fichier cible existe déjà, il est remplacé.

4
awmross