to get the number of files recursively - c#

I'm trying to count the number of *.tmp files in the computer. When I click on a button the labelbox should start increasing the count number for each search of .tmp file. my below coding does not seems to be working.
Any help is much appreciated.
Also when I click on button to get the number of tmp files; the lable box should start showing the increase in count like 1,2,,,,,56,,89,,,etc rather than showing just the total number of files.
namespace finalclean {
public partial class FinalClean : Form {
public FinalClean() {
InitializeComponent();
}
int count = 0;
private void button1_Click(object sender, EventArgs e) {
String path = Environment.ExpandEnvironmentVariables(#"c:\windows");
try {
foreach (string dirPath in Directory.GetDirectories(path)) {
foreach (string filePath in Directory.GetFiles(dirPath)) {
string filename = Path.GetFileName(filePath);
if (filename.Equals("*.tmp")) {
count++;
}
}
}
}
catch (System.Exception excpt) {
//Console.WriteLine(excpt.Message);
}
textBox1.Text = (count.ToString());
}
}
}

You could just use:
var count = Directory.EnumerateFiles(#"C:\Windows\", "*.tmp",
SearchOption.AllDirectories).Count();

Your code doesn't work because you're not visiting all the directories, but only the fist one (C:\Windows).
If you make it recursive it can do the trick for you.
internal class Program
{
private static void Main(string[] args)
{
var myClass = new Visitor();
myClass.OnNewFileFound +=Progress;
myClass.CountTmpFiles();
Console.Read();
}
private static void Progress(int i)
{
Console.WriteLine(i); //update textbox here
}
}
public class Visitor
{
public event Action<int> OnNewFileFound;
private int count = 0;
public int CountTmpFiles()
{
var path = Environment.ExpandEnvironmentVariables(#"c:\windows");
VisitDir(path);
return count;
}
private void VisitDir(string path)
{
try
{
foreach (var directory in Directory.GetDirectories(path))
{
VisitDir(directory); //recursive call here
}
foreach (var filePath in Directory.GetFiles(path, "*.tmp", SearchOption.TopDirectoryOnly))
{
count++;
if (OnNewFileFound != null)
{
OnNewFileFound(count);
}
}
}
catch (System.Exception excpt)
{
//Console.WriteLine(excpt.Message);
}
}
}
And yes, if you're only counting files, then I doesn't make sense to write your own code. You just use Directory.EnumerateFiles as Andrew and Hamlet Hakobyan suggested.

Related

UI Not Loading When Using While In Foreach Loop

I am making a program which you can create and load in a flashcard pack using csv files. When a csv file is chosen it opens other UI with the question, answer and image for a flashcard and will keep on looping until all the flashcards in the pack are gone through using a foreach loop.
However the foreach loop would keep on looping without the user pressing the next button. To fix this I did:
while (Continue() == false) { } //this is at the end of the foreach loop
}
}
private bool Continue()
{
if (btn_NextFlashcard_WasClicked) return true;
Application.DoEvents();
Thread.Sleep(250);
Application.DoEvents();
return false;
}
private bool btn_NextFlashcard_WasClicked;
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
btn_NextFlashcard_WasClicked = true;
}
This fixed the problem of it looping again without the button for the next flashcard being pressed but now it doesn't even open the second UI for me to press the next flashcard button.
How would I fix this? Any help would be greatly appreciated.
Code for foreach loop:
public void ReadFlashcardPack(string file)
{
var records = engine.ReadFile(file);
foreach (var record in records)
{
Console.WriteLine("New foreach loop");
lblQuestion.Text = record.question;
lblAnswer.Text = record.answer;
lblAnswer.Visible = false;
btn_NextFlashcard_WasClicked = false;
//check if there is an image
if (record.image == "FALSE")
{
Image.Hide();
}
else
{
Image.Show();
Image.Image = Properties.Resources.test_image;
}
while (Continue() == false) { }
}
}
The records also come from a class: [DelimitedRecord(",")]
public class FlashcardPack
{
public string question;
public string answer;
public string image;
}
And then a new instance of FileHelpers engine is made private FileHelperEngine<FlashcardPack> engine = new FileHelperEngine<FlashcardPack>(); to read the csv file and every time the foreach loop loops record.question, record.answer and record.image changes depending on what line the loop is on.
One idea that comes to mind is to store the list of records outside of the method, keep track of the next record that should be read, and modify the method to just read the next record.
Then, in your click event, you can just call the method again until all records have been read.
private string filePath = #"f:\private\temp\temp.csv"; // Use your file path here
private List<FlashcardPack> records;
private int nextRecord;
public void ReadNextRecord()
{
if (records == null)
{
records = engine.ReadFile(filePath).ToList();
nextRecord = 0;
}
else if (nextRecord >= records.Count)
{
// Do something when all records have been read
nextRecord = 0;
}
// Get next record and increment our variable
var record = records[nextRecord++];
lblQuestion.Text = record.question;
lblAnswer.Text = record.answer;
lblAnswer.Visible = false;
btn_NextFlashcard_WasClicked = false;
//check if there is an image
if (record.image == "FALSE")
{
Image.Hide();
}
else
{
Image.Show();
Image.Image = Properties.Resources.test_image;
}
}
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
ReadNextRecord();
}
Here's a working sample that uses the concept above which might help you get your code working, since I can't see your whole project:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<Flashcard> flashcards;
private int nextRecord;
// Use a valid path on your system here (the file doesn't need to exist)
private const string FilePath = #"f:\public\temp\temp.csv";
private void LoadFlashcards()
{
flashcards = Engine.ReadFile(FilePath);
nextRecord = 0;
}
public void DisplayNextFlashcard()
{
if (flashcards == null)
{
LoadFlashcards();
}
else if (nextRecord >= flashcards.Count)
{
// Do something when all records have been read
nextRecord = 0;
}
var flashcard = flashcards[nextRecord++];
lblQuestion.Text = flashcard.Question;
lblAnswer.Visible = false;
lblAnswer.Text = flashcard.Answer;
Image.Visible = flashcard.Image;
Image.Image = Properties.Resources.FlashcardImage;
}
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
DisplayNextFlashcard();
}
}
class Flashcard
{
public string Question { get; set; }
public string Answer { get; set; }
public bool Image { get; set; }
public static Flashcard Parse(string csvLine)
{
if (csvLine == null) throw new ArgumentNullException(nameof(csvLine));
var parts = csvLine.Split(',').Select(item => item.Trim()).ToList();
if (parts.Count != 3) throw new FormatException(
"csvLine does not contain 3 comma-separated items.");
return new Flashcard
{
Question = parts[0],
Answer = parts[1],
Image = !parts[2].Equals("FALSE", StringComparison.OrdinalIgnoreCase)
};
}
}
class Engine
{
public static List<Flashcard> ReadFile(string filePath)
{
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
if (!File.Exists(filePath)) CreateFile(filePath);
return File.ReadAllLines(filePath).Select(Flashcard.Parse).ToList();
}
private static void CreateFile(string filePath)
{
File.CreateText(filePath).Close();
File.WriteAllText(filePath,
"What is more useful when it is broken?, An egg, TRUE\n" +
"What belongs to you but other people use it more?, Your name, FALSE\n" +
"I have three eyes all in a row. When the red one opens " +
"no one can go. What am I?, A traffic light, TRUE");
}
}

How to make a list `global` in c#?

Firstly, most of my experience with coding is through python hence my use of global
I have a list and I want to be able to search the list and find all words that are of x length. My main issue is not knowing how to call a function from inside an event listener.
So myList is generated inside of my function functionOne, I am then wanting to use this list inside functionTwo and then finally I want to call it when buttonOne is clicked. E.g buttonOne_Click ....
This is what I have so far for functionOne
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
List<string> remove = convertLower.Distinct().ToList();
return remove;
}
functionTwo
public List<string> length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach(string item in myList)
{
if(item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
And finally my event listener
private void button_Click(object sender, EventArgs e)
{
length(remove);
}
NOTE: remove is the list I am trying to work with
But there is no output with this code because I get an error saying remove doesn't exist in this context, I'm unsure how I make this list global
Put all the functions in the same class and use noDup on your list instance.
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
List<string> remove = convertLower.Distinct().ToList();
return remove;
}
public void length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach(string item in myList)
{
if(item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
private void button_Click(object sender, EventArgs e)
{
var remove = noDup(yourInputList);
length(remove);
}
We'll here's the general idea how to achieve this in a win forms c# application.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private List<string> _remove;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
length(_remove);
}
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
_remove = convertLower.Distinct().ToList();
}
public List<string> length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach (string item in myList)
{
if (item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
}
}
Mind this doesn't build since I just used your code. For example the length method should return a List<string> but it doesn't. You would probably want to change the list that's passed in and then return it, or mutate the class level variable _remove.
Either way the event handler button1_Click needs to work with a class level variable (such as _remove that I added) or call a method that will return the list (as is present in the other anwser by Zbigniew.)

Best way to pass data to a DataGridView form from another non-form class

As the title says, I need to pass a list of hashtables from a regular class to a form class to be rendered in a DataGridView. What I've got so far is this:
namespace somenamespace
{
class aldeloUpdater
{
private static string client = "chanchitos";
private static string establishment = "c1";
static void Main()
{
try
{
var guiForm = new GuiForm(); // Instantiating the Form-derived class.
string deliveriesListResp = getOrders();
Processing...
foreach (...)
{
if ((bool)DBresponse["status"])
{
guiForm.dataGridViewProducts = (List<Hashtable>)DBresponse["deliveriesSaved"]; // Passing the data to the DataGridView.
foreach (Hashtable delivery in (List<Hashtable>)DBresponse["deliveriesSaved"])
{
string updateDeliveryResponse = updatePedidoInDomicilios(delivery["domiciliosOrderId"].ToString(), 2, DBresponse["errmsg"].ToString());
}
}
else
{
Processing...
}
}
guiForm.ShowDialog(); // Showing the form.
More processing...
}
catch (Exception e)
{
Console.WriteLine("Exception details: " + e.ToString());
Console.ReadLine();
}
}
More methods...
}
Now the Form class looks like this:
namespace somenamespace
{
public partial class GuiForm : Form
{
public List<Hashtable> dataGridViewProducts; // Variable used to store the data to be rendered by the DataGridView.
public GuiForm()
{
InitializeComponent();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void GuiForm_Load(object sender, EventArgs e)
{
int index = 0;
foreach (Hashtable product in dataGridViewProducts)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = product["productName"];
dataGridView1.Rows[index].Cells[1].Value = product["userName"];
dataGridView1.Rows[index].Cells[2].Value = product["dateAndTime"];
dataGridView1.Rows[index].Cells[3].Value = product["domiciliosOrderId"];
index++;
}
}
Some more methods.
}
}
For now this code works just fine and the data is shown in the DataGridView, nonetheless I feel like there must be a better way to achieve this goal, it's just that I'm new to C#. I will appreciate suggestions and even more a code sketch of how you would do this in a better way.
Thanks.

How to know when all my Producer - Consumer jobs have finished

I have Winforms application that read several network folders and search for files inside this folders, this function receive List<stirng> folders:
private decimal _numberOfFiles;
private static List<string> _folders;
public delegate void OnFileAddDelegate(List<string> files);
public event OnFileAddDelegate OnFileAddEventHandler;
public delegate void OnFinishSearchDelegate();
public event OnFinishSearchDelegate OnFinishSearchEventHandler;
public void SearchFiles()
{
foreach (string folder in _folders)
{
if (Directory.Exists(folder))
{
var files = Directory.EnumerateFiles(folder, "*.doc", SearchOption.TopDirectoryOnly)
.OrderByDescending(x => new FileInfo(x).CreationTime).Take((int)_numberOfFiles).ToList<string>();
if (OnFileAddEventHandler != null)
OnFileAddEventHandler(files);
}
}
if (OnFinishSearchEventHandler != null)
OnFinishSearchEventHandler();
}
After OnFileAddEventHandler(files) event is fired my ProducerConsumer class start to check this List of files that found and do the work (if the file is OK fired up event to my main UI to add this files into my ListView):
public class ProducerConsumer
{
public delegate void OnFileAddDelegate(PcapFileDetails pcapFileDetails);
public event OnFileAddDelegate OnFileAddEventHandler;
public delegate void AllFilesProcessedDelegate();
public event AllFilesProcessedDelegate AllFilesProcessedEventHandler;
private readonly Queue<string> _queue;
private int counter;
public ProducerConsumer(int workerCount, IEnumerable<string> list)
{
_isSearchFinished = true;
_queue = new Queue<string>(list); // fill the queue
counter = _queue.Count; // set up counter
for (int i = 0; i < workerCount; i++)
Task.Factory.StartNew(Consumer);
}
private void Consumer()
{
FileChecker fileChecker = new FileChecker();
for (; ; )
{
string file;
lock (_queue)
{
// synchronize on the queue
if (_queue.Count == 0) return; // we are done
file = _queue.Dequeue(); // get file name to process
} // release the lock to allow other consumers to access the queue
// do the job
string result = fileChecker.Check(file); // Check my file
if (OnFileAddEventHandler != null && result ) // In case my file OK, fired up event to my main UI
OnFileAddEventHandler(file);
// decrement the counter
if (Interlocked.Decrement(ref counter) != 0)
continue; // not the last
// all done - we were the last
if (AllFilesProcessedEventHandler != null)
AllFilesProcessedEventHandler();
return;
}
}
}
Now while this search is in process my UI is locked to prevent unnecessary clicks and i want to know when all my folders finish to search to unlock.
But my problem is because i am search several folders the event AllFilesProcessedEventHandler() fired up several times and i want to know when all my searches finished.
Here is a recursive sample with QuickIO.Net
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using SchwabenCode.QuickIO;
namespace ConsoleApplication3
{
internal class Program
{
private static readonly BlockingCollection<QuickIOFileInfo> fileInfos = new BlockingCollection<QuickIOFileInfo>();
private static void Main(string[] args)
{
var task = Task.Factory.StartNew(() =>
{
Int32 totalSize = 0;
Parallel.ForEach(fileInfos.GetConsumingEnumerable(), fi =>
{
Interlocked.Add(ref totalSize, (int)fi.Bytes);
});
Console.WriteLine("All docs bytes amount to {0}", totalSize);
});
ProcessDirectory("C:\\");
fileInfos.CompleteAdding();
Task.WaitAll(task);
}
private static void ProcessDirectory(string path)
{
Parallel.ForEach(QuickIODirectory.EnumerateDirectories(path), dir =>
{
try
{
Parallel.ForEach(QuickIODirectory.EnumerateFiles(dir), file =>
{
if (file.AsFileInfo().Extension.Equals(".docx"))
fileInfos.Add(file);
});
ProcessDirectory(dir.FullName);
}
catch (Exception e)
{
Console.WriteLine("Unable to access directory {0}", dir.FullName);
}
});
}
}
}
Blocking collection will automatically signal to Parallel ForEach when all elements have been added, by calling CompleteAdding().
To scan a 256GB SSD, with 74GB left and total of 738k+ files took 16.8s.

Extension method must be defined in a non-generic static class

I'm getting the above error. I saw other similar posts on this error but I don't seem to find where the problem is. I changed my class type to static and the error resists. This is the entire code to my main form class:
I Edited my class. This is how it looks like now and the error has changed to:Missing partial modifier on declaration of type 'PhoneFind.frmMain'; another partial declaration of this type exists.
namespace PhoneFind
{
public partial class frmMain : Form
{
// the path to the temporary file to store the webresponse
String path = "c:\\Temp\\webresponse.txt";
public frmMain()
{
InitializeComponent();
comboSelectSearchEngine.SelectedIndex = 0;
ofdPhones.Filter = "txt files (*.txt)|*.txt";
listbxMessages.Items.Clear();
addItemToListBox(listbxMessages, "Welcome to ActionBase Phone Find!");
addItemToListBox(listbxMessages, "Select the file containing the numbers.");
radioNumbers.Checked = true;
}
private void frmMain_Load(object sender, EventArgs e)
{
}
private void btnLoadFile_Click(object sender, EventArgs e)
{
if (ofdPhones.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtFile.Text = ofdPhones.FileName;
// Read the file line by line and add the numbers to the numbers listbox.
listbxNumbers.Items.Clear();
String line;
int numbersCounter = 0;
System.IO.StreamReader file = new System.IO.StreamReader(ofdPhones.FileName);
while ((line = file.ReadLine()) != null)
{
listbxNumbers.Items.Add(line.Trim());
numbersCounter++;
}
addItemToListBox(listbxMessages, ofdPhones.FileName + " loaded.");
addItemToListBox(listbxMessages, numbersCounter + " records found in the file.");
}
}
// add item to the listbox and move scroll to the end of the listbox for the latest messages to be visibile to the viewer
private void addItemToListBox(ListBox listbox, String item)
{
listbox.Items.Add(item);
listbox.SelectedIndex = (listbox.Items.Count - 1);
}
private void radioNumbers_CheckedChanged(object sender, EventArgs e)
{
if (!radioNumbers.Checked)
{
grpbxNumbers.Text = "Names and Addresses";
}
else
{
grpbxNumbers.Text = "Numbers";
}
}
private void btnRun_Click(object sender, EventArgs e)
{
if (listbxNumbers.Items.Count == 0)
{
MessageBox.Show("No records have been loaded." + "\n" + "Use the browse button to load records.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (!CheckForInternetConnection())
{
MessageBox.Show("No internet connection.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
String response;
switch (comboSelectSearchEngine.SelectedIndex)
{
case 0: // Hitta.se
foreach (String item in listbxNumbers.Items)
{
WebRequestObj request = new WebRequestObj(item, "hitta");
response = request.sendRequest();
if (response.Equals("Error"))
{
addItemToListBox(listbxMessages, "Error sending '" + item + "' to the server.");
}
else
{
//create a temporary file to work on the response
StreamWriter sw;
if (!File.Exists(path)) {
sw = File.CreateText(path);
}
try
{
File.WriteAllText(path, String.Empty); // clear the content of the file
sw = File.AppendText(path);
sw.WriteLine(response);
sw.Flush();
sw.Close();
String s = findResultType(path);
MessageBox.Show(s);
}
catch (IOException ioe)
{
MessageBox.Show(ioe.Message,"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
break;
}
}
}
public bool CheckForInternetConnection()
{
try
{
using (var client = new System.Net.WebClient())
using (var stream = client.OpenRead("http://www.google.com"))
{
return true;
}
}
catch
{
return false;
}
}
/*
* findResultType
* gets the web response and finds out if the matching result of the search termis one of the following:
* 1. one person (oneperson)
* 2. one company (onecompany)
* 3. more than one person, no company (manypersonnocompany)
* 4. no person, more than one company (nopersonmanycompany)
* 5. more than one person, more than one company (manypersonmanycompany)
* 6. no person, no company (nopersonnocompany)
*/
public String findResultType(String reponsepath)
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(reponsepath);
List<String> itemList = new List<String>();
IEnumerable<String> v = null;
var item = doc.DocumentNode.SelectNodes("//body[#id='person']");
if (item != null)
{
v = item.Select(p => p.InnerText);
itemList = v.ToList();
if (itemList.Count == 1)
return "oneperson";
}
else
{
item = doc.DocumentNode.SelectNodes("//body[#id='company']");
if (item != null)
{
v = item.Select(p => p.InnerText);
itemList = v.ToList();
if (itemList.Count == 1)
return "onecompany";
}
}
//for (int i = 0; i < itemList.Count; i++)
//{
// MessageBox.Show(itemList[i]);
// //console.writeline(itemlist[i]);
//}
//console.writeline(itemlist.count + " results found.");
return "";
}
}
}
This is your first problem:
public static class frmMain : Form
You can't derive a static class from another class. A static class always implicitly derives from Object. You also can't have non-static members in static classes.
So basically, you can't put your extension method in your frmMain class (which should be renamed to follow .NET naming conventions and to be somewhat more descriptive at the same time). Why did you want to put the extension method in that class anyway?
I can't even see an extension method in the code you've posted - did you remove it? Is it in some other class you haven't posted?
Fundamentally, I think you need to take a step back. It sounds like you've reacted to the compiler error message without really understanding it fully. Read up on extension methods, read up on what static classes are, until you really understand why you don't want your form class to be static, and why you do want to make the class that contains your extension method static.
A static class cannot have public constructors. Moreover, static forms are pointless, as you need an instance of them to show.
If you have an extension method (I don't see any...), you have to move it into a separate static class which you cannot create instances of:
static class MyExtensions
{
public static void Extend(this Object o) {}
}
You should always put your extension methods in a separate static class.
You can't fix the problem by simply marking a class as static. That changes the entire meaning of the class. Instead, create a new class for just extension methods.
For example:
public static class Extensions
{
public void SomeExtension(this object arg)
{
...
}
}

Categories

Resources