I would like to know what the most efficient way of converting a FileSystemInfo to a string array is - My code as is follows:
string[] filePaths;
DirectoryInfo di = new DirectoryInfo(batchDirectory);
FileSystemInfo[] files = di.GetFileSystemInfos();
filePaths = files.OrderBy(f => f.CreationTime);
I tried:
filePaths = files.OrderBy(f => f.CreationTime).ToArray;
but had no luck
Try this:
filePaths = files.OrderBy(f => f.CreationTime).Select(x => x.FullName).ToArray();
Add parenthesis () to Array;
files.OrderBy(f => f.CreationTime).ToArray();
Related
This is my folder structure:
c:\logs\v1\api1
c:\logs\v1\api2
c:\logs\v2\api1
c:\logs\v2\api2
c:\logs\other
I would like to get all folders that match this pattern:
c:\logs\v*\api*
So, what I want is to get list of theese:
c:\logs\v1\api1
c:\logs\v1\api2
c:\logs\v2\api1
c:\logs\v2\api2
This doesn't work:
var result = Directory.GetDirectories(#"c:\logs\v*\api*");
Because System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. : 'c:\logs\v*\api*'' is thrown
This doesn't work:
var directory = #"c:\logs\v*\api*";
var rootDirectory = Directory.GetDirectoryRoot(directory);
var remainingPath = directory.Substring(rootDirectory.Length);
Console.WriteLine($"remainingPath: {remainingPath}");
var result = Directory.GetDirectories(rootDirectory, remainingPath);
Because System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. : 'c:\logs\v*'' is thrown
This works:
public static IEnumerable<string> ResolveDirectories(string path)
{
if (path.Contains("*") || path.Contains("?"))
{
var parts = new Regex(#"[\\/](?=[^\\/]*[\*?])").Split(path, 2);
var searchRoot = parts[0];
var searchPatterns = parts[1].Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var dir in ResolveWildcards(searchRoot, searchPatterns))
yield return dir;
}
else
{
yield return path;
}
}
public static IEnumerable<string> ResolveWildcards(string searchRoot, string[] searchPatterns)
{
if (Directory.Exists(searchRoot))
{
// use next pattern to search in a search root
var next = searchPatterns[0];
// leave the rest for recursion
var rest = searchPatterns.Skip(1).ToArray();
if (!searchRoot.EndsWith("\\"))
searchRoot += "\\";
foreach (var dir in Directory.EnumerateDirectories(searchRoot, next))
{
// if nothing left (last pattern) - return it
if (rest.Length == 0)
yield return dir;
else
{
// otherwise search with rest patterns in freshly found directory
foreach (var sub in ResolveWildcards(dir, rest))
yield return sub;
}
}
}
}
But I don't like how this is coded.
Thanks to #Alessandro_D'Andria I created this:
public static IEnumerable<string> ResolveDirectories(string path)
{
var parts = new Regex(#"[\\/](?=[^\\/]*[\*?])").Split(path, 2);
var root = parts[0];
var part = #".*\\" + parts[1].Replace(#"\", #"\\");
var regex = new Regex(part);
var dirs = Directory
.EnumerateDirectories(
root,
"*",
SearchOption.AllDirectories)
.Where(x => regex.IsMatch(x))
.ToList();
return dirs;
}
But both solutions are big mess. Is there any more elegant solution?
I think you are complicating, just using some regex and linq should be enough:
var regex = new Regex(#".*\\logs\\v\d+\\api\d+");
var dirs = Directory
.EnumerateDirectories(
#"C:\logs",
"*",
SearchOption.AllDirectories)
.Where(x => regex.IsMatch(x));
i have two string array
string[] oldname = ["arun","jack","tom"];
string[] newname = ["jack","hardy","arun"];
here i want compare these two string arrays to get these distinct values separately like :
oldname = ["tom"];
newname = ["hardy"];
how to achieve these ...
string[] oldNameDistinct = oldname.Where(s => !newname.Contains(s)).ToArray();
string[] newNameDistinct = newname.Where(s => !oldname.Contains(s)).ToArray();
Let the two arrays were defined like the following:
string[] oldname = new[] { "arun", "jack", "tom" };
string[] newname = new string[] { "jack", "hardy", "arun" };
Then you can use the Extension method .Except to achieve the result that you are looking for. Consider the following code and the working example
var distinctInOld = oldname.Except(newname);
var distinctInNew = newname.Except(oldname);
Try this :
string[] oldname = new string[] { "arun", "jack", "tom" };
string[] newname = new string[] { "jack", "hardy", "arun" };
List<string> distinctoldname = new List<string>();
List<string> distinctnewname = new List<string>();
foreach (string txt in oldname)
{
if (Array.IndexOf(newname, txt) == -1)
distinctoldname.Add(txt);
}
foreach (string txt in newname)
{
if (Array.IndexOf(oldname, txt) == -1)
distinctnewname.Add(txt);
}
//here you can get both the arrays separately
Hope this help :)
string[] oldname = new []{"arun","jack","tom"};
string[] newname = new []{"jack","hardy","arun"};
// use linq to loop through through each list and return values not included in the other list.
var distinctOldName = oldname.Where(o => newname.All(n => n != o));
var distinctNewName = newname.Where(n => oldname.All(o => o != n));
distinctOldName.Dump(); // result is tom
distinctNewName.Dump(); // result is hardy
I've made a method that's doing some csv file creation. For testing purpose I was saving file on file system, but I don't want to do it like this.
This is my code:
void ICreateNewCsv.CreateCsvForIndividuals(List<FormattedPerson> formattedPersons)
{
//var CsvFilePath = "C:\\temp\\individuals.csv";
var csv = new StringBuilder();
var toExclude = new HashSet<string>
{
"ID",
"SubSystemID",
"System",
"Component"
};
var props = typeof (FormattedPerson).GetProperties(BindingFlags.Public | BindingFlags.Instance).
Where(property => !toExclude.Contains(property.Name));
var header = string.Join(", ", props.Select(p => p.Name.ToString()).ToArray());
csv.AppendLine(header);
for (var i = 0; i < formattedPersons.Count; i++)
{
var personTexts = formattedPersons
.Select(p => string.Join(",", p.Surname, p.FirstName, p.MiddleName, p.DateOfBirth,
p.NationalID, p.Gender, p.Address1, p.Address2, p.Address3,
p.City, p.Country, p.PostalCode, p.UniqueID));
var joined = string.Join(Environment.NewLine, personTexts);
csv.AppendLine(joined);
}
//File.AppendAllText(CsvFilePath, csv.ToString());
}
Is there a way to return csv file instead of just having void method?
I would suggest to replace void with FileStream,
then you will return a 'System.IO.FileStream' Object that can have the Type of everything (.CSV but also Text or anything else).
Than you would just have to Parse/Use it the way you'd like in the part where you call the Method:
FileStream objFile = ICreateNewCsv.CreateCsvForIndividuals(formattedPersons);
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();
I have FileInfo[] fileInfos
I want to populate
string[] filesNames and List<string> fileNamesList using LINQ expression, how should I do it?
FileInfo has a Name property, so
var fileNamesList = fileInfos.Select(fi => fi.Name).ToList();
var filesNames = fileInfos.Select(fi => fi.Name).ToArray();
I don't see why you would need both a List and an array though.
var list = fileInfos.Select(fi => fi.Name).ToList();
var arr = fileInfos.Select(fi => fi.Name).ToArray();
List<string> filesNamesList = fileInfos.Select(fi => fi.Name).ToList();
string[] filesNames = filesNamesList.ToArray();
Try this code:
var fileList = fileInfos.Select(f => f.Name).ToList();