Initialize a list from a second llist - c#

I want to initialize a List of images, from a List of files. The constructor of MyImage accepts one file.
Is there a shorter way to initialize the list of images? Perhaps using LINQ?
public List<MyImage> GetImages(string path)
{
List<MyImage> images = new List<MyImage>();
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] files = di.GetFiles();
// is there a shorter way to do this?
foreach (FileInfo fi in files)
{
MyImage image = new MyImage(fi);
images.Add(image);
}
return images;
}

You can return an IEnumerable<MyImage> and transform your code like
public IEnumerable<MyImage> GetImages(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] files = di.GetFiles();
return files.Select(fi => new ImageUpload(fi));
}
Note that you can still return List<MyImage>, just apply .ToList() if that's the case.

Instead foreach try:
files.Select(f=> new MyImage(f)).ToList();
If you need some conditions try this:
files.Where(f=> f.Name.Contains(".jpg"))
.Select(f=> new MyImage(f)).ToList();

Related

StackoverFlowException When creating ZipArchive from within ZipArchive

I am attempting to recursively parse through a zip folder and any zip folders inside it to collect files using the following code:
private IList<IFile> _getFilesFromZip(ZipArchive zipArchive)
{
var returnFiles = new List<IFile>();
foreach (var zippedFile in zipArchive.Entries)
{
var name = zippedFile.Name;
var type = Path.GetExtension(zippedFile.Name).Replace(".", "");
if (type == "zip")
{
var innerZipArchive = new ZipArchive(zippedFile.Open(), ZipArchiveMode.Read);
returnFiles.AddRange(_getConversionFilesFromZip(zipArchive));
}
else
{ ...
var innerZipArchive = new ZipArchive(zippedFile.Open(), ZipArchiveMode.Read);
Throws a StackOverflow exception no matter how small the files.
How can I create a zipArchive from the ZipArchiveEntry of the first ZipArchive?

Treeview with different folder classes

I'm trying to pull together a treeview with folders of mixed classes. The root folders are one class and subfolders are another, like this:
Root Folder #1 <-- DirectoryItem class
--Sub Folder <-- SubDirectoryItem class
----file <-- FileItem class
Root Folder #2 <-- DirectoryItem class
--Sub Folder <-- SubDirectoryItem class
----file <-- FileItem class
I've been attempting to combine two different recursive methods so the subfolders are retrieved as "SubDirectoryItems" instead of "DirectoryItem" I'll spare that code attempt due to lack of clarify, but I'm wondering if there's a better approach?
class ItemProvider
{
public List<Item> GetItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var subdirectory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new SubDirectoryItem()
{
Name = subdirectory.Name,
Path = subdirectory.FullName,
Items = GetItems(subdirectory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var file in dirInfo.GetFiles())
{
var item = new FileItem
{
Name = file.Name,
Path = file.FullName
};
items.Add(item);
}
return items;
}
}
}
I was able to figure it out. I made the first list TopDirectoryOnly then pulled in the rest of the items via a 2nd list for AllDirectories. Here's the code in case it helps any other beginners (like me):
class ItemProvider
{
public List<Item> GetItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetSubItems(directory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
return items;
}
public List<Item> GetSubItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var subdirectory in dirInfo.GetDirectories("*.*", SearchOption.AllDirectories))
{
var item = new SubDirectoryItem()
{
Name = subdirectory.Name,
Path = subdirectory.FullName,
Items = GetSubItems(subdirectory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var file in dirInfo.GetFiles())
{
var item = new FileItem
{
Name = file.Name,
Path = file.FullName
};
items.Add(item);
}
return items;
}
}

Add values in Varray using LINQ

I have a varray string:
string[] imgList = new[] { };
And I retrieve the list of files:
DirectoryInfo directory = new DirectoryInfo(path);
FileInfo[] files = directory.GetFiles("*.jpg");
I want to add in my varray using LINQ the result. Some like this:
imgList = files.Where(x => x.FullName).ToList();
How can I do that?
Change Where to Select, and ToList() to ToArray() in your query.
imgList = files.Select(x => x.FullName).ToArray();
Something like this:
DirectoryInfo directory = new DirectoryInfo(path);
FileInfo[] files = directory.GetFiles("*.jpg");
string[] imgList = files.Select(p => p.Name).ToArray();
// or, without LINQ, probably a little faster:
string[] imgList = Array.ConvertAll(files, p => p.Name);
Note that in both cases you don't need to create the array beforehand, because a new array is returned by the Array.Convert/.ToArray().
There is a method that returns an array, as well the method you're using which returns a List<T>, so try:
imgList = files.Select(x => x.FullName).ToArray();
You have some error in your code.
First you have an incorrect string array declaration,
second you are trying convert .ToList() to string array. So try something like this
string[] imgList = new string[] { };
DirectoryInfo directory = new DirectoryInfo(path);
FileInfo[] files = directory.GetFiles("*.jpg");
imgList = files.Where(x => x.FullName == "myCondition").Select(x => x.FullName).ToArray();

Best way to enumurate the following directories and files

I have bunch of directories at a certain paths in the following possible format:
C:\Program Files\Logic\DDC[ 0 ]
C:\Program Files\Logic\DDC[ 1]
C:\Program Files\Logic\DDC[2 ]
C:\Program Files\Logic\DDC[3]
I'd like to accomplish the following:
1)Enumurate all of numbered DDC directories and store their paths them in a List of String
I.E: List<String> ddcPaths -> should have:
ddcPaths[0] = "DDC[0]";
ddcPaths[1] = "DDC[1]";
ddcPaths[2] = "DDC[2]";
2)Enumurate all files directly under the DDC folder but nothing deeper than that
I.E: If DDC[0] has a.txt, b.txt and obj\c.txt, I should get
List<String> ddc_0 -> should have
ddc_0[0] = "a.txt";
ddc_0[1] = "b.txt";
I hope my explanation was clear enough but if something didn't make sense, please let me know.
If U have such data structure I suggest U should use one dictionary with directory name as key, and list of it's filenames as value. For example:
var ddcPaths = new Dictionary<string, List<string>>();
foreach (var directoryInfo in new DirectoryInfo(#"C:\Program Files\Logic\").GetDirectories())
{
if (directoryInfo.Name.Contains("DDC["))
{
ddcPaths.Add(directoryInfo.Name, new List<string>());
foreach (var fileInfo in directoryInfo.GetFiles())
{
ddcPaths[directoryInfo.Name].Add(fileInfo.FullName);
}
}
}
but you should notice than U cant get Dictionary value by int index, only by key, declared in this dictionary (folder name in our case). But if U don't want to do like this U can do the following:
var ddcPaths = new List<string>();
var filePaths = new List<List<string>>();
foreach (var directoryInfo in new DirectoryInfo(#"C:\Program Files\Logic\").GetDirectories())
{
if (directoryInfo.Name.Contains("DDC["))
{
ddcPaths.Add(directoryInfo.Name);
var tempList = new List<string>();
foreach (var fileInfo in directoryInfo.GetFiles())
{
tempList.Add(fileInfo.FullName);
}
filePaths.Add(tempList);
}
}
but in this case U use two different data structures to represent related data. I suggest it would be logically to use dictionary.
You can use DirectoryInfo.
DirectoryInfo dirInfo = new DirectoryInfo("yourFolderPath");
IEnumerable<DirectoryInfo> subDirs = dirInfo.EnumerateDirectories();
List<string> subDirsNames = new List<string>();
foreach (var subDir in subDirs)
{
subDirsNames.Add(subDir.Name.Trim());
IEnumerable<string> files = subDir.EnumerateFiles().Select(i => i.Name);
//do something with this list....
}

How to compare two folders for similar files based on name in C#?

I have two folders A and B..Inside A multiple files are there and inside B multiple files are there..I have to check files in A with files in B for identical files...
I tried like this for a particular file name
void DirSearch(string sDir)
{
List<string> lstFilesFound = new List<string>();
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d,"MsBuild_Tracker.proj")
{
lstFilesFound.Add(f);
}
DirSearch(d);
}
}
It is working..I tried like this for two folders
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetDirectories(dDir))
{
foreach (string g in Directory.GetFiles(d, f))
{
lstFilesFound.Add(g);
}
DirSearch(d, f);
}
}
It is not working...Any suggestion??
If you're using .NET 4, you can use DirectoryInfo and EnumerateFiles(). Then you can use LINQ to join the two directories to get the common files between the two directories.
var dir1 = new DirectoryInfo(#"c:\temp1");
var dir2 = new DirectoryInfo(#"c:\temp2");
var filesinboth = from f1 in dir1.EnumerateFiles()
join f2 in dir2.EnumerateFiles() on f1.Name equals f2.Name
select f1.Name;
or you can use where if you want additional conditions to apply.
var filesinboth = from f1 in dir1.EnumerateFiles()
from f2 in dir2.EnumerateFiles()
where f1.Name == f2.Name // and some other condition
select f1.Name;
These will both give you stream of strings. If you need the actual FileInfo instances, change the select part of the query to return f1 instead of f1.Name.
If you're using .NET 3.5, you need to use GetFiles() instead, which returns FileInfo[]. So the queries will look like this:
var filesinboth = from f1 in dir1.GetFiles()
join f2 in dir2.GetFiles() on f1.Name equals f2.Name
select f1.Name;
and
var filesinboth = from f1 in dir1.GetFiles()
from f2 in dir2.GetFiles()
where f1.Name == f2.Name // and some other condition
select f1.Name;
Why don't use just something like this (without recursion) ?
public static IEnumerable<string> GetMachingFiles(string pathA, string pathB)
{
var matchingFiles = new HashSet<string>();
var allAfiles = Directory.GetFiles(pathA, "*", SearchOption.AllDirectories);
foreach (var file in allAfiles)
{
foreach (var mathcFile in Directory.GetFiles(pathB, Path.GetFileName(file), SearchOption.AllDirectories))
matchingFiles.Add(mathcFile);
}
return matchingFiles;
}
Of course this solution suffers a performance decay in case of many files, because Directory.GetFiles navigates all files even when you pass a restrictive pattern.
To be more faster you could use LINQ as pointed out in Brian Rasmussen's answer
EDIT:
a faster example using LINQ (.NET 3.5):
public static IEnumerable<string> GetMachingFilesFast(string pathA, string pathB)
{
DirectoryInfo dirA = new DirectoryInfo(pathA);
DirectoryInfo dirB = new DirectoryInfo(pathB);
var filesA = dirA.GetFiles("*",SearchOption.AllDirectories);
var filesB = dirB.GetFiles("*", SearchOption.AllDirectories);
var matchingFiles =
filesA.Where(fA => filesB.Any(
fB => fA.Name == fB.Name
// && fA.LastWriteTime == fB.LastWriteTime
)
)
.Select(x => x.Name);
return matchingFiles;
}
try below code , you need to change path of files
DirectoryInfo dinfoTemp1 = new DirectoryInfo(#"C:\\Temp1");
DirectoryInfo dinfoTemp2 = new DirectoryInfo(#"C:\\Temp2");
FileInfo[] lstTemp1 = dinfoTemp1.GetFiles();
List<string> ui = lstTemp1.Where(
x => dinfoTemp2.GetFiles().
Where(y => y.Name.Contains(x.Name)).Count() > 0).
Select(x=>x.Name).ToList();
What you are basically doing is:
setting directory to var d like C://
Setting directory to var f like My Documents
Getting files that have the name My Documents in C://
and if you find any which I highly doubt, you add it to your list.
The first one works because;
sets the directory to var d like C://
gets the file that is named MsBuild_Tracker.proj in C://
adds it to the list.
Tell us what you need and maybe we can help..
Maybe compare (for a non-linq version) --
namespace RecursiveDirCompare
{
class Program
{
static List initialFiles = new List();
static string initRoot = #"root";
static string initCompare = #"compare";
static void Main(string[] args)
{
Directory.SetCurrentDirectory( #"C:\Temp\test\");
initRoot = #"root";// args[0];
initCompare = #"compare";// args[1];
AddFilesToInitialList(initRoot);
CompareWithInitialList(initCompare);
Console.ReadKey();
}
static void AddFilesToInitialList(string root)
{
foreach (string file in Directory.GetFiles(root))
{
initialFiles.Add(file.Replace(initRoot, ""));
}
foreach (string directory in Directory.GetDirectories(root))
{
AddFilesToInitialList(directory);
}
}
static void CompareWithInitialList(string root)
{
foreach (string file in Directory.GetFiles(root))
{
if(initialFiles.Contains(file.Replace(initCompare, "")))
{
Console.WriteLine(file + " is found in both");
}
}
foreach (string directory in Directory.GetDirectories(root))
{
CompareWithInitialList(directory);
}
}
}
}

Categories