1

I'm new to C# I'm trying to display search result from textbox to a listview on button_click.

Here is my code:

private void button1_Click(object sender, EventArgs e)
{
    listView1.Items.Clear();
    listView1.Refresh();
    string[] filePaths = Directory.GetFiles(@textBox1.Text, "*.zip");
    string txtSearch = textBox2.Text;

    foreach (var filePath in filePaths)
    {
        using (ZipArchive archive = ZipFile.OpenRead(filePath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                var position = entry.Name.IndexOf(
                    txtSearch,                                             
                    StringComparison.InvariantCultureIgnoreCase);

                if (position > -1)
                {
                    listView1.Items.Add(entry.Name);
                }
                else
                {
                    MessageBox.Show(
                        "FILE NOT FOUND", 
                        "ERROR", 
                        MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
                }
            }
        }
    }
}'

This code works if its a single folder contain other archives but with this folder structure: folderA(contains): FolderA1, FolderA2. FloderA1(contains): , FolderA1.1, FolderA1.2, FolderA1.3 and FolderA1.4 FloderA1.1 to 1.4(each contains): , Folder and lot of archives(.zip and .rar) FloderA2(contains): FolderA2.1, FolderA2.2 and FolderA2.3. FloderA2.1 to 2.3(each contains): lot of archives(.zip and .rar)

how do i use this code to search for files with particular extension to list even when any of the folders=filepath.

thanks in advance.

davmos
  • 9,324
  • 4
  • 40
  • 43

3 Answers3

0

Look, I took you 4 clicks because there're 4 times of "File not found" occurred, and it show a Messagebox for each time. I think you should change a bit in your code:

foreach (var filePath in filePaths)
    {
        int count=0;
        using (ZipArchive archive = ZipFile.OpenRead(filePath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                var position = entry.Name.IndexOf(txtSearch, StringComparison.InvariantCultureIgnoreCase);
                if (position > -1)
                {
                    listView1.Items.Add(entry.Name);
                    count++;
                }

            }
            if(count==0)
            {
                 MessageBox.Show("FILE "+filepath+ "NOT FOUND", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }

Update

To get all the files in a folder and its subfolders, read this and this and this and this.

Community
  • 1
  • 1
FlySoFast
  • 1,854
  • 6
  • 26
  • 47
  • I get invaliddataexception was handled error: Number of entries expected in End Of Central Directory does not correspond – Otun Musa Bashir Jun 03 '15 at 12:04
  • well, the above code shouldn't have anything to do with the original logic. It just simply adds a "count" variable for every loop in filePaths array. Did your old code has the same problem by now? – FlySoFast Jun 03 '15 at 12:31
0

The reason you are getting told 4 times, is presumably because there are 4 items in the Zip file you are loading that do not match the txtSearch criteria. Since you have the message box in the inner foreach loop, each time a file is not found within the ZipArchiveEntry, the message box will be displayed.

You could move the message box to the outer loop, so that it is displayed only once per .zip file. While you're at it, you can use a Lambda to simplify the code, removing the need for a secondary foreach loop. The Where clause will filter out the ZipArchive.Entries collection, and then transform the result set to a collection of strings by .Select'ing the Name property of each item in the collection.

private void button1_Click(object sender, EventArgs e)
{
    listView1.Items.Clear();
    listView1.Refresh();
    string[] filePaths = Directory.GetFiles(@textBox1.Text, "*.zip");
    string txtSearch = textBox2.Text;
    var foundEntries = new List<string>();

    foreach (var filePath in filePaths)
    {
        using (ZipArchive archive = ZipFile.OpenRead(filePath))
        {
            foundEntries = archive.Entries
                .Where(e => e.Name.IndexOf(txtSearch, StringComparison.InvariantCultureIgnoreCase) >= 0)
                .Select(e => e.Name);
            if (foundEntries.Any())
            {
                listView1.Items.AddRange(foundEntries);
            }
            else
            {
                MessageBox.Show("FILE NOT FOUND", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        foundEntries.Clear();
    }
}
Johnathon Sullinger
  • 7,097
  • 5
  • 37
  • 102
  • 3 errors from this: Error 1 A local variable named 'e' cannot be declared in this scope because it would give a different meaning to 'e', which is already used in a 'parent or current' scope to denote something else. Error 2 The best overloaded method match for 'System.Windows.Forms.ListView.ListViewItemCollection.AddRange(System.Windows.Forms.ListView.ListViewItemCollection)' has some invalid arguments Error 3 Argument 1: cannot convert from 'System.Collections.Generic.List' to 'System.Windows.Forms.ListView.ListViewItemCollection' – Otun Musa Bashir Jun 03 '15 at 12:11
  • That's because you are using a ListViewCollection. You should be more clear in your question as to what Types you are using. Your question says you are using a `ListView`, which does have an AddRange. You will need to do `AddRange` on the collection used as your `ListCollectionView` source. Then refresh your `ListCollectionView`. As for the first error, that's odd. You should be able to nest the same variable name in each Linq lambda. The easy fix for this is just rename the variable. – Johnathon Sullinger Jun 03 '15 at 18:03
0

That MessageBox will be shown for each archive inside each zip file if the name does not contains the specified string. I guess you would prefer to show the message just one time, in case none of the zip files contains any file with a name containing the specified string.

private void button1_Click(object sender, EventArgs e)
{
    listView1.Items.Clear();
    listView1.Refresh();
    string[] filePaths = Directory.GetFiles(@textBox1.Text, "*.zip");
    string txtSearch = textBox2.Text;

    bool found = false;
    foreach (var filePath in filePaths)
    {
        using (ZipArchive archive = ZipFile.OpenRead(filePath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                var position = entry.Name.IndexOf(txtSearch, StringComparison.InvariantCultureIgnoreCase);
                if (position > -1)
                {
                    found = true;
                    listView1.Items.Add(entry.Name);
                    break;      // Comment out this line if you want more results from a single zip file
                }
            }
        }
    }
    if (!found)
    {
        MessageBox.Show("File not found", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
Blas Soriano
  • 566
  • 3
  • 16
  • thank you for your response. This solution makes it freeze without any error massage displayed. the folder I'm trying to iterate is of the nature: – Otun Musa Bashir Jun 03 '15 at 12:25