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ć?

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.


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.


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 
}

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

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.


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 .


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

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.


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.


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

1
użycie zamknie plik przez wywołanie Dispose. W twojej próbce plik został zamknięty dwukrotnie
— Valentine Zakharenko
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.