2009-07-13 17 views
13

मैं सी # का उपयोग कर स्थानीय निर्देशिकाओं में से एक का आकार प्राप्त करने में सक्षम होना चाहता हूं। हालांकि सबसे खराब स्थिति में मैं इस के लिए समझौता करना होगा मैं, निम्नलिखित (कोड की तरह छद्म) से बचने के लिए कोशिश कर रहा हूँ:मैं सी # में निर्देशिका आकार (निर्देशिका में फाइलें) कैसे प्राप्त करूं?

int GetSize(Directory) 
    { 
     int Size = 0; 

     foreach (File in Directory) 
     { 
      FileInfo fInfo of File; 
      Size += fInfo.Size; 
     } 

     foreach (SubDirectory in Directory) 
     { 
      Size += GetSize(SubDirectory); 
     } 
     return Size; 
    } 

मूल रूप से, वहाँ एक वॉक() उपलब्ध कहीं है, ताकि मैं चल सकता है निर्देशिका पेड़ के माध्यम से? जो प्रत्येक उप-निर्देशिका के माध्यम से जाने के पुनरावर्तन को बचाएगा।

उत्तर

18

आप का उपयोग करते हैं Directory.GetFiles आप एक पुनरावर्ती खोज के (SearchOption.AllDirectories का प्रयोग करके) कर सकते हैं, लेकिन यह भी एक सा परतदार है (यदि आप उप-निर्देशिका के लिए पहुँच नहीं है, खासकर अगर) - और एक विशाल एकल शामिल हो सकता है सरणी वापस आ रही है (चेतावनी klaxon ...)।

मैं रिकर्सन दृष्टिकोण से खुश हूं जब तक कि मैं एक बाधा उत्पन्न नहीं कर सकता; और फिर मैं रिकर्सन अनुकरण करने के लिए Queue<string> का उपयोग करके, (एकल-स्तर) Directory.GetFiles पर स्विच कर सकता हूं।

ध्यान दें कि .NET 4.0 कुछ एन्यूमेरेटर-आधारित फ़ाइल/निर्देशिका सूची विधियों को प्रस्तुत करता है जो बड़े सरणी पर सहेजते हैं।

+0

पिछले कोड लाइन पर कि :) – ThePower

0

मैं कुछ समय पहले एक ऐसे फ़ंक्शन के लिए देख रहा हूं जिसे आप पूछते हैं और जो मैंने इंटरनेट पर और एमएसडीएन मंचों में पाया है, वहां ऐसा कोई कार्य नहीं है।

रिकर्सिव तरीका केवल एक फ़ोल्डर के आकार को प्राप्त करने के लिए मिला है जिसमें सभी फाइलें और उपफोल्डर्स शामिल हैं।

4

आप एक विस्तार विधि के पीछे अपने प्रत्यावर्तन को छिपाने (मुद्दों मार्क GetFiles साथ प्रकाश डाला() विधि से बचने के लिए) हो सकता है:

public static IEnumerable<FileInfo> Walk(this DirectoryInfo directory) 
{ 
    foreach(FileInfo file in directory.GetFiles()) 
    { 
     yield return file; 
    } 

    foreach(DirectoryInfo subDirectory in directory.GetDirectories() 
    { 
     foreach(FileInfo file in subDirectory.Walk()) 
     { 
      yield return file; 
     } 
    } 
} 

(आप शायद कुछ अपवाद संरक्षित फ़ोल्डर के लिए इसे करने के लिए से निपटने जोड़ना चाहते हैं आदि)

तब:

int totalSize = 0; 

foreach(FileInfo file in directory.Walk()) 
{ 
    totalSize += file.Length; 
} 

मूल रूप से एक ही कोड, लेकिन शायद एक छोटे से neater ...

1

इस पोस्ट पर एक नज़र डालें:

http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/eed54ebe-facd-4305-b64b-9dbdc65df04e

मूल रूप से कोई साफ नेट तरीका है, लेकिन वहाँ एक काफी सरल कॉम दृष्टिकोण है, इसलिए यदि आप COM इंटरॉप का उपयोग करने और से बंधा जा रहा है के साथ खुश हैं विंडोज़, यह आपके लिए काम कर सकता है।

6

यहाँ मेरी .NET 4.0 दृष्टिकोण

public static long GetFileSizeSumFromDirectory(string searchDirectory) 
{ 
var files = Directory.EnumerateFiles(searchDirectory); 

// get the sizeof all files in the current directory 
var currentSize = (from file in files let fileInfo = new FileInfo(file) select fileInfo.Length).Sum(); 

var directories = Directory.EnumerateDirectories(searchDirectory); 

// get the size of all files in all subdirectories 
var subDirSize = (from directory in directories select GetFileSizeSumFromDirectory(directory)).Sum(); 

return currentSize + subDirSize; 
} 

या यहां तक ​​कि अच्छे:

// get IEnumerable from all files in the current dir and all sub dirs 
var files = Directory.EnumerateFiles(searchDirectory,"*",SearchOption.AllDirectories); 

// get the size of all files 
long sum = (from file in files let fileInfo = new FileInfo(file) select fileInfo .Length).Sum(); 

गेब्रियल के रूप में बताया इस अगर आप searchDirectory के तहत एक प्रतिबंधित निर्देशिका है असफल हो जायेगी! नेट 4 DirectoryInfo की नई विधि की तरह एक UnauthorizedAccessException पर रोके बिना एक निर्देशिका की फ़ाइलों और उसके उप निर्देशिकाओं की गणना, और,: ओ) मैं एक समस्या है कि मुझे इस पृष्ठ पर ले लिया था,

+1

छोटे टाइपो के लिए धन्यवाद, होना चाहिए: // लंबे राशि = (फ़ाइलों में फ़ाइल से जाने fileinfo सभी फाइलों का आकार = नई FileInfo (फ़ाइल) fileInfo.Length चुनें) .Sum(); –

+1

और यदि आपके पास सर्च डायरेक्टरी के तहत एक प्रतिबंधित निर्देशिका है, तो यह असफल हो जाएगी! ढांचे के भविष्य के संस्करण में उस संकल्प को देखने के लिए: https://connect.microsoft.com/VisualStudio/feedback/details/512171/directory-enumeratedirectory-etc-unusable-due-to-frequent-unauthorizedaccessexceptions-even-runas- प्रशासक –

+0

आपकी टिप्पणियों के लिए धन्यवाद गेब्रियल। मैंने टाइपो को ठीक किया है और संभावित असफल चेतावनी शामिल की है। – flayn

3

सबसे पहले, मेरी गरीब अंग्रेज़ी माफ अनन्य ..., संपूर्ण क्वेरी के अंत से पहले पहला परिणाम प्राप्त करें।

यहाँ और वहाँ वेब पर पाया विभिन्न उदाहरणों की मदद से

, मैं अंत में इस विधि लिखें:

public static IEnumerable<FileInfo> EnumerateFiles_Recursive(this DirectoryInfo directory, string searchPattern, SearchOption searchOption, Func<DirectoryInfo, Exception, bool> handleExceptionAccess) 
{ 
    Queue<DirectoryInfo> subDirectories = new Queue<DirectoryInfo>(); 
    IEnumerable<FileSystemInfo> entries = null; 

    // Try to get an enumerator on fileSystemInfos of directory 
    try 
    { 
     entries = directory.EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly); 
    } 
    catch (Exception e) 
    { 
     // If there's a callback delegate and this delegate return true, we don't throw the exception 
     if (handleExceptionAccess == null || !handleExceptionAccess(directory, e)) 
      throw; 
     // If the exception wasn't throw, we make entries reference an empty collection 
     entries = EmptyFileSystemInfos; 
    } 

    // Yield return file entries of the directory and enqueue the subdirectories 
    foreach (FileSystemInfo entrie in entries) 
    { 
     if (entrie is FileInfo) 
      yield return (FileInfo)entrie; 
     else if (entrie is DirectoryInfo) 
      subDirectories.Enqueue((DirectoryInfo)entrie); 
    } 

    // If recursive search, we make recursive call on the method to yield return entries of the subdirectories. 
    if (searchOption == SearchOption.AllDirectories) 
    { 
     DirectoryInfo subDir = null; 
     while (subDirectories.Count > 0) 
     { 
      subDir = subDirectories.Dequeue(); 
      foreach (FileInfo file in subDir.EnumerateFiles_Recursive(searchPattern, searchOption, handleExceptionAccess)) 
      { 
       yield return file; 
      } 
     } 
    } 
    else 
     subDirectories.Clear(); 
} 

मैं एक पंक्ति और एक पुनरावर्ती विधि का उपयोग पारंपरिक क्रम (निर्देशिका और फिर सामग्री की सामग्री को रखने के लिए पहली उपनिर्देशिका और अपनी उपनिर्देशिकाओं और फिर दूसरी सामग्री की सामग्री ...)। "HandleExceptionAccess" पैरामीटर केवल एक फ़ंक्शन कॉल है जब किसी अपवाद को निर्देशिका के साथ फेंक दिया जाता है; फ़ंक्शन को यह इंगित करने के लिए सत्य वापस करना होगा कि अपवाद को अनदेखा किया जाना चाहिए।

इस methode के साथ

, आप लिख सकते हैं:

DirectoryInfo dir = new DirectoryInfo("c:\\temp"); 
long size = dir.EnumerateFiles_Recursive("*", SearchOption.AllDirectories, (d, ex) => true).Sum(f => f.Length); 

और यहाँ हम कर रहे हैं: सभी अपवाद है जब एक निर्देशिका की गणना करने में उपेक्षा हो जाएगा कोशिश कर रहा!

आशा इस मदद

लियोनेल

पुनश्च: एक कारण मैं व्याख्या नहीं कर सकते के लिए, मेरे विधि ढांचे 4 एक से अधिक तेज है ...

पी पी एस: यदि आप प्राप्त कर सकते हैं मेरे उन विधियों के स्रोत के साथ परीक्षण समाधान: यहां TestDirEnumerate। मैं EnumerateFiles_Recursive लिखता हूं, EnumerateFiles_NonRecursive (रिकर्सन से बचने के लिए कतार का उपयोग करें) और EnumerateFiles_NonRecursive_TraditionalOrder (रिकर्सन से बचने और पारंपरिक ऑर्डर रखने के लिए कतार के ढेर का उपयोग करें)। उन 3 विधियों को कोई दिलचस्पी नहीं है, मैं उन्हें केवल सर्वश्रेष्ठ परीक्षण के लिए लिखता हूं। मुझे लगता है कि केवल अंतिम ही रखना है। मैंने EnumerateFileSystemInfos और EnumerateDirectories के समकक्ष भी लिखा है।

+0

मैंने इस संस्करण में एक गलतफहमी की है क्योंकि मैं खोजपटल के साथ सूडैरेक्टरी खोजता हूं। तो यदि कोई उपनिर्देशिका खोजपटल के साथ मेल नहीं खाती है, तो मैं इसका पता नहीं लगाता ... [br] मैंने इसे सही करने के लिए नया संस्करण लिखा: लेकिन, मुझे निर्देशिका पर दो अनुरोध करना होगा: खोज के साथ एक, और खोज के बिना दूसरा ==> प्रदर्शन पहले की तरह उतना अच्छा नहीं है। –

+0

तो मैं खोज पैटर्न के बिना एक संस्करण जोड़ता हूं जो तेज़ हैं। यहां मेरे परीक्षण समाधान को देखें: [लिंक] (http://lionel.komsa.free.fr/temp/TestDirEnumerate2.zip) –

+0

शायद मुझे कुछ याद आ रहा है, लेकिन इस विधि के साथ आपको अभी भी अपूर्ण सूची मिल जाएगी, दाएं ? अगर मैं फ़ोल्डर्स ए और सी देखने के लिए अधिकृत हूं लेकिन बी नहीं, और 'एन्युमरेट' ए की जांच करता है, तो बी, फिर सी, यह बी के साथ रुक जाएगा और सी गिनने में विफल रहेगा।LINQ'ness के लिए –

30

.NET 4.0 में फ़ोल्डर आकार प्राप्त करने का एक बहुत ही संक्षिप्त तरीका नीचे है। यह अभी भी सभी फ़ाइलों को पुनरावर्ती रूप से पार करने की सीमा से पीड़ित है, लेकिन यह फ़ाइल नामों की संभावित विशाल सरणी लोड नहीं करता है और यह कोड की केवल दो पंक्तियां हैं।

private static long GetDirectorySize(string folderPath) 
    { 
     DirectoryInfo di = new DirectoryInfo(folderPath); 
     return di.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(fi => fi.Length); 
    } 
+0

+1! –

+4

मैं आपको * के बजाय * का उपयोग करने की सलाह देता हूं। * क्योंकि फ़ाइल नामों की आवश्यकता नहीं है। – Joe

+4

मैं आपके तर्क जो का पालन करता हूं, लेकिन मुझे लगता है कि यह अनावश्यक है क्योंकि विंडोज ओएस * से मेल खाता है। * फ़ाइल/फ़ोल्डर नामों के खिलाफ पैटर्न चाहे वे '।' या नहीं। मुझे लगता है कि इससे कोई फर्क नहीं पड़ता है, लेकिन मुझे यह जानने में दिलचस्पी होगी कि मैं गलत हूं या नहीं। बेशक, यदि यह मोनो एक अलग ओएस पर चल रहा था तो यह अलग-अलग हो सकता है। – Kev

-2

आपको इसे अपने आप को आसान बनाना चाहिए। एक विधि बनाएं और निर्देशिका के स्थान को पास करें।

private static long GetDirectorySize(string location) { 
     return new DirectoryInfo(location).GetFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length); 
    } 

जी

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

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