2012-09-04 8 views
9

का उपयोग करने के लिए फ़ाइल तैयार है जब फ़ाइल वॉचर फ़ोल्डर में फ़ाइल की प्रतिलिपि बनाई जा रही है, तो मैं कैसे पहचान सकता हूं कि फ़ाइल पूरी तरह से कॉपी की गई है और उपयोग करने के लिए तैयार है? क्योंकि मुझे फाइल कॉपी के दौरान कई घटनाएं मिल रही हैं। (फ़ाइल को फ़ाइल.कॉपी का उपयोग करके किसी अन्य प्रोग्राम के माध्यम से कॉपी किया गया है।)फाइलसिस्टम वाटर -

उत्तर

2

फ़ाइल लिखते समय मुझे यह समस्या थी। फाइल पूरी तरह से लिखी और बंद होने से पहले मुझे घटनाएं मिलीं।

समाधान एक अस्थायी फ़ाइल नाम का उपयोग करना है और एक बार समाप्त होने के बाद फ़ाइल का नाम बदलना है। फिर फाइल निर्माण या घटना बदलने के बजाय फ़ाइल नाम बदलें घटना के लिए देखें।

+1

यह कोई काम नहीं करता है अगर कोई और आपको फ़ाइल को दबा रहा है (जैसे एफ़टीपी या उस तरह कुछ) - आपको यह जानना होगा कि फाइल का नाम बदलने से पहले आप इसका उपयोग करने के लिए तैयार हैं और कहें कि यह उपयोग करने के लिए तैयार है :) – Tacroy

1

नोट: यह समस्या सामान्य मामले में हल करने योग्य नहीं है। फ़ाइल उपयोग के बारे में पूर्व ज्ञान के बिना आप नहीं जानते कि अन्य प्रोग्राम फ़ाइल के साथ ऑपरेशन समाप्त कर चुके हैं या नहीं।

अपने विशेष मामले में आपको यह पता लगाने में सक्षम होना चाहिए कि कौन से ऑपरेशन फ़ाइल.कॉपी शामिल हैं।

अधिकतर संभावित गंतव्य फ़ाइल पूरे ऑपरेशन के दौरान बंद कर दी गई है। इस मामले में आप बस फ़ाइल खोलने और "साझाकरण मोड उल्लंघन" अपवाद को संभालने का प्रयास करने में सक्षम होना चाहिए।

आप कुछ समय के लिए भी इंतजार कर सकते हैं ... - बहुत अविश्वसनीय विकल्प, लेकिन यदि आप फ़ाइलों की आकार सीमा जानते हैं तो आप कॉपी को समाप्त करने के लिए उचित देरी कर सकते हैं।

आप किसी प्रकार की लेन-देन प्रणाली "आविष्कार" भी कर सकते हैं - यानी "destination_file_name.COPYLOCK" जैसी कोई अन्य फ़ाइल बनाएं, जो प्रोग्राम "प्रतिलिपि बनाने" फ़ाइल को "destination_file_name" कॉपी करने से पहले बनाएगा और बाद में हटा देगा।

9

जब मैं इस समस्या में भाग गया, तो सबसे अच्छा समाधान जो मैं आया था, लगातार फ़ाइल पर एक विशेष लॉक प्राप्त करने का प्रयास करना था; जबकि फ़ाइल लिखी जा रही है, लॉकिंग प्रयास विफल हो जाएगा, अनिवार्य रूप से this उत्तर में विधि। एक बार फ़ाइल को और नहीं लिखा जा रहा है, तो लॉक सफल हो जाएगा।

दुर्भाग्यवश, ऐसा करने का एकमात्र तरीका फ़ाइल खोलने के लिए एक कोशिश/पकड़ लपेटना है, जो मुझे क्रिंग करता है - कोशिश/पकड़ का उपयोग करना हमेशा दर्दनाक होता है। ऐसा लगता है कि इसके आस-पास कोई रास्ता नहीं लगता है, हालांकि, मैं इसका उपयोग कर समाप्त हुआ।

कि जवाब में कोड संशोधित काम कर देता है, तो मैं कुछ इस तरह का उपयोग कर समाप्त हो गया: एक Sleep के बीच के साथ

private void WaitForFile(FileInfo file) 
{ 
    FileStream stream = null; 
    bool FileReady = false; 
    while(!FileReady) 
    { 
     try 
     { 
      using(stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
      { 
       FileReady = true; 
      } 
     } 
     catch (IOException) 
     { 
      //File isn't ready yet, so we need to keep on waiting until it is. 
     } 
     //We'll want to wait a bit between polls, if the file isn't ready. 
     if(!FileReady) Thread.Sleep(1000); 
    } 
} 
+3

आप एक गिनती जोड़ना चाहते हैं और एक्स विफल प्रयासों के बाद प्रयास करना छोड़ सकते हैं। – McGarnagle

1

यहाँ एक विधि है कि फ़ाइल का उपयोग समय की एक्स संख्या तक फिर से प्रयास करेगा है, कोशिश करता है। यह पहुँच हो जाता है कभी नहीं करते हैं, तो आवेदन पर ले जाता है:

private static bool GetIdleFile(string path) 
{ 
    var fileIdle = false; 
    const int MaximumAttemptsAllowed = 30; 
    var attemptsMade = 0; 

    while (!fileIdle && attemptsMade <= MaximumAttemptsAllowed) 
    { 
     try 
     { 
      using (File.Open(path, FileMode.Open, FileAccess.ReadWrite)) 
      { 
       fileIdle = true; 
      } 
     } 
     catch 
     { 
      attemptsMade++; 
      Thread.Sleep(100); 
     } 
    } 

    return fileIdle; 
} 

यह इस तरह इस्तेमाल किया जा सकता:

private void WatcherOnCreated(object sender, FileSystemEventArgs e) 
{ 
    if (GetIdleFile(e.FullPath)) 
    { 
     // Do something like... 
     foreach (var line in File.ReadAllLines(e.FullPath)) 
     { 
      // Do more... 
     } 
    } 
} 
0
private Stream ReadWhenAvailable(FileInfo finfo, TimeSpan? ts = null) => Task.Run(() => 
    { 
     ts = ts == null ? new TimeSpan(long.MaxValue) : ts; 
     var start = DateTime.Now; 
     while (DateTime.Now - start < ts) 
     { 
      Thread.Sleep(200); 
      try 
      { 
       return new FileStream(finfo.FullName, FileMode.Open); 
      } 
      catch { } 
     } 
     return null; 
    }) 
    .Result; 

... जाहिर है, आप इस के पहलुओं को संशोधित कर सकते सूट करने के लिए अपने की जरूरत है।

संबंधित मुद्दे