How to get FileInfo via a foreach Loop? - c#

Trying to convert some VB to C#... (learning C#, too).
I have some code that loops through files in a directory and retrieves their file information. I have this originally in VB, but am trying to learn C#, and the online convertors don't give me code that will pass .net 2.0.
Here is the error:
Type and identifier are both required in a foreach statement
Here is the code I have:
DirectoryInfo dirInfo = new DirectoryInfo(currentDir);
FileInfo[] files = null;
files = dirInfo.GetFiles();
FileInfo f = default(FileInfo);
foreach (f in files) { ...
}
I tried putting foreach(FileInfo f... but it gives me a different error:
A local variable named 'f' cannot be declared in this scope because it would give a different meaning to 'f', which is already used in a 'parent or current' scope to denote something else
How do I fix it?

DirectoryInfo dirInfo = new DirectoryInfo(currentDir);
FileInfo[] files = null;
files = dirInfo.GetFiles();
// I removed the declaration of f here to prevent the name collision.
foreach (FileInfo f in files)
{ ...
}
Here is a simpler version of the code:
DirectoryInfo dirInfo = new DirectoryInfo(currentDir);
foreach (FileInfo f in dirInfo.GetFiles())
{
}

Here's where it looks like you're going wrong:
FileInfo f = default(FileInfo);
foreach (f in files) { ...
}
You are defining f outside of the loop, and then attempting to define it within the loop.
If you need the default to be f, try this:
FileInfo f = default(FileInfo);
foreach (FileInfo file in files)
{
relevant code here
}
Otherwise delete the statement declaring the variable "f"

You should provide type of variable used inside loop. In your case it will be FileInfo. But with C# 3.0 or later you can just write var and compiler will infer type for you:
foreach (FileInfo f in files)
{
// ...
}
Read more about foreach statement here.
Complete solution (you don't need to initialize iteration variable and array of files):
DirectoryInfo dir = new DirectoryInfo(currentDir);
foreach (FileInfo file in dir.GetFiles())
{
// use file
}

This should work:
DirectoryInfo dirInfo = new DirectoryInfo(currentDir);
FileInfo[] files = null;
files = dirInfo.GetFiles();
foreach (FileInfo f in files)
{
}
Edit:
This would be cleaner, in my opinion:
foreach (FileInfo f in new DirectoryInfo(currentDir).GetFiles())
{
}

Related

Get file extensions to populate into a ComboBox in 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);
}

Searching for a file in all directories

I need to find the file and also return the address of the file. I already tried, but it does not work.
Do you have any idea how to do this?
I was using this code:
var files = new List<string>();
//#Stan R. suggested an improvement to handle floppy drives...
//foreach (DriveInfo d in DriveInfo.GetDrives())
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady == true))
{
files.AddRange(Directory.GetFiles(d.RootDirectory.FullName, actualFile, SearchOption.AllDirectories));
}
I just created a quick test and Directory.GetFiles does return the entire path (what you're calling address) to the file. The Microsoft documentation (https://msdn.microsoft.com/en-us/library/07wt70x2(v=vs.110).aspx) says it returns:
An array of the full names (including paths) for the files in the specified directory, or an empty array if no files are found.
If you still need the complete FileInfo, you could do something like this... (There are more elegant ways, but this will get you want you want.)
var files = new List<string>();
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady == true))
{
var matchingFiles = Directory.GetFiles(d.RootDirectory.FullName, actualFile, SearchOption.AllDirectories));
foreach (var matchedFile in matchingFiles)
{
var fileInfo = new FileInfo(matchedFile);
// The newly created fileInfo will have everything you need, including path inside the FullName
files.Add(fileInfo.FullName);
}
}
I hope this helps.

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();

how can I copy a file with a certain date in c#

I have an issue with my code I can get it to copy all the files in a directory and it's subdirectories and I have got an if statement telling it to copy a file if the modified date is the same as today but it still copy's all the files I have searched on the internet for a solution and they all come up with vague answers that are similar to the doe I already have I have pasted the code below.
DirectoryInfo source = new DirectoryInfo(dlg.SelectedPath);
DirectoryInfo target = new DirectoryInfo(dlg2.SelectedPath);
DirectoryInfo dir = new DirectoryInfo(dlg.SelectedPath);
FileInfo[] fis = dir.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo fi in fis)
{
if (fi.LastWriteTime.Date == DateTime.Today.Date)
{
FileInfo[] sourceFiles = source.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo fc in sourceFiles)
if (fc.LastWriteTime.Date == DateTime.Today.Date)
for (int i = 0; i < sourceFiles.Length; ++i)
File.Copy(sourceFiles[i].FullName, target.FullName + "\\" + sourceFiles[i].Name, true);
}
}
any help will be appreciated
Shouldn't it be like this?
FileInfo[] fis = dir.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo fi in fis)
{
if (fi.LastWriteTime.Date == DateTime.Today.Date)
{
File.Copy(fi.FullName, target.FullName + "\\" + fi.Name, true);
}
}
The thing is, right now, whenever you find a file that fulfills your condition, you copy all the files in the source folder to the target folder, which is wrong. You should only copy the files that you need.
The code above will only work for the files in the root folder, but it's easy to make it work for subfolders as well. Just make another function that finds all the subfolders in a folder and call the code above with each of the subfolders as parameters.
The precision of the DateTime on the FileSystem and in .net isn't the same.
Try Something like this:
if((Math.Abs((currentFile.LastWriteTime - DateTime.Today.Date).TotalMilliseconds) > tolerance){...}
As an alternative, you could use a LINQ query like the following:
DirectoryInfo source = new DirectoryInfo(dlg.SelectedPath);
DirectoryInfo target = new DirectoryInfo(dlg2.SelectedPath);
var files = source.GetFiles("*", SearchOption.AllDirectories).Where(file => file.LastWriteTime.Date.Equals(DateTime.Today.Date));
foreach (FileInfo file in files)
File.Copy(file.FullName, target.FullName + "\\" + file.Name, true);
i think you are missing indentation or parenthesis after the if statement, i think it's an empty if followed by the copy statement. do
if (date == date)
{
filecopy
}

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