I am working in C#. I have a segment of code that returns the file as well as path of a specific file type and places them inside a select list
private void Form1_Load(object sender, EventArgs e)
{
// Only get .sde files
string[] dirs = System.IO.Directory.GetFiles(#"c:\Users\JohnDoe\Desktop\my_files", "*.sde");
this.GetSdePath.Items.AddRange(dirs);
}
When I run my program, the select list contains all the sde files. They are listed/displayed as such:
c:\Users\JohnDoe\Desktop\my_files\NewCreated.sde
c:\Users\JohnDoe\Desktop\my_files\Inventory.sde
c:\Users\JohnDoe\Desktop\my_files\Surplus.sde
c:\Users\JohnDoe\Desktop\my_files\Logistics.sde
I am wondering if in my select list is it possible to hide the path and just display the name of the sde file. So the list would look like
NewCreated.sde
Inventory.sde
Surplus.sde
Logistics.sde
BUT, each value in the list would return the full path and name.
Any help on this topic would be greatly appreciated. Thanks in advance.
Use Path.GetFileName(string path)
private void Form1_Load(object sender, EventArgs e)
{
// Only get .sde files
string[] dirs = System.IO.Directory.GetFiles(#"c:\Users\JohnDoe\Desktop\my_files", "*.sde");
this.GetSdePath.Items.AddRange(dirs.Select(path => Path.GetFileName(path).ToArray());
}
Using Select on the sequence returned to apply the Path.GetFileName method that extracts just the filename from the fullpath
var dirs = System.IO.Directory.GetFiles(#"c:\Users\JohnDoe\Desktop\my_files", "*.sde")
.Select (d => Path.GetFileName(d));
this.GetSdePath.Items.AddRange(dirs.ToArray());
I don't know how many files are present in your folder but probably it is better to use EnumerateFiles instead of GetFiles
var dirs = System.IO.Directory.EnumerateFiles(#"c:\Users\JohnDoe\Desktop\my_files", "*.sde")
.Select (d => Path.GetFileName(d));
MSDN says
The EnumerateFiles and GetFiles methods differ as follows: When you
use EnumerateFiles, you can start enumerating the collection of names
before the whole collection is returned; when you use GetFiles, you
must wait for the whole array of names to be returned before you can
access the array. Therefore, when you are working with many files and
directories, EnumerateFiles can be more efficient.
EDIT
Following your comments below the choice of EnumerateFiles is not possible (available from NET 4.0) and if you want to keep the full path name available for other tasks but show just the filename in the listbox then you need to keep it in some kind of collection (an array or better a list)
using System.IO;
...
string sourcePath = #"c:\Users\JohnDoe\Desktop\my_files";
List<string> dirs = Directory.GetFiles(sourcePath, "*.sde")
.Select (d => Path.GetFileName(d)
.ToList());
this.GetSdePath.Items.AddRange(dirs.ToArray());
;
Make List<string>dirs a form level variable if you need its content outside the Form_Load event
Related
DirectoryInfo d = new DirectoryInfo(mypath);//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles("*.jpg"); //Getting Text files
How the files array could be order by name?
let's say
files[0].Name is 'hi1.jpg'
files[1].Name is 'hi2.jpg'
and so on
It is just a call to OrderBy in Linq namespace
using System.Linq;
....
FileInfo[] Files = d.GetFiles("*.jpg").OrderBy(x => x.Name).ToArray();
By the way, I suggest you to use EnumerateFiles instead of GetFiles. In particular if you have to loop over the result like this
foreach(FileInfo fi in d.EnumerateFiles("*.jpg").OrderBy(x => x.Name))
Console.WriteLine(fi.Name);
As explained in the MSDN documentation
The EnumerateFiles and GetFiles methods differ as follows: When you
use EnumerateFiles, you can start enumerating the collection of
FileInfo objects before the whole collection is returned. When you
use GetFiles, you must wait for the whole array of FileInfo objects to
be returned before you can access the array.
FileInfo[] Files = d.GetFiles("*.jpg").OrderBy(f => f.Name).ToArray();
Using Linq
d.GetFiles("*.jpg").OrderBy(file=> file.Name).ToArray();
FileInfo[] files = d.GetFiles("*.jpg").OrderBy(file => file.Name).ToArray();
As answered above .ToArray() function along with OrderBy(columnName) does the job.
I am having a little trouble getting files into a string[]. Everything seems to be ok until I have a .docx and doc file and a .xlsx and a .xls file in my directory that I am searching. Can someone advise me on how to acheive this?
Please see my code that I have so far below:
Filter = ".DOC|.DOCX|.XLS|.XLSX|.PDF|.TXT|.TIF|.TIFF"
public string[] getFiles(string SourceFolder, string Filter)
{
// ArrayList will hold all file names
System.Collections.ArrayList alFiles = new System.Collections.ArrayList();
// Create an array of filter string
string[] MultipleFilters = Filter.Split('|');
// for each filter find mathing file names
foreach (string FileFilter in MultipleFilters)
{
// add found file names to array list
alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter));
}
// returns string array of relevant file names
return (string[])alFiles.ToArray(typeof(string));
}
Thanks,
George
You can take advantage of LINQ's Distinct() (System.Linq).
Returns distinct elements from a sequence by using the default equality comparer to compare values.
Filter = ".DOC|.DOCX|.XLS|.XLSX|.PDF|.TXT|.TIF|.TIFF";
public string[] GetFiles(string SourceFolder, string Filter)
{
List<string> alFiles = new List<string>();
string[] MultipleFilters = Filter.Split('|');
foreach (string FileFilter in MultipleFilters)
{
alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter));
}
return alFiles.Distinct().ToArray();
}
Notice that I am now creating a new List<string> instance (System.Collections.Generic), instead of your ArrayList
First off, the code as originally posted doesn't return any files, because none of the calls to Directory.GetFiles() include a wildcard in the filter.
Second, assuming that the original filter did include wildcards, there's a nasty little surprise in the MSDN Directory.GetFiles(string, string) documentation:
When you use the asterisk wildcard character in a searchPattern such
as "*.txt", the number of characters in the specified extension
affects the search as follows:
•If the specified extension is exactly three characters long, the
method returns files with extensions that begin with the specified
extension. For example, "*.xls" returns both "book.xls" and
"book.xlsx".
•In all other cases, the method returns files that exactly match the
specified extension. For example, "*.ai" returns "file.ai" but not
"file.aif".
(emphasis added)
Rather than trying to work around the "helpful" behavior of the Directory.GetFiles(string, string) overload, I'd use the Directory.GetFiles(string) overload to get all the files and then filter the results using LINQ:
public string[] getFiles(string SourceFolder, string Filter)
{
string[] MultipleFilters = Filter.Split('|');
var SelectedFiles = Directory.GetFiles(SourceFolder)
.Where(f => MultipleFilters.Contains(Path.GetExtension(f).ToUpper()))
.Select(f => f);
return SelectedFiles.ToArray();
}
If there are huge number of files in the folder then getting all files could cause memory problem.
In below code I am searching files based on wild card filter and then filtering them using LINQ :)
string Filter = ".DOC|.DOCX|.XLS|.XLSX|.PDF|.TXT|.TIF|.TIFF" //without "*"
public string[] getFiles(string SourceFolder, string Filter)
{
var filters = Filter.ToUpper().Split('|');
return filters.SelectMany(filter => System.IO.Directory.GetFiles(SourceFolder, "*"+filter)).Where(file=> filters.Contains(Path.GetExtension(file).ToUpper())).ToArray();
}
Currently I am using the following code to search for files in a folder:
public string[] getFiles(string SourceFolder, string Filter,System.IO.SearchOption searchOption)
{
// ArrayList will hold all file names
ArrayList alFiles = new ArrayList();
// Create an array of filter string
string[] MultipleFilters = Filter.Split('|');
// for each filter find mathing file names
foreach (string FileFilter in MultipleFilters)
{
// add found file names to array list
alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption));
}
// returns string array of relevant file names
return (string[])alFiles.ToArray(typeof(string));
}
The problem is that when I pass a drive like D:\\ as the path to search, either I get an exception in GetFiles() or nothing is found!
I also get exceptions when I try to access some hidden or system secured folder.
How can I properly search for files in a drive or folder recursively?
One more thing, I come to know that a extension like "abc" may return files with having extensions like "abcd" or "abcde".
If this is true, how can I overcome this problem?
Thank you.
I have a snippet of code that will traverse a directory location and create a data model from it. For example, if I have a directory structure:
c:\TestDir1
c:\TestDir1\Sub1\
c:\TestDir1\Sub1\File1.txt
c:\TestDir1\Sub1\File2.txt
c:\TestDir1\Sub1\SubSub1
c:\TestDir1\Sub1\SubSub1\File3.xlsx
c:\TestDir1\Sub1\SubSub1\SubDirX
c:\TestDir1\Sub1\SubSub1\SubDirX\File4.txt
c:\TestDir1\Sub1\SubSub1\SubDirX\File5.txt
c:\TestDir1\Sub1\SubSub1\SubDirX\File6.txt
It will create the appropriate data model via the following code:
static void BeginIt()
{
DirectoryInfo diTop = new DirectoryInfo(#"c:\Misc\3) Projects\002) Document Manager\DirectoryReading\TestDir1");
string path = diTop.FullName;
MySubDir mySubDir = new MySubDir(path);
}
public class MySubDir
{
public ArrayList _dirs;
public ArrayList _files;
public MySubDir(string dirPath)
{
_dirs = new ArrayList();
_files = new ArrayList();
this.ProcessDirectory(dirPath);
}
private void ProcessDirectory(string dirPath)
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(dirPath);
foreach (string fileName in fileEntries)
{
_files.Add(fileName);
}
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries = Directory.GetDirectories(dirPath);
foreach (string subdirectory in subdirectoryEntries)
{
_dirs.Add(new MySubDir(subdirectory));
}
}
}
Here's my question. When I step through the code line by line it is building up the data model appropriately. When I do an AddWatch I can see the object and the directory structure is built up properly.
When I try to access the value of the contents via the Immediate Window I get errors. For example if I type the following into the immediate window the following
? mySubDir._dirs[0]._dirs[0]
I get an error.
How do I get at the values of these subdirectories? I would like to be able to access the directory names and filenames of the elements in this model now that it is created.
Thanks
That doesn't look like it would work, since the expression mySubDir.whatever depends on mySubDir being in scope and having a valid value. In order for that to happen, the constructor has to return first -- but the object is being populated during the execution of the constructor. So there's really no point during the lifetime of this program that such an expression would yield a meaningful result.
If you break into the debugger inside the ProcessDirectory method, you can use this._dirs to have a look into the data structure.
Apart from that, ArrayList is not the best choice for a collection that you know from beforehand will contain just strings, like the ones you have here. It would be more appropriate to define those as System.Collections.Generic.List<string>.
well.. _dirs and files are arraylist.. so you might want to transverse that list and get all the values. a for, an enumerator, a linq or whatever method you like will do the trick..
Update:
After reading some more your post, I think there is a problem of basic understand. Adding just names to the class, will not give you the file position or it folder. You will have to look for a better way to use it (maybe a class folder/files that can hold folders also?)..
_dirs is an ArrayList which stores objects so you need to cast the object from the first _dir[0] to a MySubDir
e.g.
((MySubDir)mySubDir._dir[0])._dir[0]
Either that or change the collection type from ArrayList to
List<MySubDir>
this will give you strongly typed list items when accessed with the indexer.
Hi i'm a c# begginer and i'd like to do a simple program which is going to go through a folder and count how many files are .mp3 files and how many are .flac .
Like I said the program is very basic. It will ask for the music folder path and will then go through it. I know there will be a lot of subfolders in that main music folder so it will have to open them one at the time and go through them too.
E.g
C:/Music/
will be the given directory.
But it doesn't contain any music in itself.
To get to the music files the program would have to open subfolders like
C:/Music/Electronic/deadmau5/RandomAlbumTitle/
Only then he can count the .mp3 files and .flac files and store them in two separated counters.
The program will have to do that for at least 2000 folders.
Do you know a good way or method to go through files and return its name (and extension)?
You can use System.IO.DirectoryInfo. DirectoryInfo provides a GetFiles method, which also has a recursive option, so if you're not worried about speed, you can do this:
DirectoryInfo di = new DirectoryInfo(#"C:\Music");
int numMP3 = di.GetFiles("*.mp3", SearchOption.AllDirectories).Length;
int numFLAC = di.GetFiles("*.flac", SearchOption.AllDirectories).Length;
Use DirectoryInfo and a grouping by the file extension:
var di = new DirectoryInfo(#"C:/Music/");
var extensionCounts = di.EnumerateFiles("*.*", SearchOption.AllDirectories)
.GroupBy(x => x.Extension)
.Select(g => new { Extension = g.Key, Count = g.Count() })
.ToList();
foreach (var group in extensionCounts)
{
Console.WriteLine("There are {0} files with extension {1}", group.Count,
group.Extension);
}
C# has a built in method of searching for files in all sub-directories. Make sure you add a using statement for System.IO
var path = "C:/Music/"
var files = Directory.GetFiles(path, "*.mp3", SearchOption.AllDirectories);
var count = files.Length;
Since you're a beginner you should hold off on the more flexible LINQ method until later.
int fileCount = Directory.GetFiles(_Path, "*.*", SearchOption.TopDirectoryOnly).Length
Duplicate question How to read File names recursively from subfolder using LINQ
Jon Skeet answered there with
You don't need to use LINQ to do this - it's built into the framework:
string[] files = Directory.GetFiles(directory, "*.dll",
SearchOption.AllDirectories);
or if you're using .NET 4:
IEnumerable<string> files = Directory.EnumerateFiles(directory, "*.dll",
SearchOption.AllDirectories);
To be honest, LINQ isn't great in terms of recursion. You'd probably want to write your own general-purpose recursive extension method. Given how often this sort of question is asked, I should really do that myself some time...
Here is MSDN support page, How to recursively search directories by Visual C#
Taken directly from that page:
void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, txtFile.Text))
{
lstFilesFound.Items.Add(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
You can use this code in addition to creating FileInfo objects. Once you have the file info objects you can check the Extension property to see if it matches the ones you care about.
MSDN has lots of information and examples, for example how you can iterate through a directory: http://msdn.microsoft.com/en-us/library/bb513869.aspx