Plik używany przez inny proces po użyciu funkcji File.Create ()

118

Próbuję wykryć, czy plik istnieje w czasie wykonywania, jeśli nie, utwórz go. Jednak pojawia się ten błąd, gdy próbuję do niego napisać:

Proces nie może uzyskać dostępu do pliku „myfile.ext”, ponieważ jest używany przez inny proces.

string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
if (!File.Exists(filePath)) 
{ 
    File.Create(filePath); 
} 

using (StreamWriter sw = File.AppendText(filePath)) 
{ 
    //write my text 
}

Jakieś pomysły, jak to naprawić?

Brett
źródło

Odpowiedzi:

112

File.CreateMetoda tworzy plik i otwiera FileStreamplik. Twój plik jest już otwarty. Tak naprawdę nie potrzebujesz pliku, w ogóle metoda Create:

string filePath = @"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
    //write to the file
}

Wartość logiczna w StreamWriterkonstruktorze spowoduje dołączenie zawartości, jeśli plik istnieje.

Chris Dunaway
źródło
Wypróbowałem powyższy kod, ale otrzymuję ten sam błąd, gdy plik jest tworzony i kiedy próbuje zapisać się do pliku, pokazuje, że plik jest używany przez inny proces.
Anmol Rathod,
@AnmolRathod, upewnij się, że nie używasz File.Create()metody! Powyższy fragment już tworzy plik!
Daniel Eisenreich
138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Chcę zaktualizować tę odpowiedź, aby powiedzieć, że nie jest to najbardziej efektywny sposób pisania całego tekstu. Powinieneś używać tego kodu tylko wtedy, gdy potrzebujesz czegoś szybkiego i nieczystego.

Byłem młodym programistą, kiedy odpowiedziałem na to pytanie i wtedy myślałem, że jestem jakimś geniuszem, jeśli chodzi o wymyślenie takiej odpowiedzi.

Carsen Daniel Yates
źródło
4
Uwielbiam to, że wszystkie inne odpowiedzi były zbyt skomplikowane. Ludzie nie zdają sobie sprawy, że istnieje prostsza odpowiedź na każdy problem.
Carsen Daniel Yates
14
Wadą tego kodu jest to, że niepotrzebnie otwiera plik dwukrotnie. Ponadto nie jest konieczne sprawdzanie, czy plik w ogóle istnieje, ponieważ konstruktor FileStream automatycznie utworzy go za Ciebie, jeśli nie istnieje, chyba że wyraźnie powiesz mu, aby tego nie robił.
reirab
2
@reirab To jest całkowicie względne. Muszę sprawdzić, czy plik istnieje, a jeśli tak, usuń go i utwórz ponownie, więc w moim przypadku ta odpowiedź jest preferowana.
makoshichi
1
@SO Więc masz inny problem niż OP, tylko powiązany. Ponadto w twoim przypadku nadal możesz po prostu użyć FileStream(string, FileMode)konstruktora i przekazać go FileMode.Create , który nadpisze istniejący plik. Nadal nie ma potrzeby dwukrotnego otwierania pliku. Również ta odpowiedź została zredagowana po tym, jak zamieściłem mój oryginalny komentarz.
reirab
2
Celem tej odpowiedzi jest pokazanie, że możesz po prostu dodać .Close()na końcu, więc działa w każdym przypadku. Nie ufam systemowi używania FileStreamdo wszystkiego, ponieważ nie chcę, aby zdarzał się wyjątek, FileMode.Createże plik już tam jest - zwłaszcza gdy chcę wyczyścić zawartość i nie dołączać do niej za pośrednictwem FileMode.Open. Dla mnie FileStreamtak naprawdę działa tylko po pozbyciu się danego pliku, a następnie napisaniu do niego. Ponieważ File.Createpozostawia to otwarte i zamknięte, wydaje się, że dodawanie .Close()do niego jest jedynym prawdziwym sposobem radzenia sobie z moim scenariuszem i SO.
vapcguy
25

Tworząc plik tekstowy możesz skorzystać z następującego kodu:

System.IO.File.WriteAllText("c:\test.txt", "all of your content here");

Używając kodu z Twojego komentarza. Utworzony plik (strumień) musi zostać zamknięty. File.Create zwraca strumień pliku do właśnie utworzonego pliku .:

string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
    System.IO.FileStream f = System.IO.File.Create(filePath);
    f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{ 
    //write my text 
}
Ralf de Kleine
źródło
Wydaje się, że nie mam bliskiej opcji. Oto kod: string filePath = string.Format (@ "{0} \ M {1} .dat", ConfigurationManager.AppSettings ["DirectoryPath"], costCentre); if (! File.Exists (filePath)) {File.Create (filePath); } using (StreamWriter sw = File.AppendText (filePath)) {// napisz mój tekst}
Brett
File.Createpowraca FileStreami to maClose()
Null Head
15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
user3430377
źródło
7
Witamy w Stackoverflow. Powinieneś przynajmniej napisać krótki opis, aby opisać swoją odpowiedź / rozwiązanie.
Paresh Mayani
9

File.Create zwraca FileStream. Musisz to zamknąć, gdy napiszesz do pliku:

using (FileStream fs = File.Create(path, 1024)) 
        {
            Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
            // Add some information to the file.
            fs.Write(info, 0, info.Length);
        }

Możesz użyć do automatycznego zamykania pliku.

kimtiede
źródło
Chociaż OP próbuje otworzyć, StreamWriterjak można wywnioskować z jego użycia File.AppendText.
binki
8

Zaktualizowałem Twoje pytanie fragmentem kodu. Po odpowiednim wcięciu od razu widać, na czym polega problem: używasz, File.Create()ale nie zamykasz tego FileStream, co zwraca.

Zrobienie tego w ten sposób jest niepotrzebne, StreamWriterpozwala już na dołączenie do istniejącego pliku i utworzenie nowego pliku, jeśli jeszcze nie istnieje. Lubię to:

  string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
  using (StreamWriter sw = new StreamWriter(filePath, true)) {
    //write my text 
  }

Który używa tego StreamWriterkonstruktora .

Hans Passant
źródło
1

Na to pytanie udzielono już odpowiedzi, ale tutaj jest rozwiązanie ze świata rzeczywistego, które sprawdza, czy katalog istnieje i dodaje na końcu liczbę, jeśli plik tekstowy istnieje. Używam tego do tworzenia codziennych plików dziennika w usłudze Windows, którą napisałem. Mam nadzieję, że to komuś pomoże.

// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
    // filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
    var filePath = "C:\\Logs";

    // Append a backslash if one is not present at the end of the file path.
    if (!filePath.EndsWith("\\"))
    {
        filePath += "\\";
    }

    // Create the path if it doesn't exist.
    if (!Directory.Exists(filePath))
    {
        Directory.CreateDirectory(filePath);
    }

    // Create the file name with a calendar sortable date on the end.
    var now = DateTime.Now;
    filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);

    // Check if the file that is about to be created already exists. If so, append a number to the end.
    if (File.Exists(filePath))
    {
        var counter = 1;
        filePath = filePath.Replace(".txt", " (" + counter + ").txt");
        while (File.Exists(filePath))
        {
            filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
            counter++;
        }
    }

    // Note that after the file is created, the file stream is still open. It needs to be closed
    // once it is created if other methods need to access it.
    using (var file = File.Create(filePath))
    {
        file.Close();
    }
}
Zimorodek
źródło
1

Wiem, że to stare pytanie, ale chcę po prostu wyrzucić to, z którego nadal możesz korzystać File.Create("filename")", po prostu je dodaj .Dispose().

File.Create("filename").Dispose();

W ten sposób tworzy i zamyka plik do wykorzystania w następnym procesie.

Jestem Batmanem
źródło
1
File.Create(FilePath).Close();z powyższej odpowiedzi ma this.Dispose(true); GC.SuppressFinalize((object) this);w swojej realizacji.
Ghukas
1

Myślę, że znam powód tego wyjątku. Możesz uruchamiać ten fragment kodu w wielu wątkach.

Kusala Subasinghe
źródło
Dla mnie był problem, że piszę plik dziennika na Asynchroniczna sposób (w innym wątku. Task.Run () bez czekania (celowo), a to przyczyna multithread dostęp do tego samego pliku
Bence Végert
-1

Spróbuj tego: zadziała w każdym przypadku, jeśli plik nie istnieje, utworzy go, a następnie zapisze do niego. A jeśli już istnieje, nie ma problemu to otworzy się i napisze do niego:

using (FileStream fs= new FileStream(@"File.txt",FileMode.Create,FileAccess.ReadWrite))
{ 
     fs.close();
}
using (StreamWriter sw = new StreamWriter(@"File.txt")) 
 { 
    sw.WriteLine("bla bla bla"); 
    sw.Close(); 
 } 
PureSilence
źródło
1
użycie zamknie plik przez wywołanie Dispose. W twojej próbce plik został zamknięty dwukrotnie
Valentine Zakharenko