Arquivo sendo usado por outro processo após usar File.Create ()

117

Estou tentando detectar se existe um arquivo em tempo de execução, se não, crie-o. No entanto, estou recebendo este erro quando tento escrever nele:

O processo não pode acessar o arquivo 'myfile.ext' porque ele está sendo usado por outro processo.

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 
}

Alguma ideia de como consertar isso?

Brett
fonte

Respostas:

112

o File.Create método cria o arquivo e abre um FileStreamno arquivo. Portanto, seu arquivo já está aberto. Você realmente não precisa do método file.Create:

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

O booleano no StreamWriterconstrutor fará com que o conteúdo seja anexado se o arquivo existir.

Chris Dunaway
fonte
Tentei o código acima, mas estou recebendo o mesmo erro quando o arquivo é criado e quando tenta gravar no arquivo, ele mostra que o arquivo está sendo usado por outro processo.
Anmol Rathod
@AnmolRathod certifique-se de não usar o File.Create()método! O trecho acima já cria o arquivo!
Daniel Eisenreich de
138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Quero atualizar essa resposta para dizer que essa não é realmente a maneira mais eficiente de escrever todo o texto. Você só deve usar este código se precisar de algo rápido e sujo.

Eu era um jovem programador quando respondi a essa pergunta e, naquela época, achava que era algum tipo de gênio por ter essa resposta.

Carsen Daniel Yates
fonte
4
Eu amo como todas as outras respostas eram complicadas demais. As pessoas não percebem que existe uma resposta mais simples para cada problema.
Carsen Daniel Yates
14
A desvantagem desse código é que ele abre o arquivo duas vezes desnecessariamente. Além disso, não é realmente necessário verificar se o arquivo existe, pois o construtor FileStream o criará automaticamente para você se ele não existir, a menos que você diga explicitamente para não fazer isso.
reirab
2
@reirab Isso é completamente relativo. Preciso verificar se o arquivo existe e se existir, exclua-o e crie-o novamente, portanto, esta resposta é a preferida no meu caso.
makoshichi de
1
@SO Então você tem um problema diferente do OP, apenas um relacionado. Além disso, no seu caso, você ainda pode simplesmente usar o FileStream(string, FileMode)construtor e passá-lo FileMode.Create , que sobrescreverá qualquer arquivo existente. Ainda não há necessidade de abrir o arquivo duas vezes. Além disso, essa resposta foi editada depois que postei meu comentário original.
reirab
2
O objetivo desta resposta é mostrar que você pode apenas adicionar .Close()no final, então funciona em qualquer caso. Desconfio do sistema de usar FileStreampara tudo porque não quero que aconteça a exceção de FileMode.Createque o arquivo já está lá - especialmente quando quero limpar o conteúdo e não anexar a ele FileMode.Open. Para mim, FileStreamsó funciona realmente depois de me livrar do arquivo em questão e, em seguida, escrever para ele. Como File.Createestá deixando-o aberto e trancado, parece que adicionar .Close()a ele é a única maneira real de lidar com meu cenário e SOs.
vapcguy
25

Ao criar um arquivo de texto, você pode usar o seguinte código:

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

Usando o código do seu comentário. O arquivo (fluxo) que você criou deve ser fechado. File.Create retorna o fluxo de arquivos para o arquivo recém-criado:

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
fonte
Eu não pareço ter uma opção próxima. Aqui está o código: 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)) {// escrever meu texto}
Brett
File.Createretorna FileStreame isso temClose()
Null Head
15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
user3430377
fonte
7
Bem-vindo ao Stackoverflow. Você deve pelo menos escrever uma breve descrição para descrever sua resposta / solução.
Paresh Mayani
9

File.Create retorna um FileStream. Você precisa fechar isso quando escrever no arquivo:

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

Você pode usar para fechar o arquivo automaticamente.

Kimtiede
fonte
Embora o OP esteja tentando abrir um StreamWriter, pode-se inferir do uso de File.AppendText.
binki
8

Eu atualizei sua pergunta com o snippet de código. Após o recuo adequado, fica imediatamente claro qual é o problema: você usa, File.Create()mas não fecha oFileStream que ele retorna.

Fazer assim é desnecessário, StreamWriterjá permite anexar a um arquivo existente e criar um novo arquivo se ainda não existir. Como isso:

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

Que usa este StreamWriterconstrutor .

Hans Passant
fonte
1

Esta pergunta já foi respondida, mas aqui está uma solução do mundo real que verifica se o diretório existe e adiciona um número ao final se o arquivo de texto existe. Eu uso isso para criar arquivos de log diários em um serviço do Windows que escrevi. Espero que isso ajude alguém.

// 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();
    }
}
idílico
fonte
1

Eu sei que esta é uma pergunta antiga, mas eu só quero jogar isso para fora que você ainda pode usar File.Create("filename")", basta adicionar .Dispose()a ela.

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

Desta forma, ele cria e fecha o arquivo para o próximo processo utilizá-lo.

Eu sou o Batman
fonte
1
File.Create(FilePath).Close();da resposta acima tem this.Dispose(true); GC.SuppressFinalize((object) this);em sua implementação.
Ghukas de
1

Acho que sei o motivo dessa exceção. Você pode estar executando este trecho de código em vários segmentos.

Kusala Subasinghe
fonte
Para mim foi o problema de escrever um arquivo de log no modo assíncrono (em uma thread diferente: Task.Run () sem esperar (propositalmente), e isso causa acesso multithread ao mesmo arquivo.
Bence Végert
-1

Experimente: Funciona em qualquer caso, se o arquivo não existir, ele irá criá-lo e depois gravá-lo. E se já existir, não há problema, ele vai abrir e escrever nele:

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
fonte
1
usando irá fechar o arquivo pela chamada Dispose. Em seu arquivo de amostra foi fechado duas vezes
Valentine Zakharenko