Почему я не могу создать текстовый файл после его удаления? - PullRequest
4 голосов
/ 29 декабря 2011

Моя программа создает файл журнала при запуске.У пользователя есть возможность через настройки «очистить журнал», который вызывает метод для удаления файла журнала.

        //calls for a YesNo prompt to delete log or not
        result = objectMessageBox.ReturnDeleteLogPrompt();

        if (result == DialogResult.Yes)
        {
            //throw prompt
            if (File.Exists(objectLog.GetLogLocation()) == true)
            {
                try
                {                        
                    //delete the log file
                    File.Delete(objectLog.GetLogLocation());                        

                    //throw balloon tip saying log was cleared
                    ShowBalloonTip("LogCleared");
                }
                catch (Exception ee)
                {
                    MessageBox.Show("Error thrown deleting log: " + ee);
                    System.Windows.Forms.Clipboard.SetText(ee.ToString());
                }
            }
        }

Поскольку я полностью удалил файл журнала, мне нужно его заново создать.Поэтому я вызываю метод, который имеет это:

try
        {
            //we create a new log file so it seems that the log has just been cleared
            objectLog.CreateLog();
        }
        catch (Exception ee)
        {
            MessageBox.Show("Error occured while clearing log:\n" + ee);
        }

Но когда он пытается воссоздать файл журнала, он выдает ошибку, которая говорит:

"System.IO.IOException:Процесс не может получить доступ к файлу '~~', потому что он используется другим процессом. "

Итак, кажется, что во время моего звонка, чтобы удалить файл, он продолжает обращаться к нему?Нужно ли мне что-то распоряжаться, когда я звоню file.delete?

Ответы [ 4 ]

6 голосов
/ 29 декабря 2011

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

  • Операция удаления все еще ожидает выполненияоперационная система
  • Антивирусная программа или аналогичная функция безопасности открывали файл в ответ на его удаление для анализа перед удалением
  • Антивирусная программа или аналогичная функция безопасности уже открывали файл, покавы использовали его и все еще отвечаете на запрос на удаление

Mercurial также имел эту проблему в Windows.Если вы выполнили одну команду, которая заблокировала хранилище (что было сделано с использованием временных файлов), а затем сразу же выполнили другую команду, которую либо нужно было заблокировать, либо, по крайней мере, убедиться, что блокировка отсутствует, она может завершиться с ошибкой того же типа,файл использовался, хотя это были два разных процесса, а первый уже завершился.

Другими словами, временная шкала была следующей:

  • hg.exe instance # 1запускается, блокирует репозиторий, создавая временный файл
  • hg.exe делает то, что ему нужно
  • hg.exe удаляет файл, затем выходит
  • hg.exeэкземпляр № 2 запускается, пытается заблокировать репозиторий, происходит сбой, потому что файл используется

Их взломать, чтобы «исправить», было просто выбрать случайное имя файла, которое не использовалось в каталоге,переименуйте файл с этим именем, а затем удалите его.Это не решило проблему с задержкой файла на короткое время, но освободило имя файла и сразу сделало его доступным для новых файлов.

4 голосов
/ 30 декабря 2011

Уже есть принятый ответ, но, возможно, кто-то найдет это полезным (или посмеется над этим, если я снова пропустил что-то очевидное и полностью потратил свое время)

У меня сложилось впечатление, что File.Delete либо удалитфайл и затем возвращать, или иначе генерировать исключение - пока я не прочитаю эту ветку.

Windows API упоминает, что при вызове DeleteFile файл «помечается для удаления при закрытии», поскольку он позволяет вызывать удаление пооткрытый файл.После того, как файл помечен для удаления, попытка открыть его завершится с ошибкой «Доступ запрещен».Когда последний дескриптор этого файла закрыт, файл фактически удаляется.

Если Windows действительно удаляет файл перед возвратом после последнего вызова CloseHandle файла, теоретически этот код гарантирует, что файлудаляется ниже блока using:

using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete))
{
    File.Delete(path);
}

Сбой File.Open произойдет, если другой процесс в данный момент откроет файл.

Обратите внимание на то, что File.Delete даже успешно выполняется, если файл не существует (если каталог не существует).

3 голосов
/ 29 декабря 2011

Вместо удаления и повторного создания одного и того же файла, вы можете просто очистить его?

Примерно так должно работать у вас:

FileStream f = File.Open(@[filename], FileMode.Create);
f.Close();
0 голосов
/ 29 декабря 2011

Вы можете использовать System.IO.FileInfo.Delete для удаления файла, а затем System.IO.FileInfo.Refresh () перед повторным созданием файла. Обновление должно остановить исключение при повторном создании файла. Или, как говорит nycdan, используйте перечисление FileMode.Create.

...