2009-06-22 21 views
23

Pracowałem nad tym małym kawałkiem kodu, który wydaje się trywialny, ale nadal nie mogę zobaczyć, gdzie jest problem. Moje funkcje robią całkiem prostą rzecz. Otwiera plik, kopiuje jego zawartość, zastępuje ciąg wewnątrz i kopiuje go z powrotem do oryginalnego pliku (proste wyszukiwanie i zamiana w pliku tekstowym). Naprawdę nie wiedziałem, jak to zrobić, gdy dodam linie do oryginalnego pliku, więc po prostu utworzę kopię pliku, (file.temp) skopiuj także kopię zapasową (file.temp), a następnie skasuj oryginał plik (plik) i skopiuj plik file.temp do pliku. Otrzymuję wyjątek podczas usuwania pliku. Oto przykładowy kod:System.IO.IOException: plik używany przez inny proces

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

i związanym z wyjątkiem

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) 

Zwykle błędy te pochodzą z niezamkniętych strumieni plików, ale już załatwione, że. Sądzę, że zapomniałem o ważnym kroku, ale nie wiem, gdzie. Bardzo dziękuję za pomoc,

+1

spróbuj ustawić obiekt FileInfo przeszły do metody do wartości null. – TheVillageIdiot

Odpowiedz

23

Brzmi jak proces zewnętrzny (AV?) Blokuje go, ale czy w ogóle nie można go uniknąć?

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; 
    } 
} 
+13

+1 cały kompleks pozbyć się blisko, flush streamreader thingy (nie używając instrukcji itp. Itp.) Sprawia, że ​​dreszczę. jest to prosty problem w niezrozumiały bałagan. –

+0

Bardzo dziękuję za tę metodę, zgadzam się, że jest ona o wiele bardziej przejrzysta niż moja oryginalna. To rozwiązało mój problem! – srodriguez

+0

Dziękuję za to. Szukałem odpowiedzi na podobną sytuację. Zamknąłem już XMLWriter, ale wciąż mi podawał błąd. Kiedy umieściłem oświadczenie wewnątrz try-catch, przestałem podawać mi błąd. – illinoistim

5

Kod działa najlepiej, jak potrafię. Odpalałbym Sysinternals process explorer i sprawdzam, co trzyma plik otwarty. To może równie dobrze być Visual Studio.

3

To zadziałało dla mnie.

Oto mój kod testowy. Uruchomienie testu jest następujące:

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

Czy używasz skanera antywirusowego w czasie rzeczywistym przez przypadek? Jeśli tak, możesz spróbować (tymczasowo) wyłączyć go, aby sprawdzić, czy to właśnie jest dostęp do pliku, który próbujesz usunąć. (Sugestia Chrisa, aby użyć eksploratora procesu Sysinternals, jest dobra).

18

Zdaję sobie sprawę, że jestem trochę spóźniona, ale wciąż lepiej późno niż wcale. Ostatnio miałem podobny problem. Użyłem XMLWriter do późniejszego zaktualizowania pliku XML i otrzymałem te same błędy. Znalazłem czyste rozwiązanie tego problemu:

Urządzenie XMLWriter używa podrzędnego FileStream, aby uzyskać dostęp do zmodyfikowanego pliku. Problem polega na tym, że po wywołaniu metody XMLWriter.Close() strumień bazowy nie zostaje zamknięty i blokuje plik. Trzeba tylko utworzyć instancję z ustawieniami i określić, że potrzebny jest zamknięty strumień bazowy.

przykład:

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

Hope it pomaga.

4

Po napotkaniu tego błędu i braku znalezienia czegokolwiek w sieci, co mnie poprawiło, pomyślałem, że dodam kolejny powód do uzyskania tego wyjątku - a mianowicie, że ścieżki źródłowe i docelowe w poleceniu kopiowania plików są takie same. Zajęło mi to trochę czasu, ale może pomóc dodać gdzieś kod, aby wyrzucić wyjątek, jeśli ścieżki źródłowe i docelowe wskazują na ten sam plik.

Powodzenia!

2

Spróbuj tego: To działa w każdym przypadku, jeśli plik nie istnieje, to będzie go utworzyć, a następnie napisać do niego. A jeśli już istnieje, nie ma problemu otworzy i napisać do niego:

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

Nie wierzę, że to działa w każdym przypadku. Na przykład spróbuj napisać do pliku PDF otwartego przez Adobe Reader. – nalply

-1
System.Drawing.Image FileUploadPhoto = System.Drawing.Image.FromFile(location1); 
           FileUploadPhoto.Save(location2); 
           FileUploadPhoto.Dispose(); 
+0

Nie widzę, jak ten post można nazwać odpowiedzią, jeśli w ogóle niczego nie wyjaśnia. –

0

Po utworzeniu pliku trzeba wymusić strumień, aby zwolnić zasoby:

//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(); 
+0

FS.Dispose(); zwalnia zasoby –

Powiązane problemy