.NET equivalents of Some Python Functions - c#

I am trying to port some Python code to .NET, and I was wondering if there were equivalents of the following Python functions in .NET, or some code snippets that have the same functionality.
os.path.split()
os.path.basename()
Edit
os.path.basename() in Python returns the tail of os.path.split, not the result of System.IO.Path.GetPathRoot(path)
I think the following method creates a suitable port of the os.path.split function, any tweaks are welcome. It follows the description of os.path.split from http://docs.python.org/library/os.path.html as much as possible I believe.
public static string[] PathSplit(string path)
{
string head = string.Empty;
string tail = string.Empty;
if (!string.IsNullOrEmpty(path))
{
head = Path.GetDirectoryName(path);
tail = path.Replace(head + "\\", "");
}
return new[] { head, tail };
}
I'm unsure about the way I'm returning the head and tail, as I didn't really want to pass out the head and tail via parameters to the method.

You're looking for the System.IO.Path Class.
It has many functions you can use to get the same functionality.
Path.GetDirectoryName(string)
For split, you'll probably want to use String.Split(...) on the actual path name. You can get the OS Dependant seperator by Path.PathSeparator.
In the case that im missing the point about os.path.split and you want the file name, use Path.GetFileName(string).
Please Note: You can explore all the members of the System.IO namespace by using the Object Browser (Ctrl+Alt+J) in Visual Studio. From here you go mscorlib -> System.IO and all the classes will be discoverable there.
It's like Intellisense on crack :)

os.path.basename()
The alternative is System.IO.Path.GetPathRoot(path);:
System.IO.Path.GetPathRoot("C:\\Foo\\Bar.xml") // Equals C:\\
Edit: The above returned the first path of the path, where basename should return the tail of the path. See the code below for an example of how this could be achieved.
os.path.split()
Unfortunately there's no alternative to this as there's no .Net equivalent. The closest you can find is System.IO.Path.GetDirectoryName(path), however if your path was C:\Foo, then GetDirectoryName would give you C:\Foo instead of C: and Foo. This would only work if you wanted to get the Directory Name of an actual file path.
So you'll have to write some code like the following to break these down for you:
public void EquivalentSplit(string path, out string head, out string tail)
{
// Get the directory separation character (i.e. '\').
string separator = System.IO.Path.DirectorySeparatorChar.ToString();
// Trim any separators at the end of the path
string lastCharacter = path.Substring(path.Length - 1);
if (separator == lastCharacter)
{
path = path.Substring(0, path.Length - 1);
}
int lastSeparatorIndex = path.LastIndexOf(separator);
head = path.Substring(0, lastSeparatorIndex);
tail = path.Substring(lastSeparatorIndex + separator.Length,
path.Length - lastSeparatorIndex - separator.Length);
}

Path.GetFileName
Path.GetDirectoryName
http://msdn.microsoft.com/en-us/library/beth2052.aspx
Should help

Why not just use IronPython and get the best of both worlds?

Related

C# cut file Name from Path

I am creating an Image Extraction tool and I am able to retrieve the Images with full path..
For Example:
I need to cut the File name (rss) from path...
I search posts and Tried following
//1.
//string str = s.Split('/', '.')[1];
//2.
string s1;
// string fileName = "abc.123.txt";
int fileExtPos = s.LastIndexOf(".");
if (fileExtPos >= 0)
s1 = s.Substring(0, fileExtPos);
//3.
//var filenames = String.Join(
// ", ",
// Directory.GetFiles(#"c:\", "*.txt")
// .Select(filename =>
//4.
// Path.GetFileNameWithoutExtension(filename)));
None seems to be working
I want the name between "images" and "png" ..What can be the exact code?
Any Suggestion will be helpful
Just use the class Path and its method GetFileNameWithoutExtension
string file = Path.GetFileNameWithoutExtension(s);
Warning: In this context (just the filename without extension and no arguments passed after the URL) the method works well, however this is not the case if you use other methods of the class like GetDirectoryName. In that context the slashes are reversed into Windows-style backslashes "\" and this could be an error for other parts of your program
Another solution, probably more WEB oriented is through the class Uri
Uri u = new Uri(s);
string file = u.Segments.Last().Split('.')[0];
but I find this a lot less intuitive and more error prone.
In your example you're using a uri so you should use System.Uri
System.Uri uri = new System.Uri(s);
string path = uri.AbsolutePath;
string pathWithoutFilename = System.IO.Path.GetDirectoryName(path);
Why use Uri? Because it will handle things like
http://foo.com/bar/file.png#notthis.png
http://foo.com/bar/file.png?key=notthis.png
http://foo.com/bar/file.png#moo/notthis.png
http://foo.com/bar/file.png?key=moo/notthis.png
http://foo.com/bar/file%2epng
Etc.
Here's a fiddle
You should use the various System.IO.Path functions to manipulate paths as they work cross platform. Similarly you should use the System.Uri class to manipulate Uris as it will handle all the various kinds of edge cases like escaped characters, fragments, query strings, etc.

Directory Exists with Path Combine vs String Concatenation

So as I am building a Folder/File checking conditional, and a co-worker says it is "better" to use Path.Combine:
string finalPath = Path.Combine(folder, "file.txt");
as opposed to the way I was doing it with
string finalPath = folder + "\\file.txt";
Any sound reasoning this is "better?"
It's an interesting question;
You could, of course, write something like:
string finalPath = String.Format("{0}\\file.txt", folder);
To achieve the result you want.
Using ILSpy, though, lets see why Path.Combine is better.
The overload you are calling is:
public static string Combine(string path1, string path2)
{
if (path1 == null || path2 == null)
{
throw new ArgumentNullException((path1 == null) ? "path1" : "path2");
}
Path.CheckInvalidPathChars(path1, false);
Path.CheckInvalidPathChars(path2, false);
return Path.CombineNoChecks(path1, path2);
}
The advantages are obvious; firstly, the function checks for null values and throws the appropriate exception. Then it checks for illegal characters in either of the arguments, and throws an appropriate exception. Once it is satisfied, it calls Path.CombineNoChecks:
private static string CombineNoChecks(string path1, string path2)
{
if (path2.Length == 0)
{
return path1;
}
if (path1.Length == 0)
{
return path2;
}
if (Path.IsPathRooted(path2))
{
return path2;
}
char c = path1[path1.Length - 1];
if (c != Path.DirectorySeparatorChar && c != Path.AltDirectorySeparatorChar && c != Path.VolumeSeparatorChar)
{
return path1 + Path.DirectorySeparatorChar + path2;
}
return path1 + path2;
}
The most interesting thing here are the characters it supports;
Path.DirectorySeparatorChar = "\\"
Path.AltDirectorySeparatorChar = "/"
Path.VolumeSeparatorChar = ":"
So it will also support paths where the separator is the wrong way around (like from a urn file://C:/blah, too)
In short, it's better because it gives you validation, a degree of portability (the 3 constants shown above can be defined on a per framework-OS basis), and has support for more than one type of path that you commonly encounter.
try these two to see the difference.... It can handle URI and standard paths. So always use Path.Combine.
Console.WriteLine(Path.Combine(#"file:///c:/temp/", "x.xml"));
Output file:///c:/temp/x.xml
Console.WriteLine(Path.Combine(#"C:\test", "x.xml"));
Output C:\test\x.xml
Yes, it's more portable in the case that the file-path separator is different to \
First you can use this notation #"\file.txt instead of "\\file.txt";
Second, let .Net care about fixing the path. There is a reason we have it.
You can be 100% sure that you've done it correctly but if you start combining paths by hand everywhere in your code, there is always a chance to create bugs.
A simple example.
User enters a path and you want to create a subfolder named temp there. What will you do?
If no backslash at the end, add one, else do this, otherwise do the other... etc.
With Path.Combine() you don't have to do checking. You can concentrate on the actual logic of your application.
One really could thing plus the other comments, it is the capability to combine many parts of the directory you want to create.
As an example is this:
Path.Combine(root, nextFolder, childfolder, file);
It supports many characters as it receives an array of string, so it is capable to create the right directory in one single executed line.
Regards,

Using Substring in C# reverse

And I have filepath say "\ABC\ABX\file.pdf".
How can I get only the folder path i.e. "\ABC\ABX\" using substring any other way.
Thank you in advance.
Use System.IO.Path class
var dir = Path.GetDirectoryName(#"\ABC\ABX\file.pdf");
You're looking for Path.GetDirectoryName
var directoryOnly = System.IO.Path.GetDirectoryName(#"\ABC\ABX\file.pdf")
Live example: http://rextester.com/WDVD42852
You can do this using a combination of Substring and LastIndexOf:
string path = #"\ABC\ABX\file.pdf";
string directory = path.Substring(0, path.LastIndexOf(#"\") + 1);
It would also be ideal to add a check to ensure that the path even contains a \, and because of the + 1 you would also want to check that the \ is not already the last character. Of course though, it would be better to not need such string manipulation in the first place, but I don't know what your exact scenario is
string result = test.Substring(0, test.LastIndexOf("\\") + 1);
There are nicer ways to do this using System.IO, but purely string manipulation:
string path = #"\ABC\ABX\file.pdf";
string folder = path.Substring(0, path.LastIndexOf(#"\"));

How to get folder/directory path from input?

How do you get the last folder/directory out of user-input regardless of if the input is a path to a folder or a file? This is when the folder/file in question may not exist.
C:\Users\Public\Desktop\workspace\page0320.xml
C:\Users\Public\Desktop\workspace
I'm trying to get out the folder "workspace" out of both examples, even if the folder "workspace" or file "page0320.xml" doesn't exist.
EDIT: Using BrokenGlass's suggestion, I got it to work.
String path = #"C:\Users\Public\Desktop\workspace";
String path2 = #"C:\Users\Public\Desktop\workspace\";
String path3 = #"C:\Users\Public\Desktop\workspace\page0320.xml";
String fileName = path.Split(new char[] { '\\' }).Last<String>().Split(new char[] { '/' }).Last<String>();
if (fileName.Contains(".") == false)
{
path += #"\";
}
path = Path.GetDirectoryName(path);
You can substitute any of the path variables and the output will be:
C:\Users\Public\Desktop\workspace
Of course, this is working under the assuption that files have extensions. Fortunately, that assumption works for my purposes.
Thanks all. Been a long-time lurker and first-time poster. It was really impressive how fast and helpful the responses were :D
use Path.GetDirectoryName :
string path = Path.GetDirectoryName(#"C:\Users\Public\Desktop\workspace\page0320.xml");
string path2 = Path.GetDirectoryName(#"C:\Users\Public\Desktop\workspace\");
Note the trailing backslash in the path though in the second example - otherwise workspace will be interpreted as file name.
I will use DirectoryInfo in this way:
DirectoryInfo dif = new DirectoryInfo(path);
if(dif.Exist == true)
// Now we have a true directory because DirectoryInfo can't be fooled by
// existing file names.
else
// Now we have a file or directory that doesn't exist.
// But what we do with this info? The user input could be anything
// and we cannot assume that is a file or a directory.
// (page0320.xml could be also the name of a directory)
You can use GetFileName after GetDiretoryName from the Path class in the System.IO namespace.
GetDiretoryName will get the path without the filename (C:\Users\Public\Desktop\workspace).
GetFileName then returns the last part of the path as if it is a extensionless file (workspace).
Path.GetFileName(Path.GetDirectoryName(path));
EDIT: the path must have a trailing path separator to make this example work.
If you can make some assumptions then its pretty easy..
Assumption 1: All files will have an extension
Assumption 2: The containing directory will never have an extension
If Not String.IsNullOrEmpty(Path.GetExtension(thePath))
Return Path.GetDirectoryName(thePath)
Else
Return Path.GetFileName(thePath)
End If
Like said before, there's not really a feasible solution but this might also do the trick:
private string GetLastFolder(string path)
{
//split the path into pieces by the \ character
var parts = path.Split(new[] { Path.DirectorySeparatorChar, });
//if the last part has an extension (is a file) return the one before the last
if(Path.HasExtension(path))
return parts[parts.Length - 2];
//if the path has a trailing \ return the one before the last
if(parts.Last() == "")
return parts[parts.Length - 2];
//if none of the above apply, return the last element
return parts.Last();
}
This might not be the cleanest solution but it will work. Hope this helps!

How to cut a string

I have a strings like
"/LM/W3SVC/1216172363/root/175_Jahre_STAEDTLER_Faszination_Schreiben"
And I need only "175_Jahre_STAEDTLER_Faszination_Schreiben" where "root" is separator. How can I do this?
"/LM/W3SVC/1216172363/root/175_Jahre_STAEDTLER_Faszination_Schreiben".Split("/root/")[1] should give you "175_Jahre_STAEDTLER_Faszination_Schreiben"
Another method:
String newstring = file_path.Substring(file_path.LastIndexOf('/') + 1);
Check out the System.IO.Path methods - not quite files and folders but with the / delimiter it just might work!
If you're looking to extract a part of a string based on an overall pattern, regular expressions can be a good alternative in some situations.
string s = "/LM/W3SVC/1216172363/root/175_Jahre_STAEDTLER_Faszination_Schreiben";
Regex re = new Regex(#"/root/(?<goodPart>\w+)$");
Match m = re.Match(s);
if (m.Success) {
return m.Groups["goodPart"].ToString();
}
string s = "/LM/W3SVC/1216172363/root/175_Jahre_STAEDTLER_Faszination_Schreiben";
string separator = "root";
string slash = "/";
int idx = s.IndexOf(separator);
string result = s.SubString(idx + separator.Length + slash.Length);
Use String.Split to separate the string with "root" as the separator. Then use the second element of the resulting array.
If you need to find a relative path based on a base path (which it sounds like what the problem you are trying to solve is, or at least a generalization of your problem) you can use the System.Uri class. It does have it's limitations, however. The cleanest and most correct way to find a relative path is to use DirectoryInfo. With DirectoryInfo you can "walk" the directory tree (backwards or forwards) and build a hierarchy based on that. Then just do a little set manipulation to filter out duplicates and what you have left is your relative path. There are some details, like adding ellipses in the correct place, etc..., but DirectoryInfo is a good place to start in order to parse paths based on the current OS platform.
FYI - I just finished writing a component here at work to do just that so it's fairly fresh in my mind.
string s = "/LM/W3SVC/1216172363/root/175_Jahre_STAEDTLER_Faszination_Schreiben";
int li = s.LastIndexOf("root/");
s = s.Substring(li + 5, s.Length - 1 - (li + 4));
MessageBox.Show(s);

Categories

Resources