简体   繁体   中英

I need help at coding a program which goes through directories, shows the files and says how many and which extensions there are

I need to code a program that iterates through directories and prints the type of the extensions and how many of those are in this folder. For example:

There is a folder called "public". In this folder, there are 2 more folders called "2015" and "2017" and a ".txt"-file. In "2015" there are 2 pdf's, one txt and 3 docx.

I'm a total noob (as you will probably see soon) but I'm curious how to solve it with Dictionaries.

1st, I tried the following code, but the output and the code are not like they should be (so I'll probably scrap the code)

2nd, I should solve it with "Dictionary's", but I have never heard of them and I don't know what they are and how I use them, although I already tried to understand them. My teacher said we should work with Dictionary[extensions]; if the extension already exists, we should "Dictionary[extensions]++;" and if a new extension "appears", we should add it to another array.

Here is what I tried:

Main:

string path = @"C:\User\public"; 
readDir(path); 
Console.ReadKey();

Method "readDir":

public static void readDir(string currentDirectory) 
{ 
    string extension = " "; 
    string[] rootSub = Directory.GetDirectories(currentDirectory); 
    string[] files = Directory.GetFiles(currentDirectory); 
    int result = files.GetLength(0);
    Console.WriteLine(currentDirectory); 

    foreach (var item in files)
    {       
       extension = Path.GetExtension(item); 
       Console.WriteLine("{0} Files with Extension {1}", result, extension); 
    }

    Console.WriteLine(); 

    foreach(string dir in rootSub)  
    { 
        readDir(dir); 
    }
} 

I found a Linq-solution online (I just c/p it in my program to see if it works) and it kinda does, here is it:

https://stackoverflow.com/a/9456014/10858923

The output should look like this:

C:\\User\\public

1 Files with Extension .txt

C:\\User\\public\\2015

2 Files with Extension .pdf

1 Files with Extension .txt

3 Files with Extension .docx

... and so on, but my actual output looks like this:

C:...

1 Files with Extension .txt

C:...\\2015

6 Files with Extension .docx

6 Files with Extension .pdf

6 Files with Extension .docx

6 Files with Extension .pdf

6 Files with Extension .docx

6 Files with Extension .txt

You can get a list of all files inside a directory, including sub-directories, buy suing Directory.EnumerateFiles() .

var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories);

Then, iterate through them, and see if the dictionary already contains the said key.

Dictionary<string, int> ExtensionCount = new Dictionary<string, int>();

foreach (var file in files)
{
    var ext = Path.GetExtension(file);
    if (ExtensionCount.ContainsKey(ext))
    {
        ExtensionCount[ext]++;
    }
    else
    {
        ExtensionCount.Add(ext, 1);
    }
}

Or you can make this even more concise using LINQ

var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories);
var groups = files.GroupBy(x => Path.GetExtension(x));
Dictionary<string, int> ExtensionCount = new Dictionary<string, int>();
foreach(var group in groups)
{
    ExtensionCount.Add(group.Key, group.Count());
}

Regarding Dictionary:

Since you said you're not familiar with the Dictionary , here's a quick course, but you should read up on them more.

A dictionary is a data structure that can hold a bunch of 'KeyValuePair's. A KeyValuePair is essentially a set of two data items, the two data items can be of any types.

So, Dictionary<int, int> Is a list of a pair of int items. The first of the two is called the Key , and you can't have duplicate keys in a dictionary. The second of the two is called the Value , and it can be duplicated.

Therefore in the above example, the dictionary can contain values as follows. Note that the Key is unique but the Value can be repeated.

[1,4]

[6,3]

[3,4]

[7,4]

Now in our example here, we use a dictionary of type Dictionary<string, int> where the first of the two, string represents the file extension, and the second of the two, the int , represents the count of each file extension type. So when you run through the code, it will populate this dictionary and will look something like this, depending on what types of files you have:

[".txt", 4]

[".pdf", 1]

[".cs", 6]

[".log", 8]

Right now you're just using the number of all files in the directory. To get the number per extension one way is to use a dictionary with the extension as keys and count every occurrence of an extension while iterating over the files.

You may also want to set the extension to lower (or upper) case so that different cases don't result in different extensions.

It could look something like:

public static void readDir(string currentDirectory)
{
    string[] rootSub = Directory.GetDirectories(currentDirectory);
    string[] files = Directory.GetFiles(currentDirectory);

    Console.WriteLine(currentDirectory);

    Dictionary<string, int> extensions = new Dictionary<string, int>();
    foreach (var item in files)
    {
        string extension = Path.GetExtension(item).ToLower();
        if (!extensions.ContainsKey(extension))
        {
            extensions[extension] = 1;
        }
        else
        {
            extensions[extension]++;
        }
    }
    foreach (string key in extensions.Keys)
    {
        Console.WriteLine("{0} Files with Extension {1}", extensions[key], key);
    }

    Console.WriteLine();

    foreach (string dir in rootSub)
    {
        readDir(dir);
    }
}

Currently, you are getting a list of files in the current directory and then getting the number of files immediately after

string[] files = Directory.GetFiles(currentDirectory);
int result = files.GetLength(0);

At no point are you grouping the files together by extension or resetting this result so when you are looping through all the files, you will print out a line per file and use the result found at the beginning which will never change.

You probably want do use some of that linq you found previously to change up the method slightly.

public static void readDir(string currentDirectory) 
{ 
    string extension = " "; 
    string[] rootSub = Directory.GetDirectories(currentDirectory); 
    string[] files = Directory.GetFiles(currentDirectory); 

    // This will be an IEnumerable<IGrouping<string, string>> where they key is the extension and the "value" is every file for that extension
    IEnumerable<IGrouping<string, string>> filesGroupedByExtension = files.GroupBy(file => Path.GetExtension(file));

    foreach (IGrouping<string, string> groupedFiles in filesGroupedByExtension)
    {
        Console.WriteLine($"{groupedFiles.Count()} Files with Extension {groupedFiles.Key}"); 
    }

    Console.WriteLine(); 

    foreach(string dir in rootSub)  
    { 
        readDir(dir); 
    }
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM