Pregunta

He estado trabajando en este pequeño fragmento de código que parece trivial, pero aún así, realmente no puedo ver dónde está el problema. Mis funciones hacen una cosa bastante simple. Abre un archivo, copia su contenido, reemplaza una cadena dentro y vuelve a copiarlo en el archivo original (una simple búsqueda y reemplazo dentro de un archivo de texto). Realmente no sabía cómo hacerlo, ya que estoy agregando líneas al archivo original, así que solo creo una copia del archivo, (file.temp), también copio una copia de seguridad (file.temp) y luego elimino el archivo original (archivo) y copie el archivo.temp en el archivo. Recibo una excepción al eliminar el archivo. Aquí está el código de muestra:

private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod)
    {
        Boolean result = false;
        FileStream fs = new FileStream(file.FullName + ".tmp", FileMode.Create, FileAccess.Write);
        StreamWriter sw = new StreamWriter(fs);

        StreamReader streamreader = file.OpenText();
        String originalPath = file.FullName;
        string input = streamreader.ReadToEnd();
        Console.WriteLine("input : {0}", input);

        String tempString = input.Replace(extractedMethod, modifiedMethod);
        Console.WriteLine("replaced String {0}", tempString);

        try
        {
            sw.Write(tempString);
            sw.Flush();
            sw.Close();
            sw.Dispose();
            fs.Close();
            fs.Dispose();
            streamreader.Close();
            streamreader.Dispose();

            File.Copy(originalPath, originalPath + ".old", true);
            FileInfo newFile = new FileInfo(originalPath + ".tmp");
            File.Delete(originalPath);
            File.Copy(fs., originalPath, true);

            result = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        return result;
    }`

Y la excepción relacionada

System.IO.IOException: The process cannot access the file 'E:\mypath\myFile.cs' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.Delete(String path)
   at callingMethod.modifyFile(FileInfo file, String extractedMethod, String modifiedMethod)

Normalmente, estos errores provienen de secuencias de archivos no cerradas, pero me he ocupado de eso. Supongo que he olvidado un paso importante pero no puedo entender dónde. Muchas gracias por tu ayuda,

¿Fue útil?

Solución

Parece que un proceso externo (AV?) lo está bloqueando, pero ¿no puedes evitar el problema en primer lugar?

private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod)
{
    try
    {
        string contents = File.ReadAllText(file.FullName);
        Console.WriteLine("input : {0}", contents);
        contents = contents.Replace(extractedMethod, modifiedMethod);
        Console.WriteLine("replaced String {0}", contents);
        File.WriteAllText(file.FullName, contents);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        return false;
    }
}

Otros consejos

Me doy cuenta de que llego un poco tarde, pero aún mejor tarde que nunca. Estaba teniendo un problema similar recientemente. Utilicé XMLWriter para actualizar posteriormente el archivo XML y recibí los mismos errores. Encontré la solución limpia para esto:

El XMLWriter utiliza el FileStream subyacente para acceder al archivo modificado. El problema es que cuando llama al método XMLWriter.Close () , la secuencia subyacente no se cierra y bloquea el archivo. Lo que debe hacer es crear una instancia de su XMLWriter con la configuración y especificar que necesita cerrar esa secuencia subyacente.

Ejemplo:

XMLWriterSettings settings = new Settings();
settings.CloseOutput = true;
XMLWriter writer = new XMLWriter(filepath, settings);

Espero que ayude.

El código funciona lo mejor que puedo decir. Encendería Sysinternals process explorer y descubriría qué contiene el archivo abierto Bien podría ser Visual Studio.

Funcionó para mí.

Aquí está mi código de prueba. La ejecución de prueba sigue:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            FileInfo f = new FileInfo(args[0]);
            bool result = modifyFile(f, args[1],args[2]);
        }
        private static bool modifyFile(FileInfo file, string extractedMethod, string modifiedMethod) 
        { 
            Boolean result = false; 
            FileStream fs = new FileStream(file.FullName + ".tmp", FileMode.Create, FileAccess.Write); 
            StreamWriter sw = new StreamWriter(fs); 
            StreamReader streamreader = file.OpenText(); 
            String originalPath = file.FullName; 
            string input = streamreader.ReadToEnd(); 
            Console.WriteLine("input : {0}", input); 
            String tempString = input.Replace(extractedMethod, modifiedMethod); 
            Console.WriteLine("replaced String {0}", tempString); 
            try 
            { 
                sw.Write(tempString); 
                sw.Flush(); 
                sw.Close(); 
                sw.Dispose(); 
                fs.Close(); 
                fs.Dispose(); 
                streamreader.Close(); 
                streamreader.Dispose(); 
                File.Copy(originalPath, originalPath + ".old", true); 
                FileInfo newFile = new FileInfo(originalPath + ".tmp"); 
                File.Delete(originalPath); 
                File.Copy(originalPath + ".tmp", originalPath, true); 
                result = true; 
            } 
            catch (Exception ex) 
            { 
                Console.WriteLine(ex); 
            } 
            return result; 
        }
    }
}


C:\testarea>ConsoleApplication1.exe file.txt padding testing
input :         <style type="text/css">
        <!--
         #mytable {
          border-collapse: collapse;
          width: 300px;
         }
         #mytable th,
         #mytable td
         {
          border: 1px solid #000;
          padding: 3px;
         }
         #mytable tr.highlight {
          background-color: #eee;
         }
        //-->
        </style>
replaced String         <style type="text/css">
        <!--
         #mytable {
          border-collapse: collapse;
          width: 300px;
         }
         #mytable th,
         #mytable td
         {
          border: 1px solid #000;
          testing: 3px;
         }
         #mytable tr.highlight {
          background-color: #eee;
         }
        //-->
        </style>

Después de encontrar este error y no encontrar nada en la web que me enderezara, pensé en agregar otra razón para obtener esta Excepción: las rutas de origen y destino en el comando Copiar archivo son las mismas. Me tomó un tiempo descubrirlo, pero puede ayudar agregar código en algún lugar para lanzar una excepción si las rutas de origen y destino apuntan al mismo archivo.

¡Buena suerte!

¿Está ejecutando un antivirus en tiempo real por casualidad? Si es así, puede intentar (temporalmente) deshabilitarlo para ver si eso es lo que está accediendo al archivo que está tratando de eliminar. (La sugerencia de Chris de utilizar el explorador de procesos Sysinternals es buena).

Pruebe esto: funciona en cualquier caso, si el archivo no existe, lo creará y luego lo escribirá. Y si ya existe, no hay problema, se abrirá y le escribirá:

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

Después de crear un archivo, debe forzar la transmisión para liberar los recursos:

//FSm is stream for creating file on a path//
System.IO.FileStream FS = new System.IO.FileStream(path + fname,
                                                   System.IO.FileMode.Create);
pro.CopyTo(FS);
FS.Dispose();
 System.Drawing.Image FileUploadPhoto = System.Drawing.Image.FromFile(location1);
                                 FileUploadPhoto.Save(location2);
                                 FileUploadPhoto.Dispose();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top