Get file extensions to populate into a ComboBox in C# - c#

So I have a folder with some imagens in many extensions like .ico, .png, .jpg, etc. and I've populated it into a comboBox using this code:
string caminho = #"C:\Users\User1\Desktop\Test\";
DirectoryInfo dir = new DirectoryInfo(caminho);
FileInfo[] fi = dir.GetFiles();
foreach (var ficheiro in fi)
{
string caminhoF = caminho + ficheiro.ToString();
string extension = Path.GetExtension(caminhoF);
comboBox1.Items.Add(extension);
}
The code is getting all the existing extensions in this path and put it on the comboBox, but it displays like this:
.ico
.ico
.ico
.png
.png
.jpg
.jpg
and I want to simply display each one of the existing extensions like grouping them.
Could you help me with that?

You can get the file extension from the FileInfo. You can also use Linq Distinct() to get unique extensions.
string caminho = #"C:\Users\User1\Desktop\Test\";
DirectoryInfo dir = new DirectoryInfo(caminho);
var extensions = dir.GetFiles().Select(fi => fi.Extension).Distinct();
foreach (var extension in extensions) {
comboBox1.Items.Add(extension);
}

Ok, I was to find a solution for it. Here it is the code:
string caminho = #"C:\Users\User1\Desktop\Test\";
DirectoryInfo dir = new DirectoryInfo(caminho);
FileInfo[] fi = dir.GetFiles();
foreach (var ficheiro in fi)
{
string caminhoF = caminho + ficheiro.ToString();
string extension = Path.GetExtension(caminhoF);
if (!comboBox1.Items.Contains(extension))
{
comboBox1.Items.Add(extension);
}
}

LINQ-to-Objects makes this easy. LINQ is similar to SQL but allows chaining transformations.
var comboBox1 = new ComboBox();
var caminho = #"C:\Users\User1\Desktop\Test\";
var dir = new DirectoryInfo(caminho);
var extensions = dir.GetFiles()
.Select(fi => fi.Extension)
.OrderBy(ext => ext, StringComparer.CurrentCulture)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.ToArray();
comboBox1.Items.AddRange(extensions);

Here are the rough steps:
Scan your folder to find out what files it contains.
Extract the file extension from each file you find.
Using a data structure that stores only unique entries, add extensions that you find to be new to the structure.
Iterate over the data structure to populate your combobox.
The part that you need is to find a data structure that helps you store unique values.
HashSet<T> has your back here: it allows quick lookups to determine set membership ("does the set already contain some element x?").
string caminho = #"C:\Users\User1\Desktop\Test\";
DirectoryInfo dir = new DirectoryInfo(caminho);
FileInfo[] fi = dir.GetFiles();
HashSet<string> extensions = new HashSet<string>;
foreach (var ficheiro in fi)
{
string caminhoF = caminho + ficheiro.ToString();
string extension = Path.GetExtension(caminhoF);
// If the set does not contain this extension, it'll be added and
// `Add()` will return true. Otherwise, it will do nothing and `Add()`
// will return false.
extensions.Add( extension );
}
foreach( var extension in extensions ) {
comboBox1.Items.Add(extension);
}

Related

Searching with System.IO.Directory.GetFiles and wildcards in path

I have a curious problem in a C#-program.
I have some local folderpaths like
"C:\test\AB_Systems\ELEGANCE\CB-DOC\live\M7-091.249.99.XX.01\extobjects".
Now i want to search for PDF-files in the subfolder called "extobjects".
Unfortunately there are many subfolders in the folder "live", which got a subfolder called "extobjects", so i thought it would be better to use a wildcard in the searchpath like that:
"C:\test\AB_Systems\ELEGANCE\CB-DOC\live\*\extobjects"
But this doesn't work.
Is there a way do do this?
public static FileInfo[] findFile(String whereToSearch, String searchFor , String mode)
{
IEnumerable<FileInfo> files = null;
if (mode.Equals(""))
mode = "s";
if (searchFor.Equals(""))
searchFor = "*";
if (mode.Equals("r") || mode.Equals("recursive"))
{
DirectoryInfo dir = new DirectoryInfo(whereToSearch);
files = dir.EnumerateFiles(searchFor, searchOption: SearchOption.AllDirectories);
}
if (mode.Equals("s") || mode.Equals("specific"))
{
DirectoryInfo dir = new DirectoryInfo(whereToSearch);
files = dir.EnumerateFiles(searchFor, searchOption: SearchOption.TopDirectoryOnly);
}
if (files != null) return files.ToArray<FileInfo>();
else return null;
}
That's an example how to do it.
It's important to say that only the filename can contain a wildcard pattern like *. The Path can be given as where to start the search and by giving searchOption: searchOption.AllDirectories as an argument it will go through all sub-directories of the entry path.
You will receive an Array of FileInfo which objects that contain the the path and more information.
You can use Linq like this:
var files = Directory
.EnumerateDirectories(#"C:\test\AB_Systems\ELEGANCE\CB-DOC\live", "extobjects", SearchOption.AllDirectories)
.SelectMany(x => Directory.EnumerateFiles(x, "*pdf", SearchOption.TopDirectoryOnly))
.ToArray();
I'd choose a solution exactly what BugFinder proposed, you could optimize the following foreach-loop into a LINQ query if your .NET target supports it.
// Itterate subdirectories of the live folder
foreach (var subDir in Directory.GetDirectories(#"C:\test\AB_Systems\ELEGANCE\CB-DOC\live"))
{
// Check if path to extobjects exists
var extObjects = Path.Combine(subDir, "extobjects");
if (Directory.Exists(extObjects))
{
var pdfFiles = Directory.GetFiles(extObjects, "*").Where(x=>x.EndsWith(".pdf"));
// Do something with the pdf file paths
}
}

how to convert FileInfo object to string

i am picking txt files from a folder in that i am ordering those file according to their respective modify date after ordering these files i've to read contents of each one by one. what will be the possible solution for this. cause i am not able convert FileInfo object to string following is the snippet.
in output : i want all files sorted according to modified date and want to read it one by one.
thanks
string sourcePath = #"C:\sample\*.log";
DirectoryInfo dir = new DirectoryInfo(sourcePath);
FileInfo[] files = dir.GetFiles(sourcePath).OrderBy(order => order.LastWriteTime).ToArray();
foreach (var item in files)
{
listBox1.items.Add(item)
}
Use File.ReadAllText and FileInfo.FullName property to get the path :
listBox1.items.Add(File.ReadAllText(item.FullName));
If you are only looking to get FileName of the file then use FileInfo.Name property like:
listBox1.items.Add(item.Name);
If you are looking to get file path then use FileInfo.FullName like:
listBox1.items.Add(item.FullName);
use the method File.ReadAllText to read each file.
string sourcePath = #"C:\sample\*.log";
DirectoryInfo dir = new DirectoryInfo(sourcePath);
FileInfo[] files = dir.GetFiles(sourcePath).OrderBy(order => order.LastWriteTime).ToArray();
foreach (var item in files)
{
string filecontent = File.ReadAllText(item.FullName);
//do your job here
......
listBox1.items.Add(item.Name);
}

Using GetFiles but splitting the results to show full path and just the filename

I am using “GetFiles” to extract files in a specified folder as shown below:
Directory.GetFiles(_dirPath, File_Filter);
This creates a string array which is fine but now I need to do something similar but create a Tuple array where each Tuple holds the full path including filename and also just the filename. So at the moment I have this in my string
C:\temp\test.txt
The new code needs to create a Tuple where each one looks similar to this:
Item1 = C:\temp\test.txt
Item2 = test.txt
I’m guessing I could do this this with a bit of Linq but am not sure. Speed and efficiency is too much of a problem as the lists will be very small.
You should use Directory.EnumerateFiles with LINQ which can improve performance if you don't need to consume all files. Then use the Path class:
Tuple<string, string>[] result = Directory.EnumerateFiles(_dirPath, File_Filter)
.Select(fn => Tuple.Create( fn, Path.GetFileName(fn) ))
.ToArray();
Use DirectoryInfo.GetFiles to return FileInfo instances, which have both file name and full name:
var directory = new DirectoryInfo(_dirPath);
var files = directory.GetFiles(File_Filter);
foreach(var file in files)
{
// use file.FullName
// use file.Name
}
That's much more readable than having tuple.Item1 and tuple.Item2. Or at least use some anonymous type instead of tuple, if you don't need to pass this data between methods:
var files = from f in Directory.EnumerateFiles(_dirPath, File_Filter)
select new {
Name = Path.GetFileName(f),
FullName = f
};
string[] arrayOfFiles = Directory.GetFiles(PathName.Text); // PathName contains the Path to your folder containing files//
string fullFilePath = "";
string fileName = "";
foreach (var file in arrayOfFiles)
{
fullFilePath = file;
fileName = System.IO.Path.GetFileName(file);
}

How to convert FileInfo into FileInfo[]

I have been working on a program that requires a different approach to finish a job using try and catch nested within another try/catch.
For this purpose I have had to create a set of files as strings and then converted them to FileInfo.
IEnumerable<string> paths = null;
foreach (String fil in paths)
FileInfo h = new FileInfo(fil);
So That wasn't so difficult, I require FileInfo to be in the form of a FileInfo[] array to continue the program however.
System.IO.FileInfo[] files = null;
Simply put, what is the best method to convert one type to the other, either directly from the string of from the converted FileInfo into a FileInfo array (FileInfo[])?
Yeah or create a single-item array:
FileInfo[] files = new FileInfo[] { info };
Why not directly?
paths.Select(p => new FileInfo(p)).ToArray();
Use:
var result = paths.Select(p => new FileInfo(p)).ToArray();
You could just use Linq select to create your FileInfo[]
IEnumerable<string> paths = null; // assuming you are going to fill this with filenames
FileInfo[] fileInfos = paths.Select(p => new FileInfo(p)).ToArray();

C# list file in directory issue

I am using VSTS 2008 + C# + .Net 3.0. I want to enumerate all files in a directory by creation time, i.e. files created more recently will be enumarate at first, older files will be enumerated at last. Any ideas how to implment this?
Something like that
System.IO.FileInfo[] array = new System.IO.DirectoryInfo("directory_path").GetFiles();
Array.Sort(array, delegate(System.IO.FileInfo f1, System.IO.FileInfo f2)
{
return f2.CreationTimeUtc.CompareTo(f1.CreationTimeUtc);
});
I would probably use LINQ and a list... something like this should work:
DirectoryInfo di = new DirectoryInfo("YourPath");
List<FileInfo> files = di.GetFiles().OrderBy(f => f.CreationTime).ToList();
foreach (FileInfo file in files)
{
//do something
}
Try somithing like this:
DirectoryInfo di = new DirectoryInfo("path to folder");
FileInfo[] files = di.GetFiles();
IOrderedEnumerable<FileInfo> enumerable = files.OrderBy(f => f.CreationTime);
foreach (FileInfo info in enumerable)
{
// do stuff...
}
EDIT: updated, here's a non-LINQ solution
FileInfo[] files = new DirectoryInfo("directory").GetFiles();
Array.Sort(files, delegate(FileInfo f1, FileInfo f2) {
return f2.CreationTime.CompareTo(f1.CreationTime);
});
The above will sort by latest to oldest. To sort by oldest to latest change the delegate to: return f1.CreationTime.CompareTo(f2.CreationTime);
LINQ solution:
FileInfo[] files = new DirectoryInfo("directory").GetFiles();
var results = files.OrderByDescending(file => file.CreationTime);
Use OrderByDescending to sort by most recent CreationTime, otherwise use OrderBy to sort from oldest to newest CreationTime.
DirectoryInfo baseFolder=new DirectoryInfo("folderName");
FileInfo[] files=baseFolder.GetFiles("");
for(int i=1; i<=files.Length;i++)
for(int j=1; j<files.Length;j++)
{
if(files[j].CreationTime > files[j+1].CreationTime)
{
FileInfo f = files[j];
files[j] = files[j+1];
files[j+1] = f;
}
}

Categories