185

I would like to create a .txt file and write to it, and if the file already exists I just want to append some more lines:

string path = @"E:\AppServ\Example.txt";
if (!File.Exists(path))
{
    File.Create(path);
    TextWriter tw = new StreamWriter(path);
    tw.WriteLine("The very first line!");
    tw.Close();
}
else if (File.Exists(path))
{
    TextWriter tw = new StreamWriter(path);
    tw.WriteLine("The next line!");
    tw.Close(); 
}

But the first line seems to always get overwritten... how can I avoid writing on the same line (I'm using this in a loop)?

I know it's a pretty simple thing, but I never used the WriteLine method before. I'm totally new to C#.

Johnny Bueti
  • 637
  • 1
  • 8
  • 27
Berker Yüceer
  • 7,026
  • 18
  • 68
  • 102
  • 12
    Beware that **almost all answers here are wrong** and subject to **race conditions**. Remember: the pattern `if (file exists) { open file }` is almost always wrong in all programming languages! For .NET the solution is to use [`File.Open(path, FileMode.Append, FileAccess.ReadWrite)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_) with appropriate flags. – ComFreek Aug 21 '19 at 08:23
  • "A FileMode value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten." so same thing done by .net instead of manual approach here. So it's not wrong here, it is the same process done manually. You may say unefficient but saying wrong doesn't count. – Berker Yüceer Aug 21 '19 at 10:07
  • The difference is: `File.Open` internally delegates to a WinAPI function (see next comment) hopefully preventing the race condition. Most solutions here do not do this and are pretty obviously subject to race conditions. – ComFreek Aug 21 '19 at 13:02
  • `File.Open` internally calls one [`FileStream` c'tor](https://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs,76ef6c04de9d0ed8,references) which in turns calls [`SafeCreateFile`](https://referencesource.microsoft.com/#mscorlib/microsoft/win32/win32native.cs,99d4d2e82c581557) which calls [WinAPI's `CreateFileA`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea). `FileAccess.CreateNew` is probably forwarded to the latter function as `CREATE_NEW`. I am pretty confident that a WinAPI function with such a flag accounts for race conditions. – ComFreek Aug 21 '19 at 13:04
  • 2
    The existence check however is determined by FileMode.Append here.. and it directs to an existence check then creates file with CreateFileA. Still saying wrong a little bit extreme, but you can say unefficient. We also should not forget the existence check may not be used only for write/read access may also be used by other matters so for new starters this topic is usefull to understand how it works. However if you can add an answer including all the definitions you wrote here and the reason why it is better that would help a lot as an answer and probably will be chosen as correct. – Berker Yüceer Aug 21 '19 at 13:23
  • 4
    @ComFreek I strongly agree that you should write a complete answer about it to explain it clearly. Comments are not for answering, and I'm sincerely curious about these race conditions and how you propose to solve it. – Zoma Sep 25 '19 at 08:39

15 Answers15

191

Use the correct constructor:

else if (File.Exists(path))
{
    using(var sw = new StreamWriter(path, true))
    {
        sw.WriteLine("The next line!");
    }
}
Amin Golmahalleh
  • 3,585
  • 2
  • 23
  • 36
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • 11
    First answer, Most simple answer, Most usefull answer for me lol. When i looked at it i was like: Huh? just adding ",true" is enough? How come i wont see that before? Damn... I felt like a total dumb thanks. I really preciate these kinda good answers. – Berker Yüceer Mar 28 '12 at 13:07
  • 7
    hint: If the file does not exist, this constructor creates a new file. – Abou-Emish Mar 06 '16 at 15:09
  • 1
    wrap i in a using (see answer below). – David Thielen Feb 01 '17 at 02:45
  • 1
    Close is redundant, if you have using – Michael Freidgeim Mar 05 '18 at 11:14
  • 5
    -1 This is subject to race conditions and may produce wrong behavior! Perhaps rather use [`File.Open(path, FileMode.Append, FileAccess.ReadWrite)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_) and check the file size via that returned stream. – ComFreek Aug 21 '19 at 08:20
70
string path = @"E:\AppServ\Example.txt";
File.AppendAllLines(path, new [] { "The very first line!" });

See also File.AppendAllText(). AppendAllLines will add a newline to each line without having to put it there yourself.

Both methods will create the file if it doesn't exist so you don't have to.

drch
  • 3,040
  • 1
  • 18
  • 29
  • 3
    I think this is more appropriate for what the user was asking. It sounds like there are 2 issues. 1 is the text is overwritten - this is because WriteLine is over-writing the file. In this case, File.AppendAllText is more appropriate. and 2) - the question of how can I create my file and know I'm appending to it. Its good to know it File.AppendAllText creates the file, that was my question. StreamWriter isn't always appropriate, it depends on what that application is used for. Either case this helped me out. +1 – Devin C Jan 09 '19 at 14:47
  • Why is this not the top answer? 3 lines and uses .net library – Lightsout Nov 30 '21 at 20:26
48
string path=@"E:\AppServ\Example.txt";

if(!File.Exists(path))
{
   File.Create(path).Dispose();

   using( TextWriter tw = new StreamWriter(path))
   {
      tw.WriteLine("The very first line!");
   }

}    
else if (File.Exists(path))
{
   using(TextWriter tw = new StreamWriter(path))
   {
      tw.WriteLine("The next line!");
   }
}
Rich
  • 3,928
  • 4
  • 37
  • 66
Aek
  • 499
  • 4
  • 4
  • I have a same problem too,and find this poster but solutions in here doesnt solve my problem. So I use some pieces of solution and just add Dispose().My aim doesnt involve copy-paste. – Aek Sep 24 '13 at 07:25
  • 1
    I'm not suggesting it did; I'm saying that without including that in your answer, the original poster won't know why you made the changes you made or what they're supposed to accomplish. Always include all relevant information when you post, so that people will know all of what you're doing. :) – DiMono Sep 24 '13 at 19:50
  • 1
    This works because it doesn't give an error that says you can't write to the newly created file because it's being used by another process. The .Dispose() is key. Thank you so much! – GenXisT May 12 '14 at 20:33
  • This doesn't in any way address the question, which is about preserving the existing contents. – Ben Voigt Oct 31 '14 at 13:57
  • There's no point in calling `Close()` from a `using` statement, as all resources will be closed before being disposed automatically. – Sheridan Mar 14 '16 at 15:35
  • 1
    -1 This is subject to race conditions and may produce wrong behavior! Perhaps rather use [`File.Open(path, FileMode.Append, FileAccess.ReadWrite)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_) and check the file size via that returned stream. – ComFreek Aug 21 '19 at 08:21
  • +1 for the ".Dispose()", many forget about it and end up running into another problem which is "cannot access file because its being used by another process ! ". – The Doctor Jan 19 '23 at 15:28
25

You don't actually have to check if the file exists, as StreamWriter will do that for you. If you open it in append-mode, the file will be created if it does not exists, then you will always append and never over write. So your initial check is redundant.

TextWriter tw = new StreamWriter(path, true);
tw.WriteLine("The next line!");
tw.Close(); 
John Boling
  • 464
  • 6
  • 14
  • 1
    I was trying to work out the logic of the accepted answer, I knew I had done this in one line before but couldn't remember the exact syntax. Thank you. – Morvael May 10 '19 at 10:45
15

File.AppendAllText adds a string to a file. It also creates a text file if the file does not exist. If you don't need to read content, it's very efficient. The use case is logging.

File.AppendAllText("C:\\log.txt", "hello world\n");
Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
dubucha
  • 1,027
  • 10
  • 16
6

You just want to open the file in "append" mode.

http://msdn.microsoft.com/en-us/library/3zc0w663.aspx

Ed Manet
  • 3,118
  • 3
  • 20
  • 23
  • yea this is usefull too but i was looking for a fast and simple solution and thanks to @Daniel Hilgarth he provided that kinda solution. so +1. – Berker Yüceer Mar 28 '12 at 13:10
5

You can just use File.AppendAllText() Method this will solve your problem. This method will take care of File Creation if not available, opening and closing the file.

var outputPath = @"E:\Example.txt";
var data = "Example Data";
File.AppendAllText(outputPath, data);
Vijay Shaaruck
  • 611
  • 8
  • 5
3

Try this.

string path = @"E:\AppServ\Example.txt";
if (!File.Exists(path))
{
    using (var txtFile = File.AppendText(path))
    {
        txtFile.WriteLine("The very first line!");
    }
}
else if (File.Exists(path))
{     
    using (var txtFile = File.AppendText(path))
    {
        txtFile.WriteLine("The next line!");
    }
}
Asiri Jayaweera
  • 199
  • 1
  • 7
  • Redudant `File.AppendText(path)`, and with it no need to check for `File.Exists(path)`. And `If (not A) Else If (A)` is a weird If/Else. Basically there is no thing good in this question, no explanation code that is a redudant version of other answer. – xdtTransform Jul 15 '19 at 11:14
  • -1 This is subject to race conditions and may produce wrong behavior! Perhaps rather use [`File.Open(path, FileMode.Append, FileAccess.ReadWrite)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_) and check the file size via that returned stream. – ComFreek Aug 21 '19 at 08:21
  • About File.AppendText, according to its reference: "Creates a StreamWriter that appends UTF-8 encoded text to an existing file, or to a new file if the specified file does not exist." – cesAR Aug 12 '20 at 22:12
3

When you start StreamWriter it's override the text was there before. You can use append property like so:

TextWriter t = new StreamWriter(path, true);
Matan Shahar
  • 3,190
  • 2
  • 20
  • 45
3
 else if (File.Exists(path)) 
{ 
  using (StreamWriter w = File.AppendText(path))
        {
            w.WriteLine("The next line!"); 
            w.Close();
        }
 } 
Smack
  • 936
  • 1
  • 13
  • 31
  • 1
    If you have `using' block, w.Close is redundant. Dispose at the end of using block does the same. – Michael Freidgeim Aug 25 '18 at 02:17
  • -1 This is subject to race conditions and may produce wrong behavior! Perhaps rather use [`File.Open(path, FileMode.Append, FileAccess.ReadWrite)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_) and check the file size via that returned stream. – ComFreek Aug 21 '19 at 08:21
2

You could use a FileStream. This does all the work for you.

http://www.csharp-examples.net/filestream-open-file/

Tom Ceuppens
  • 378
  • 4
  • 15
1

From microsoft documentation, you can create file if not exist and append to it in a single call File.AppendAllText Method (String, String)

.NET Framework (current version) Other Versions

Opens a file, appends the specified string to the file, and then closes the file. If the file does not exist, this method creates a file, writes the specified string to the file, then closes the file. Namespace: System.IO Assembly: mscorlib (in mscorlib.dll)

Syntax C#C++F#VB public static void AppendAllText( string path, string contents ) Parameters path Type: System.String The file to append the specified string to. contents Type: System.String The string to append to the file.

AppendAllText

David Fawzy
  • 1,056
  • 15
  • 17
1
using(var tw = new StreamWriter(path, File.Exists(path)))
{
    tw.WriteLine(message);
}
  • Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – Tim Diekmann May 24 '18 at 09:23
0

.NET Core Console App:

public static string RootDir() => Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, @"..\..\..\"));


string _OutputPath = RootDir() + "\\Output\\" + "MyFile.txt";
if (!File.Exists(_OutputPath))
    File.Create(_OutputPath).Dispose();
using (TextWriter _StreamWriter = new StreamWriter(_OutputPath))
{
    _StreamWriter.WriteLine(strOriginalText);
}


      
0

Please note that AppendAllLines and AppendAllText methods only create the file, but not the path. So if you are trying to create a file in "C:\Folder", please ensure that this path exists.

Jaideep Dhumal
  • 903
  • 6
  • 6