Utwórz plik .txt, jeśli nie istnieje, a jeśli tak, dołącz nowy wiersz

161

Chciałbym stworzyć plik .txt i napisać do niego, a jeśli plik już istnieje, chcę tylko dodać kilka wierszy:

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(); 
}

Ale wydaje się, że pierwsza linia zawsze jest nadpisywana ... jak mogę uniknąć pisania w tej samej linii (używam tego w pętli)?

Wiem, że to dość prosta rzecz, ale nigdy wcześniej nie korzystałem z tej WriteLinemetody. Jestem zupełnie nowy w C #.

Berker Yüceer
źródło
3
Uważaj, prawie wszystkie odpowiedzi tutaj są błędne i zależą od warunków wyścigu . Pamiętaj: wzorzec if (file exists) { open file }jest prawie zawsze błędny we wszystkich językach programowania! W przypadku platformy .NET rozwiązaniem jest użycie File.Open(path, FileMode.Append, FileAccess.ReadWrite)odpowiednich flag.
ComFreek
„Wartość FileMode, która określa, czy plik jest tworzony, jeśli taki nie istnieje, i określa, czy zawartość istniejących plików jest zachowywana, czy nadpisywana”. tak samo robi .net zamiast ręcznego podejścia tutaj. Więc nie jest źle, jest to ten sam proces, który jest wykonywany ręcznie. Możesz powiedzieć, że nieefektywne, ale mówienie źle się nie liczy.
Berker Yüceer
Różnica polega na tym, że File.Openwewnętrznie deleguje do funkcji WinAPI (patrz następny komentarz), miejmy nadzieję, że zapobiega wyścigowi. Większość rozwiązań tutaj tego nie robi i są one oczywiście uzależnione od warunków wyścigu.
ComFreek
1
Jednak sprawdzenie istnienia jest określane przez FileMode.Append tutaj .. i kieruje do sprawdzenia istnienia, a następnie tworzy plik z CreateFileA. Nadal mówisz źle, trochę ekstremalnie, ale możesz powiedzieć, że nieskuteczne. Nie powinniśmy również zapominać, że sprawdzenie istnienia nie może być używane tylko do zapisu / odczytu, może być również używane przez inne sprawy, więc dla początkujących ten temat jest przydatny do zrozumienia, jak to działa. Jeśli jednak możesz dodać odpowiedź zawierającą wszystkie definicje, które tutaj napisałeś i powód, dla którego jest lepiej, to bardzo by pomogło jako odpowiedź i prawdopodobnie zostanie wybrane jako poprawne.
Berker Yüceer
1
@ComFreek Zdecydowanie zgadzam się, że powinieneś napisać pełną odpowiedź na ten temat, aby jasno to wyjaśnić. Komentarze nie służą do odpowiadania na nie i jestem szczerze ciekawa warunków wyścigu i tego, jak proponujesz je rozwiązać.
Matthieu Foltzer

Odpowiedzi:

167

Użyj odpowiedniego konstruktora :

else if (File.Exists(path))
{
    using(var tw = new StreamWriter(path, true))
    {
        tw.WriteLine("The next line!");
    }
}
Daniel Hilgarth
źródło
11
Pierwsza odpowiedź, najprostsza odpowiedź, najbardziej przydatna odpowiedź dla mnie lol. Kiedy na to spojrzałem, pomyślałem: Hę? wystarczy dodać „prawda”? Dlaczego nie widzę tego wcześniej? Cholera ... Czułem się jak totalnie głupi dzięki. Naprawdę doceniam te dobre odpowiedzi.
Berker Yüceer
7
wskazówka: Jeśli plik nie istnieje, ten konstruktor tworzy nowy plik.
Abou-Emish
1
zawiń w użycie (patrz odpowiedź poniżej).
David Thielen
1
Zamknięcie jest zbędne, jeśli używasz
Michael Freidgeim
2
-1 Zależy to od warunków wyścigu i może powodować niewłaściwe zachowanie! Może raczej użyj File.Open(path, FileMode.Append, FileAccess.ReadWrite)i sprawdź rozmiar pliku przez ten zwrócony strumień.
ComFreek
57
string path = @"E:\AppServ\Example.txt";
File.AppendAllLines(path, new [] { "The very first line!" });

Zobacz także File.AppendAllText (). AppendAllLines doda nową linię do każdej linii bez konieczności jej samodzielnego umieszczania.

Obie metody utworzą plik, jeśli nie istnieje, więc nie musisz.

drch
źródło
3
Myślę, że jest to bardziej odpowiednie dla tego, o co prosił użytkownik. Wygląda na to, że są 2 problemy. 1 oznacza, że ​​tekst jest nadpisywany - dzieje się tak, ponieważ WriteLine nadpisuje plik. W takim przypadku bardziej odpowiedni jest plik File.AppendAllText. i 2) - pytanie jak mogę stworzyć swój plik i wiedzieć, że do niego doklejam. Dobrze wiedzieć, że File.AppendAllText tworzy plik, to było moje pytanie. StreamWriter nie zawsze jest odpowiedni, zależy to od tego, do czego ta aplikacja jest używana. W każdym razie to mi pomogło. +1
Devin C,
42
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!");
   }
}
Aek
źródło
Ja też mam ten sam problem i znalazłem ten plakat, ale rozwiązania tutaj nie rozwiązują mojego problemu. Więc używam kilku fragmentów rozwiązania i po prostu dodaję Dispose () .Moim celem nie jest kopiowanie i wklejanie.
Aek,
1
Nie sugeruję, że tak; Mówię, że bez uwzględnienia tego w Twojej odpowiedzi oryginalny plakat nie będzie wiedział, dlaczego wprowadziłeś zmiany, które wprowadziłeś, ani co mają osiągnąć. Zawsze dołączaj wszystkie istotne informacje, kiedy publikujesz, aby ludzie wiedzieli o wszystkim, co robisz. :)
DiMono,
1
Działa to, ponieważ nie wyświetla błędu informującego, że nie możesz pisać do nowo utworzonego pliku, ponieważ jest używany przez inny proces. Kluczem jest .Dispose (). Dziękuję bardzo!
GenXisT
To w żaden sposób nie rozwiązuje problemu, który polega na zachowaniu istniejącej treści.
Ben Voigt
Nie ma sensu wywoływać Close()z usinginstrukcji, ponieważ wszystkie zasoby zostaną zamknięte przed automatycznym usunięciem.
Sheridan,
21

W rzeczywistości nie musisz sprawdzać, czy plik istnieje, ponieważ StreamWriter zrobi to za Ciebie. Jeśli otworzysz go w trybie dopisywania, plik zostanie utworzony, jeśli nie istnieje, wtedy zawsze będziesz dodawać i nigdy nie nadpisywać. Więc twoja wstępna kontrola jest zbędna.

TextWriter tw = new StreamWriter(path, true);
tw.WriteLine("The next line!");
tw.Close(); 
John Boling
źródło
1
Próbowałem wypracować logikę zaakceptowanej odpowiedzi, wiedziałem, że zrobiłem to wcześniej w jednej linii, ale nie pamiętałem dokładnej składni. Dziękuję Ci.
Morvael
14

File.AppendAllText dodaje ciąg do pliku. Tworzy również plik tekstowy, jeśli plik nie istnieje. Jeśli nie musisz czytać treści, jest to bardzo wydajne. Przypadek użycia to rejestrowanie.

File.AppendAllText("C:\\log.txt", "hello world\n");
R.Cha
źródło
To jest właśnie to, czego potrzebowałem, ale jak mogę sprawić, aby nowa zawartość zaczęła się w nowej linii? Używam plików CSV.
NiallUK
Chyba nie ma prostego rozwiązania. Proponuję sprawdzić ten wpis. stackoverflow.com/questions/1343044/…
R.Cha
6

Chcesz tylko otworzyć plik w trybie „dołączania”.

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

Ed Manet
źródło
Tak, to też jest przydatne, ale szukałem szybkiego i prostego rozwiązania, a dzięki @Daniel Hilgarth dostarczył takie rozwiązanie. więc +1.
Berker Yüceer
3

Po uruchomieniu StreamWriter zastępuje tekst, który był tam wcześniej. Możesz użyć właściwości append w następujący sposób:

TextWriter t = new StreamWriter(path, true);
Matan Shahar
źródło
3
 else if (File.Exists(path)) 
{ 
  using (StreamWriter w = File.AppendText(path))
        {
            w.WriteLine("The next line!"); 
            w.Close();
        }
 } 
Uderzyć
źródło
1
Jeśli masz blok 'using', w.Close jest zbędne. Dispose na końcu używania bloku robi to samo.
Michael Freidgeim,
-1 Zależy to od warunków wyścigu i może powodować niewłaściwe zachowanie! Może raczej użyj File.Open(path, FileMode.Append, FileAccess.ReadWrite)i sprawdź rozmiar pliku przez ten zwrócony strumień.
ComFreek
2

Spróbuj tego.

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
źródło
Nadmiarowy File.AppendText(path), a dzięki temu nie trzeba go sprawdzać File.Exists(path). I If (not A) Else If (A)to dziwne Jeśli / Inaczej. Zasadniczo nie ma nic dobrego w tym pytaniu, nie ma kodu wyjaśniającego, który byłby redudatywną wersją innej odpowiedzi.
xdtTransform
-1 Zależy to od warunków wyścigu i może powodować niewłaściwe zachowanie! Może raczej użyj File.Open(path, FileMode.Append, FileAccess.ReadWrite)i sprawdź rozmiar pliku przez ten zwrócony strumień.
ComFreek
2

Możesz po prostu użyć metody File.AppendAllText (), aby rozwiązać problem. Ta metoda zajmie się tworzeniem pliku, jeśli nie jest dostępna, otwieraniem i zamykaniem pliku.

var outputPath = @"E:\Example.txt";
var data = "Example Data";
File.AppendAllText(outputPath, data);
Vijay Shaaruck
źródło
1

Z dokumentacji firmy Microsoft można utworzyć plik, jeśli nie istnieje, i dołączyć do niego w jednym wywołaniu Metoda File.AppendAllText (String, String)

.NET Framework (aktualna wersja) Inne wersje

Otwiera plik, dołącza określony ciąg do pliku, a następnie zamyka plik. Jeśli plik nie istnieje, ta metoda tworzy plik, zapisuje określony ciąg do pliku, a następnie zamyka plik. Przestrzeń nazw: System.IO Assembly: mscorlib (w mscorlib.dll)

Składnia C # C ++ F # VB public static void AppendAllText (ścieżka ciągu, zawartość ciągu) Parametry ścieżka Typ: System.String Plik, do którego ma zostać dołączony określony ciąg. zawartość Typ: System.String Ciąg do dołączenia do pliku.

AppendAllText

David Fawzy
źródło
1
using(var tw = new StreamWriter(path, File.Exists(path)))
{
    tw.WriteLine(message);
}
Andreas Gusakov
źródło
Ogólnie odpowiedzi są znacznie bardziej pomocne, jeśli zawierają wyjaśnienie, do czego służy kod i dlaczego to rozwiązuje problem bez wprowadzania innych.
Tim Diekmann