How to split path to set of Path - c#

I have one path variable like 'Customer\\Calls\\A1\\A2\\A3\\A4'.From this i want split it into an array like
'Customer'
'Customer\Calls'
'Customer\Calls\A1'
'Customer\Calls\A1\A2'
'Customer\Calls\A1\A2\A3'
'Customer\Calls\A1\A2\A3\A4'
If we do it like
string[] directories = currentFolderPath.Split(Path.DirectorySeparatorChar);
we will get a set of folder,but it will not get in above structure
Can anyone suggest a better approach

Get parent directory until you get to the root
if it's an absolute path
private static IEnumerable<string> SplitPath(string path){
do{
yield return path;
path=Path.GetDirectoryName(path);
} while(path!=null);
}
if it is a relative path
private static IEnumerable<string> SplitRelativePath(string path){
do{
yield return path;
var lastIndex=path.LastIndexOf('\\');
if(lastIndex==-1)
yield break;
path=path.Substring(0, lastIndex);
} while(path!=null);
}
//usage
SplitRelativePath(#"Customer\Calls\A1\A2\A3\A4");
/* result:
C:\Customer\Calls\A1\A2\A3\A4
C:\Customer\Calls\A1\A2\A3
C:\Customer\Calls\A1\A2
C:\Customer\Calls\A1
C:\Customer\Calls
C:\Customer
C:\ *

string path = #"Customer\Calls\A1\A2\A3\A4";
var sections = path.Split('\\').ToList();
var result = Enumerable.Range(0, sections.Count)
.Select(index => string.Join(#"\", sections.Take(index + 1)))
.ToList();
//Result:
// Customer
// Customer\Calls
// Customer\Calls\A1
// Customer\Calls\A1\A2
// Customer\Calls\A1\A2\A3
// Customer\Calls\A1\A2\A3\A4

It's not really obvious from your post, but if you need to do something with each item in your array, I would probably take this approach:
string path = string.Empty;
"Customer\\Calls\\A1\\A2\\A3\\A4".Split(new Char[] { '\\' }).ToList().ForEach(
part => {
path = Path.Combine(path, part);
// Do stuff!
}
);

// easy and simple try this
string path = #"Customer\Calls\A1\A2\A3\A4";
string[] pathArr = path.Split('\\');
List<string> list = new List<string>();
for (int i = 0; i < pathArr.Length; i++)
{
string temp = pathArr[i];
if (i > 0)
{
temp = list[i - 1].ToString() + #"\" + temp;
}
list.Add(temp);
}

string path = "Customer\\Calls\\A1\\A2\\A3\\A4";
var pathArr = path.Split(new string[] { "\\" }, StringSplitOptions.None);
var pathList = new List<string>();
while (pathArr.Length != pathList.Count)
{
string modifiedPath = "";
for (int i = 0; i < pathArr.Length; i++)
{
modifiedPath = modifiedPath + pathArr[i] + "\\";
if (i == pathList.Count)
{
pathList.Add(modifiedPath);
break;
}
}
}
foreach (var str in pathList)
{
Console.WriteLine(str.Remove(str.Length - 1));
}
Console.ReadKey();

Related

get line number of string in file C#

That code makes filter on the files with the regular expression, and to shape the results. But how can I get a line number of each matches in the file?
I have no idea how to do it...
Please help me
class QueryWithRegEx
enter code here
IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);
System.Text.RegularExpressions.Regex searchTerm =
new System.Text.RegularExpressions.Regex(#"Visual (Basic|C#|C\+\+|Studio)");
var queryMatchingFiles =
from file in fileList
where file.Extension == ".htm"
let fileText = System.IO.File.ReadAllText(file.FullName)
let matches = searchTerm.Matches(fileText)
where matches.Count > 0
select new
{
name = file.FullName,
matchedValues = from System.Text.RegularExpressions.Match match in matches
select match.Value
};
Console.WriteLine("The term \"{0}\" was found in:", searchTerm.ToString());
foreach (var v in queryMatchingFiles)
{
string s = v.name.Substring(startFolder.Length - 1);
Console.WriteLine(s);
foreach (var v2 in v.matchedValues)
{
Console.WriteLine(" " + v2);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
static IEnumerable<System.IO.FileInfo> GetFiles(string path)
{
...}
Give this a go:
var queryMatchingFiles =
from file in Directory.GetFiles(startFolder)
let fi = new FileInfo(file)
where fi.Extension == ".htm"
from line in File.ReadLines(file).Select((text, index) => (text, index))
let match = searchTerm.Match(line.text)
where match.Success
select new
{
name = file,
line = line.text,
number = line.index + 1
};
You can Understand from this example:
Read lines number 3 from string
string line = File.ReadLines(FileName).Skip(14).Take(1).First();
Read text from a certain line number from string
string GetLine(string text, int lineNo)
{
string[] lines = text.Replace("\r","").Split('\n');
return lines.Length >= lineNo ? lines[lineNo-1] : null;
}
Retrieving the line number from a Regex match can be tricky, I'd use the following approach:
private static void FindMatches(string startFolder)
{
var searchTerm = new Regex(#"Visual (Basic|C#|C\+\+|Studio)");
foreach (var file in Directory.GetFiles(startFolder, "*.htm"))
{
using (var reader = new StreamReader(file))
{
int lineNumber = 1;
string lineText;
while ((lineText = reader.ReadLine()) != null)
{
foreach (var match in searchTerm.Matches(lineText).Cast<Match>())
{
Console.WriteLine($"Match found: <{match.Value}> in file <{file}>, line <{lineNumber}>");
}
lineNumber++;
}
}
}
}

String formatting in C#?

I have some problems to format strings from a List<string>
Here's a picture of the List values:
Now I managed to manipulate some of the values but others not, here's what I used to manipulate:
string prepareStr(string itemToPrepare) {
string first = string.Empty;
string second = string.Empty;
if (itemToPrepare.Contains("\"")) {
first = itemToPrepare.Replace("\"", "");
}
if (first.Contains("-")) {
int beginIndex = first.IndexOf("-");
second = first.Remove(beginIndex, first.Length - beginIndex);
}
return second;
}
Here's a picture of the Result:
I need to get the clear Path without the (-startup , -minimzed , MSRun , double apostrophes).
What am I doing wrong here?
EDIT my updated code:
void getStartUpEntries() {
var startEntries = StartUp.getStartUp();
if (startEntries != null && startEntries.Count != 0) {
for (int i = 0; i < startEntries.Count; i++) {
var splitEntry = startEntries[i].Split(new string[] { "||" }, StringSplitOptions.None);
var str = splitEntry[1];
var match = Regex.Match(str, #"\|\|""(?<path>(?:\""|[^""])*)""");
var finishedPath = match.Groups["path"].ToString();
if (!string.IsNullOrEmpty(finishedPath)) {
if (File.Exists(finishedPath) || Directory.Exists(finishedPath)) {
var _startUpObj = new StartUp(splitEntry[0], finishedPath,
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(finishedPath));
_startUpList.Add(_startUpObj);
}
else {
var _startUpObjNo = new StartUp(splitEntry[0], finishedPath,
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(string.Empty));
_startUpList.Add(_startUpObjNo);
}
}
var _startUpObjLast = new StartUp(splitEntry[0], splitEntry[1],
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(string.Empty));
_startUpList.Add(_startUpObjLast);
}
lstStartUp.ItemsSource = _startUpList.OrderBy(item => item.Name).ToList();
}
You could use a regex to extract the path:
var str = #"0Raptr||""C:\Program Files (x86)\Raptr\raptrstub.exe"" --startup"
var match = Regex.Match(str, #"\|\|""(?<path>(?:\""|[^""])*)""");
Console.WriteLine(match.Groups["path"]);
This will match any (even empty) text (either an escaped quote, or any character which is not a quote) between two quote characters preceeded by two pipe characters.
Similarly, you could simply split on the double quotes as I see that's a repeating occurrence in your examples and take the second item in the split array:
var path = new Regex("\"").Split(s)[1];
This is and update to your logic without using any Regex:
private string prepareStr(string itemToPrepare)
{
string result = null;
string startString = #"\""";
string endString = #"\""";
int startPoint = itemToPrepare.IndexOf(startString);
if (startPoint >= 0)
{
startPoint = startPoint + startString.Length;
int EndPoint = itemToPrepare.IndexOf(endString, startPoint);
if (EndPoint >= 0)
{
result = itemToPrepare.Substring(startPoint, EndPoint - startPoint);
}
}
return result;
}

C# List & Sort URLs by FileName

I want to make this:
anywhere.com/file/mybirthday.avi
anywhere.com/file/yourbirthday.avi
somewhere.com/file/mybirthday.avi
somewhere.com/file/yourbirthday.avi
To This:
anywhere.com/file/mybirthday.avi
somewhere.com/file/mybirthday.avi
##############
anywhere.com/file/yourbirthday.avi
somewhere.com/file/yourbirthday.avi
I found filenames with regex. And I sorted them. So my codes are here:
private void button1_Click(object sender, EventArgs e)
{
string gelenler = textBox2.Text;
gelenler = gelenler.Replace("\r\n\r\n", "\r\n");
string cikti = string.Empty;
string regex = #"([^\/\\]+\.\w+)$";
string[] parca = Regex.Split(gelenler, "\r\n");
string[] parca2 = new string[parca.Length];
for (int i = 0; i < parca.Length; i++)
{
string ad = match(regex, parca[i]);
parca2[i] = ad;
}
Array.Sort(parca2);
for (int j = 0; j < parca2.Length; j++)
{
for (int i = 0; i < parca2.Length; i++)
{
if (parca2[i].IndexOf(match(regex,parca[j]))!=-1)
{
textBox1.Text += parca[i] + Environment.NewLine;
parca[i] = "";
}
textBox1.Text += "#############" + Environment.NewLine;
}
}
}
private string match(string regex, string html, int i = 1)
{
return new Regex(regex, RegexOptions.Multiline).Match(html).Groups[i].Value.Trim();
}
But didn't working. Any ideas ?
//Sorry my English
I think always the best idea is to use existing .net framework stuff, as in this case Path.GetFileName:
var strings = new[]
{
"anywhere.com/file/mybirthday.avi",
"anywhere.com/file/yourbirthday.avi",
"somewhere.com/file/mybirthday.avi",
"somewhere.com/file/yourbirthday.avi"
};
strings = strings.OrderBy(x => Path.GetFileName(x)).ToArray();
foreach (var s in strings)
{
Console.WriteLine(s);
}
Console.ReadKey();
I think you mean grouping the files; in which case the following code can be used:
IEnumerable<IGrouping<string, string>> groups = strings.GroupBy(x => Path.GetFileName(x)).OrderBy(g => g.Key);
foreach (var group in groups)
{
foreach (var str in group)
{
Console.WriteLine(str);
}
Console.WriteLine("#############");
}
You should use the Uri class. Use the Segements property in order to get the file name (it will be the last segment).
var uris = new[]
{
new Uri("http://anywhere.com/file/mybirthday.avi"),
new Uri("http://anywhere.com/file/yourbirthday.avi"),
new Uri("http://somewhere.com/file/mybirthday.avi"),
new Uri("http://somewhere.com/file/yourbirthday.avi")
};
var filename = uris.OrderBy(x => x.Segments[x.Segments.Length - 1]).ToArray();
foreach (var f in filename)
{
Console.WriteLine(f);
}

Getting rid of *consecutive* periods in a filename

I was wondering how I'd get rid of periods in a filename if i have a filename like:
Test....1.txt to look like Test 1.txt ? I do NOT want files like : 1.0.1 Test.txt to be touched. Only files with consecutive periods should be replaced with a space. Any ideas?
This is my current code but as you can see, it replaces every period aside from periods in extension names:
public void DoublepCleanUp(List<string> doublepFiles)
{
Regex regExPattern2 = new Regex(#"\s{2,}");
Regex regExPattern4 = new Regex(#"\.+");
Regex regExPattern3 = new Regex(#"\.(?=.*\.)");
string replace = " ";
List<string> doublep = new List<string>();
var filesCount = new Dictionary<string, int>();
try
{
foreach (string invalidFiles in doublepFiles)
{
string fileOnly = System.IO.Path.GetFileName(invalidFiles);
string pathOnly = System.IO.Path.GetDirectoryName(fileOnly);
if (!System.IO.File.Exists(fileOnly))
{
string filewithDoublePName = System.IO.Path.GetFileName(invalidFiles);
string doublepPath = System.IO.Path.GetDirectoryName(invalidFiles);
string name = System.IO.Path.GetFileNameWithoutExtension(invalidFiles);
//string newName = name.Replace(".", " ");
string newName = regExPattern4.Replace(name, replace);
string newName2 = regExPattern2.Replace(newName, replace);
string filesDir = System.IO.Path.GetDirectoryName(invalidFiles);
string fileExt = System.IO.Path.GetExtension(invalidFiles);
string fileWithExt = newName2 + fileExt;
string newPath = System.IO.Path.Combine(filesDir, fileWithExt);
System.IO.File.Move(invalidFiles, newPath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = doublepPath;
clean.Cells[1].Value = filewithDoublePName;
clean.Cells[2].Value = fileWithExt;
dataGridView1.Rows.Add(clean);
}
else
{
if (filesCount.ContainsKey(fileOnly))
{
filesCount[fileOnly]++;
}
else
{
filesCount.Add(fileOnly, 1);
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(fileOnly),
filesCount[fileOnly].ToString(),
System.IO.Path.GetExtension(fileOnly));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fileOnly), newFileName);
System.IO.File.Move(fileOnly, newFilePath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = fileOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
}
catch(Exception e)
{
//throw;
StreamWriter doublepcleanup = new StreamWriter(#"G:\DoublePeriodCleanup_Errors.txt");
doublepcleanup.Write("Double Period Error: " + e + "\r\n");
doublepcleanup.Close();
}
}
string name = "Text...1.txt";
Regex r = new Regex("[.][.]+");
string result = r.Replace(name, " ");
Well, to do that with a string:
string st = "asdf..asdf...asfd...asdf.asf.asdf.s.s";
Regex r = new Regex("\\.\\.+");
st = r.Replace(st, " ");
This will replace any instance of 2 or more '.'s with a space.
I would throw this into a method:
public static string StringReplace(string original,
string regexMatch, string replacement) {
Regex r = new Regex(regexMatch);
return r.Replace(original, replacement);
}
How about this?
string newFileName = String.Join(".", fileName.Split('.').Select(p => !String.IsNullOrEmpty(p) ? p : " ").ToArray())
Why not use something like this?
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", " ");
static string CleanUpPeriods(string filename)
{
StringBuilder sb = new StringBuilder();
if (filename.Length > 0) sb.Append(filename[0]);
for (int i = 1; i < filename.Length; i++)
{
char last = filename[i - 1];
char current = filename[i];
if (current != '.' || last != '.') sb.Append(current);
}
return sb.ToString();
}
You could use use regular expressions, something like this
string fileName = new Regex(#"[.][.]+").Replace(oldFileName, "");
Continuing from dark_charlie's solution, isn't
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", ".");
enough?
I have tested this code on a number of cases, and it appears to exhibit the requested behavior.
private static string RemoveExcessPeriods(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
// If there are no consecutive periods, then just get out of here.
if (!text.Contains(".."))
return text;
// To keep things simple, let's separate the file name from its extension.
string extension = Path.GetExtension(text);
string fileName = Path.GetFileNameWithoutExtension(text);
StringBuilder result = new StringBuilder(text.Length);
bool lastCharacterWasPeriod = false;
bool thisCharacterIsPeriod = fileName.Length > 0 && fileName[0] == '.';
bool nextCharacterIsPeriod;
for (int index = 0; index < fileName.Length; index++)
{
// Includes both the extension separator and other periods.
nextCharacterIsPeriod = fileName.Length == index + 1 || fileName[index + 1] == '.';
if (!thisCharacterIsPeriod)
result.Append(fileName[index]);
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod && !nextCharacterIsPeriod)
result.Append('.');
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod)
result.Append(' ');
lastCharacterWasPeriod = thisCharacterIsPeriod;
thisCharacterIsPeriod = nextCharacterIsPeriod;
}
return result.ToString() + extension;
}
I just made a change to handle some edge cases. Here are some test results for this version.
"Test....1.txt" => "Test 1.txt"
"1.0.1..Test.txt" => "1.0.1 Test.txt"
"Test......jpg" => "Test .jpg"
"Test.....jpg" => "Test .jpg"
"one.pic.jpg" => "one.pic.jpg"
"one..pic.jpg" => "one pic.jpg"
"one..two..three.pic.jpg" => "one two three.pic.jpg"
"one...two..three.pic.jpg" => "one two three.pic.jpg"
"one..two..three.pic..jpg" => "one two three.pic .jpg"
"one..two..three..pic.jpg" => "one two three pic.jpg"
"one..two..three...pic...jpg" => "one two three pic .jpg"
Combining some other answers...
static string CleanUpPeriods(string filename)
{
string extension = Path.GetExtension(filename);
string name = Path.GetFileNameWithoutExtension(filename);
Regex regex = new Regex(#"\.\.+");
string s = regex.Replace(name, " ").Trim();
if (s.EndsWith(".")) s = s.Substring(0, s.Length - 1);
return s + extension;
}
Sample Output
"Test........jpg" -> "Test.jpg"
"Test....1.jpg" -> "Test 1.jpg"
"Test 1.0.1.jpg" -> "Test 1.0.1.jpg"
"Test..jpg" -> "Test.jpg"
void ReplaceConsecutive(string src, int lenght, string replace)
{
char last;
int count = 0;
StringBuilder ret = new StringBuilder();
StringBuilder add = new StringBuilder();
foreach (char now in src)
{
if (now == last)
{
add.Append(now);
if (count > lenght)
{
ret.Append(replace);
add = new StringBuilder();
}
count++;
}
else
{
ret.Append(add);
add = new StringBuilder();
count = 0;
ret.Append(now);
}
}
return ret.ToString();
}
Untested, but this should work.
src is the string you want to check for consecutives, lenght is the number of equal chars followed by each other until they get replaced with replace.
This is AFAIK also possible in Regex, but I'm not that good with Regex's that I could do this.

C#: what is the simplest way to sort the directory names and pick the most recent one?

I have a list of directories in a parent directory. These directories will be created in a format like 00001, 00002, 00003... so that the one with the bigger trailing number is the recent one. in the above instance, it is 00003. I want to get this programmatically.
thanks for any help..
Try this:
var first = Directory.GetDirectories(#"C:\")
.OrderByDescending(x => x).FirstOrDefault();
Obviously replace C:\ with the path of the parent directory.
.NET 2:
private void button1_Click(object sender, EventArgs e) {
DirectoryInfo di = new DirectoryInfo(#"C:\Windows");
DirectoryInfo[] dirs = di.GetDirectories("*",
SearchOption.TopDirectoryOnly);
Array.Sort<DirectoryInfo>(dirs,
new Comparison<DirectoryInfo>(CompareDirs);
}
int CompareDirs(DirectoryInfo a, DirectoryInfo b) {
return a.CreationTime.CompareTo(b.CreationTime);
}
Why not do something like this:
string[] directories = Directory.GetDirectories(#"C:\temp");
string lastDirectory = string.Empty;
if (directories.Length > 0)
{
Array.Sort(directories);
lastDirectory = directories[directories.Length - 1];
}
What about:
var greaterDirectory =
Directory.GetDirectories(#"C:\")
.Select(path => Path.GetFileName(path)) // keeps only directory name
.Max();
or
var simplest = Directory.GetDirectories(#"C:\").Max();
Just throw the output of GetDirectories or GetFiles at a bubble sort function.
private void SortFiles(FileSystemInfo[] oFiles)
{
FileSystemInfo oFileInfo = null;
int i = 0;
while (i + 1 < oFiles.Length)
{
if (string.Compare(oFiles[i].Name, oFiles[i + 1].Name) > 0)
{
oFileInfo = oFiles[i];
oFiles[i] = oFiles[i + 1];
oFiles[i + 1] = oFileInfo;
if (i > 0)
{
i--;
}
}
else
{
i++;
}
}
}

Categories