Файл используется другим процессом после использования File.Create ()

118

Я пытаюсь определить, существует ли файл во время выполнения, если нет, создайте его. Однако я получаю эту ошибку, когда пытаюсь написать на нее:

Процесс не может получить доступ к файлу 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 
}

Есть идеи, как это исправить?

Brett
источник

Ответы:

112

File.CreateМетод создает файл и открывает FileStreamна файл. Итак, ваш файл уже открыт. Вам вообще не нужен метод file.Create:

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

Логическое значение в StreamWriterконструкторе приведет к добавлению содержимого, если файл существует.

Крис Данауэй
источник
Я пробовал приведенный выше код, но получаю ту же ошибку, когда файл создается, и когда он пытается записать в файл, он показывает, что файл используется другим процессом.
Anmol Rathod
@AnmolRathod убедитесь, что вы не используете File.Create()метод! Приведенный выше фрагмент уже создает файл!
Daniel Eisenreich
138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Я хочу обновить этот ответ, чтобы сказать, что это не самый эффективный способ написать весь текст. Вы должны использовать этот код, только если вам нужно что-то быстрое и грязное.

Я был молодым программистом, когда ответил на этот вопрос, и тогда я подумал, что был гением, придумавшим этот ответ.

Карсен Даниэль Йейтс
источник
4
Мне нравится, что все остальные ответы были слишком сложными. Люди не понимают, что на каждую проблему есть более простой ответ.
Carsen Daniel Yates
14
Обратной стороной этого кода является то, что он без необходимости открывает файл дважды. Кроме того, на самом деле нет необходимости проверять, существует ли вообще файл, поскольку конструктор FileStream автоматически создаст его для вас, если он не существует, если вы явно не укажете ему не делать этого.
Рейраб 09
2
@reirab Это полностью относительно. Мне нужно проверить, существует ли файл, и если он существует, удалить его и создать снова, поэтому этот ответ предпочтительнее в моем случае.
makoshichi
1
@SO Тогда у вас другая проблема, чем OP, просто связанная с ней. Кроме того, в вашем случае вы все равно можете просто использовать FileStream(string, FileMode)конструктор и передать ему FileMode.Create , который перезапишет любой существующий файл. По-прежнему нет необходимости открывать файл дважды. Кроме того, этот ответ был отредактирован после того, как я опубликовал свой исходный комментарий.
Рейраб
2
Суть этого ответа в том, чтобы показать, что вы можете просто добавить .Close()в конце, чтобы он работал в любом случае. Я не доверяю системе использования FileStreamдля всего, потому что я не хочу, чтобы исключение произошло в FileMode.Createтом случае, если файл уже существует, особенно когда я хочу очистить содержимое, а не добавлять к нему FileMode.Open. Для меня это FileStreamдействительно работает только после того, как я избавился от рассматриваемого файла, а затем записал в него. Поскольку File.Createон оставляет его открытым и заблокированным, кажется, что добавление .Close()к нему - единственный реальный способ справиться с моим сценарием и SO.
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); если (! File.Exists (filePath)) {File.Create (filePath); } using (StreamWriter sw = File.AppendText (filePath)) {// напишу мой текст}
Бретт
File.Createвозвращается, FileStreamи у него естьClose()
Null Head
15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
user3430377
источник
7
Добро пожаловать в Stackoverflow. Вы должны хотя бы написать краткое описание своего ответа / решения.
Пареш Майани
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);
        }

Вы можете использовать using для автоматического закрытия файла.

kimtiede
источник
Хотя OP пытается открыть файл, о StreamWriterчем можно судить по его использованию File.AppendText.
binki
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 () без ожидания (намеренно), и это вызывает многопоточный доступ к одному и тому же файлу.
Бенце Вегерт,
-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(); 
 } 
PureSilence
источник
1
using закроет файл вызовом Dispose. В вашем семпле файл был закрыт дважды
Валентин Захаренко