Файл, який використовується іншим процесом після використання File.Create ()


117

Я намагаюся виявити, чи існує файл під час виконання, якщо ні, створити його. Однак я отримую цю помилку, коли намагаюся написати їй:

Процес не може отримати доступ до файлу 'myfile.ext', оскільки він використовується іншим процесом.

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 
}

Будь-які ідеї, як це виправити?

Відповіді:


112

File.CreateМетод створює файл і відкриває FileStreamна файл. Отже ваш файл уже відкритий. Файл вам зовсім не потрібен. Створіть метод взагалі:

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

Булева структура в StreamWriterконструкторі призведе до додавання вмісту, якщо файл існує.


Я спробував вищевказаний код, але я отримую ту ж помилку, коли файл створений і коли він намагається записати у файл, він показує, що файл використовується іншим процесом.
Anmol Rathod

@AnmolRathod переконайтеся, що ви не використовуєте File.Create()метод! Розташований вище фрагмент вже створює файл!
Даніель Айзенрайх

138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Я хочу оновити цю відповідь, щоб сказати, що це насправді не найефективніший спосіб написання всього тексту. Цей код слід використовувати лише тоді, коли вам потрібно щось швидке і брудне.

Я був молодим програмістом, коли відповів на це запитання, і тоді я думав, що я якийсь геній, що придумав цю відповідь.


4
Мені подобається, що всі інші відповіді були занадто складними. Люди не розуміють, що існує простіша відповідь на кожну проблему.
Карсен Даніель Йейтс

14
Недоліком цього коду є те, що він зайво відкриває файл двічі. Крім того, не потрібно перевіряти, чи існує файл взагалі, оскільки конструктор FileStream автоматично створить його для вас, якщо його не існує, якщо ви прямо не скажете йому цього робити.
reirab

2
@reirab Це абсолютно відносно. Мені потрібно перевірити, чи існує файл, і якщо він є, видалити його та створити його знову, тому ця відповідь є кращою у моєму випадку.
makoshichi

1
@SO Тоді у вас інша проблема, ніж з ОП, просто пов’язана. Крім того, у вашому випадку ви можете просто скористатися FileStream(string, FileMode)конструктором і передати його FileMode.Create , який замінить будь-який існуючий файл. Ще не потрібно відкривати файл двічі. Також ця відповідь була відредагована після того, як я опублікував свій оригінальний коментар.
reirab

2
Суть цієї відповіді полягає в тому, щоб показати, що ви можете просто додати .Close()в кінці, так що це працює в будь-якому випадку. Я не довіряю системі використання FileStreamдля всього, тому що я не хочу, щоб виняток стався з FileMode.Createтого, що файл вже є, особливо коли я хочу очистити вміст, а не додавати їх до них FileMode.Open. Для мене це FileStreamдійсно працює лише після того, як позбудеться відповідного файлу, а потім записати його. Оскільки File.Createвін залишає його відкритим і заблокованим, здається, що додавання .Close()до нього є єдиним реальним способом впоратися з моїм сценарієм та можливістю загального користування.
vapcguy

25

Створюючи текстовий файл, ви можете використовувати наступний код:

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

Використання коду з вашого коментаря. Створений вами файл (потік) повинен бути закритим. File.Create повернути потоковий файл у щойно створений файл .:

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 
}

Мені здається, немає близького варіанту. Ось код: string filePath = string.Format (@ "{0} \ M {1} .dat", ConfigurationManager.AppSettings ["DirectoryPath"], costCentre); if (! File.Exists (filePath)) {File.Create (filePath); } за допомогою (StreamWriter sw = File.AppendText (filePath)) {// написати мій текст}
Бретт

File.Createповертається, FileStreamа цеClose()
Null Head

15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();

7
Ласкаво просимо до Stackoverflow. Ви повинні хоча б написати короткий опис, щоб описати свою відповідь / рішення.
Paresh Mayani

9

File.Create повертає FileStream. Це потрібно закрити, коли ви записали у файл:

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

Ви можете використовувати за допомогою автоматичного закриття файлу.


Хоча ОП намагається відкрити те StreamWriter, що можна зробити з його використання File.AppendText.
бінкі

8

Я оновив ваше запитання за допомогою фрагмента коду. Після належного відступу, відразу зрозуміло, в чому проблема: ви використовуєте, File.Create()але не закриваєте те, FileStreamщо воно повертається.

Зробити це таким чином непотрібно, StreamWriterвже дозволяє додавати до вже наявного файлу та створювати новий файл, якщо він ще не існує. Подобається це:

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

Який використовує цей StreamWriterконструктор .


1

На це питання вже відповіли, але ось справжнє світове рішення, яке перевіряє, чи існує каталог, і додає число до кінця, якщо існує текстовий файл. Я використовую це для створення файлів щоденних журналів на службі Windows, яку я написав. Я сподіваюся, що це комусь допоможе.

// 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

Я знаю, що це давнє запитання, але я просто хочу викинути це там, яке ви ще можете використовувати File.Create("filename")", просто додайте .Dispose()до нього.

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

Таким чином він створює і закриває файл для наступного процесу для його використання.


1
File.Create(FilePath).Close();з відповіді вище this.Dispose(true); GC.SuppressFinalize((object) this);в своїй реалізації.
Гукас

1

Я думаю, я знаю причину цього винятку. Цей фрагмент коду може бути запущений у кількох потоках.


Для мене була проблема, що я записую файл журналу асинхронним способом (іншою темою: Task.Run (), не чекаючи (спеціально), і це спричиняє багатопотоковий доступ до того самого файлу.
Bence Végert,

-1

Спробуйте це: у будь-якому випадку він працює, якщо файл не існує, він створить його і потім запише до нього. І якщо вона вже існує, немає проблем, вона відкриється і напише їй:

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
за допомогою закриє файл за викликом Dispose. У вашому зразку файл був закритий двічі
Валентин Захаренко,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.