I've been working on a "File Explorer" project for a while now as a learning project and to have some fun with trying new ways to code. It's been going quite well so far and I'm very pleased with what I've managed to figure out. Where I'm hitting a bit of a roadblock is with speed. In windows explorer, if you go into a new directory it will (depending of course on version and other variables) only take a few moments to list all the files and subdirectories. My application on the other hand, is still decently quick, but will very noticeably slow down the more items there are in the directory.
I have this function which I call in my "Navigate" function. Which I believe is where I will likely find the culprit and solution:
private void GetDirectoryContent(string directory)
{
txtPath.Text = directory;
currentDirectoryFiles.Clear();
filesList.Items.Clear();
int longestName = 0;
int longestType = 0;
foreach (string item in Directory.GetDirectories(directory))
{
int nameLength = item.Substring(item.LastIndexOf('\\') 1).Length;
if (nameLength > longestName) longestName = nameLength;
if ("Folder".Length > longestType) longestType = "Folder".Length;
}
foreach (string item in Directory.GetFiles(directory))
{
int nameLength = item.Substring(item.LastIndexOf('\\') 1).Length;
if (nameLength > longestName) longestName = nameLength;
if (GetFileType(item).Length > longestType) longestType = GetFileType(item).Length;
}
filesList.Sorting = SortOrder.Ascending;
filesList.View = View.Details;
filesList.Columns.Clear();
filesList.Columns.Add("Name", longestName * 8);
filesList.Columns.Add("Date Modified", 160);
filesList.Columns.Add("Type", longestType * 8);
foreach (string item in Directory.GetDirectories(directory))
{
string name = item.Substring(item.LastIndexOf('\\') 1);
smallImageList.Images.Add(new Bitmap(Environment.CurrentDirectory "\\Xplorer.ico"));
ListViewItem row = new ListViewItem(name, smallImageList.Images.Count - 1); // Name
row.SubItems.Add(Directory.GetLastWriteTime(item).ToString(CultureInfo.CurrentCulture)); // Date Modified
row.SubItems.Add("Folder"); // Type
row.Tag = "Folder";
currentDirectoryFiles.Add(item);
filesList.Items.Add(row);
}
foreach (string item in Directory.GetFiles(directory))
{
string name = item.Substring(item.LastIndexOf('\\') 1);
smallImageList.Images.Add(Icon.ExtractAssociatedIcon(item) ?? throw new InvalidOperationException());
ListViewItem row = new ListViewItem(name, smallImageList.Images.Count - 1); // Name
row.SubItems.Add(File.GetLastWriteTime(item).ToString(CultureInfo.CurrentCulture)); // Date Modified
row.SubItems.Add(GetFileType(item)); // Type
row.Tag = "File";
currentDirectoryFiles.Add(item);
filesList.Items.Add(row);
}
}
I'm still a newbie programmer so I know a lot of this code could probably be condensed, but I don't actually know how so that's what my main question is. How can I condense/optimize this function to speed up the results (and just to follow better practices for later projects.)
Please let me know if I left any details out you might need, as I said I'm still fairly new and don't know a ton about what might be helpful to know. Thanks in advance!
CodePudding user response:
Seems to be a good choice for a learning project :) Maybe use DirectoryInfo instead of searching with the strings. It would make it a easier for you and it's probably a little bit faster
private void GetDirectoryContent(DirectoryInfo directory)
{
//you could also leave it as string and write var dir = new DirectoryInfo(directory);
/*...*/
foreach (DirectoryInfo item in directory.GetDirectories())
{
string name = item.Name; //.FullName would include the path
smallImageList.Images.Add(new Bitmap(Environment.CurrentDirectory "\\Xplorer.ico"));
ListViewItem row = new ListViewItem(name, smallImageList.Images.Count - 1);
row.SubItems.Add(item.LastWriteTime.ToString(CultureInfo.CurrentCulture))
row.SubItems.Add("Folder"); // Type
row.Tag = "Folder";
currentDirectoryFiles.Add(item);
filesList.Items.Add(row);
}
foreach (FileInfo item in directory.GetFiles())
{
/* also knows its name, extension, last write time, ...*/
}
/*...*/
}
If you get a little farther and feel comfortable maybe also try a bit of new stuff. I think usefull stuff for your learning project would be things like IEnumerables or recursion (it's really useful for treelike structures like the filesystem)
CodePudding user response:
Thanks for the help everyone! This is a new function, it works very quickly!
private void GetDirectoryContent(string directory)
{
txtPath.Text = directory;
currentDirectoryFiles.Clear();
filesList.Items.Clear();
string[] files = Directory.EnumerateFiles(directory).ToArray();
string[] directories = Directory.EnumerateDirectories(directory).ToArray();
filesList.Sorting = SortOrder.Ascending;
filesList.View = View.Details;
filesList.Columns.Clear();
filesList.Columns.Add("Name", 250);
filesList.Columns.Add("Date Modified", 160);
filesList.Columns.Add("Type", 125);
foreach (string item in directories)
{
string name = item.Substring(item.LastIndexOf('\\') 1);
smallImageList.Images.Add(new Bitmap(Environment.CurrentDirectory "\\Xplorer.ico"));
ListViewItem row = new ListViewItem(name, smallImageList.Images.Count - 1); // Name
row.SubItems.Add(Directory.GetLastWriteTime(item).ToString(CultureInfo.CurrentCulture)); // Date Modified
row.SubItems.Add("Folder"); // Type
row.Tag = "Folder";
currentDirectoryFiles.Add(item);
filesList.Items.Add(row);
}
foreach (string item in files)
{
string name = item.Substring(item.LastIndexOf('\\') 1);
smallImageList.Images.Add(Icon.ExtractAssociatedIcon(item) ?? throw new InvalidOperationException());
ListViewItem row = new ListViewItem(name, smallImageList.Images.Count - 1); // Name
row.SubItems.Add(File.GetLastWriteTime(item).ToString(CultureInfo.CurrentCulture)); // Date Modified
row.SubItems.Add(GetFileType(item)); // Type
row.Tag = "File";
currentDirectoryFiles.Add(item);
filesList.Items.Add(row);
}
}