Path.Combine() returns unexpected results - c#

I'm trying to create a path using Path.Combine() but I am getting unexpected results.
using System;
using System.IO;
namespace PathCombine_Delete
{
class Program
{
static void Main(string[] args)
{
string destination = "D:\\Directory";
string destination02 = "it";
string path = "L:\\MyFile.pdf";
string sourcefolder = "L:\\";//In other instances, it could be L:\\SomeFolder\AndMayBeAnotherFolder
string replacedDetails = path.Replace(sourcefolder + "\\", "");
string result = Path.Combine(destination, destination02, replacedDetails);
Console.WriteLine(result);
Console.ReadKey();//Keep it on screen
}
}
}
I would expect the result D:\\Directory\it\MyFile.pdf but instead, I get L:\MyFile.pdf
I can't see why? I admit it's late in the evening here, but still, I've used Path.Combine many times, and since .NET 4.0 it allows the string param to be passed. However, it appears to be ignoring the first 2 and only reading the last.

Here is the error
string replacedDetails = path.Replace(sourcefolder + "\\" , "");
You are adding another backslash and nothing is found to be replaced.
Removing the added backslash gives the correct string to search for and replace
string replacedDetails = path.Replace(sourcefolder , "");
however you could avoid all that replace stuff and intermediate variables just with
string result = Path.Combine(destination, destination02, Path.GetFileName(path));

I would recommend using:
string replacedDetails = Path.GetFileName(path);
That will handle removing the source folder from the path without using string replacement, which isn't necessarily reliable if you're getting the path from elsewhere (eventually).

Have you read the documentation? Have you verified what you're passing to Path.Combine()? The documentation says, and I quote:
path1 should be an absolute path (for example, "d:\archives" or "\archives\public").
If path2 or path3 is also an absolute path, the combine operation discards all
previously combined paths and resets to that absolute path.
That should hint at the problem.

Related

Remove Extra back slash "\" from string file path in c#

How to convert
"String path = #"C:\Abc\Omg\Why\Me\\\\\\\\\\\\\\\\\\\\\";
into
String path = #"C:\Abc\Omg\Why\Me\".
My approach is to first reverse the string and then remove all the "\" till we get first char, and the reverse it again.
How to do this in C#, is there any method for such operation?
You can just construct path using the Path static class:
string path = Path.GetFullPath(#"C:\Abc\Omg\Why\Me\\\\\\\\\\\\\\\\\\\\\");
After this operation, variable path will contain the minimal version:
C:\Abc\Omg\Why\Me\
You can use path.TrimEnd('\\'). Have a look at the documentation for String.TrimEnd.
If you want the trailing slash, you can add it back easily.
var path = #"C:\Abc\Omg\Why\Me\\\\\\\\\\\\\\\\\\\\\";
path = path.TrimEnd('\\') + '\\';
another solution is
var path = #"C:\Abc\Omg\Why\Me\\\\\\\\\\\\\\\\\\\\\";
path = Path.GetFullPath(path);

Combining two relative paths with C#

There are many dupes for "appending a relative path to an absolute path", but I need to add relative to relative.
e.g.:
Path1 = "Parent/Child/a.txt"
Path2 = "../Sibling/file.cs"
Result = "Parent/Sibling/file.cs"
Tried:
Directory.GetParent() - works, but I can't find a way to return the result (it can only return absolute paths)
Path.Combine() - only works for simple cases and absolute paths. Fails (badly!) on the use of ".." with relative paths
...it seems absurd to write a string-tokenizing Path class to solve this, but I've been digging through the MSDN docs and can't seem to find a working Path/Directory class that correctly works with relative paths.
To make matters worse ... I'm trying to make this work all the way back to .NET 2 (thanks to Mono compatibilty)
I know the following code is ugly but will work (sorry I don't confirm on mono yet):
var Result =
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Path1), Path2))
.Substring(Directory.GetCurrentDirectory().Length + 1); // +1 to remove leading path separator
I'm not sure why you say Path.Combine fails badly, since you don't give any examples of what you've tried. But Path.Combine does exactly what you're looking for. You do have to give it a little help in this case; your first path is a filename, and you need the directory.
var filePath1 = "Parent/Child/a.txt";
var filePath2 = "../Sibling/file.cs";
var baseDirectory = Path.GetDirectoryName(filePath1);
var result = Path.Combine(baseDirectory, filePath2);
This returns "Parent\Child\../Sibling/file.cs" rather than the "Parent/Sibling/file.cs" you're looking for, but the two paths are exactly equivalent.
I tried this on Windows, it should work on Mac OS (Mono/Xamarin) or Linux (Mono) but you might need a different value for the dummyDriveLetter variable.
static void Main(string[] args)
{
string Path1 = "Parent/Child/a.txt";
string Path2 = "../Sibling/file.cs";
string dummyDriveLetter = "C:/"; // must be an absolute path, so let's add a dummy prefix, works on Windows
string absolutePath1 = dummyDriveLetter + Path1;
var path1Uri = new Uri(absolutePath1, UriKind.Absolute);
var path2Uri = new Uri(Path2, UriKind.Relative);
var diff = new Uri(path1Uri, path2Uri);
string Result = diff.OriginalString.Replace(dummyDriveLetter, "");
Console.WriteLine(Result);
}

How do I verify that a string supplied file path is in a valid directory format?

I have a reasonably straight-forward question here but I seem to find myself revisiting each time I have to deal with the validation of file paths and names. So I'm wondering if there is a method available in System.IO or some other library in the framework that can make my life easier!?
Lets take the contrived example of a method that takes a file path and a filename and from these inputs it formats and returns unique full file-location.
public string MakeFileNameUnique(string filePath, string fileName)
{
return filePath + Guid.NewGuid() + fileName;
}
I know that I must do the following to get the path in a correct format so that I can append the guid and filename:
if filePath is null or empty then throw exception
if filePath does not exist then throw exception
if no valid postfixed '/' then add one
if it contains a postfixed '\' then remove and replace with a '/'
Can someone tell me if there is a framework method that can do this(particularly the forwareslash/backslash logic) available to achieve this repetitive logic?
Are you looking for the Path.Combine method:
public string MakeFileNameUnique(string filePath, string fileName)
{
return Path.Combine(filePath, Guid.NewGuid().ToString(), fileName);
}
but looking at the name of your method (MakeFileNameUnique), have you considered using the Path.GenerateRandomFileName method? Or the Path.GetTempFileName method?
Following your requirements this will do
public string MakeFileNameUnique(string filePath, string fileName)
{
// This checks for nulls, empty or not-existing folders
if(!Directory.Exists(filePath))
throw new DirectoryNotFoundException();
// This joins together the filePath (with or without backslash)
// with the Guid and the file name passed (in the same folder)
// and replace the every backslash with forward slashes
return Path.Combine(filePath, Guid.NewGuid() + "_" + fileName).Replace("\\", "/");
}
a call with
string result = MakeFileNameUnique(#"d:\temp", "myFile.txt");
Console.WriteLine(result);
will result in
d:/temp/9cdb8819-bdbc-4bf7-8116-aa901f45c563_myFile.txt
However I wish to know the reason about the replace for the backslash with forward slashes

How to get the second to last directory in a path string in C#

For example,
string path = #"C:\User\Desktop\Drop\images\";
I need to get only #"C:\User\Desktop\Drop\
Is there any easy way of doing this?
You can use the Path and Directory classes:
DirectoryInfo parentDir = Directory.GetParent(Path.GetDirectoryName(path));
string parent = parentDir.FullName;
Note that you would get a different result if the path doesn't end with the directory-separator char \. Then images would be understood as filename and not as directory.
You can also use a subsequent call of Path.GetDirectoryName
string parent = Path.GetDirectoryName(Path.GetDirectoryName(path));
This behaviour is documented here:
Because the returned path does not include the DirectorySeparatorChar
or AltDirectorySeparatorChar, passing the returned path back into the
GetDirectoryName method will result in the truncation of one folder
level per subsequent call on the result string. For example, passing
the path "C:\Directory\SubDirectory\test.txt" into the
GetDirectoryName method will return "C:\Directory\SubDirectory".
Passing that string, "C:\Directory\SubDirectory", into
GetDirectoryName will result in "C:\Directory".
This will return "C:\User\Desktop\Drop\" e.g. everything but the last subdir
string path = #"C:\User\Desktop\Drop\images";
string sub = path.Substring(0, path.LastIndexOf(#"\") + 1);
Another solution if you have a trailing slash:
string path = #"C:\User\Desktop\Drop\images\";
var splitedPath = path.Split('\\');
var output = String.Join(#"\", splitedPath.Take(splitedPath.Length - 2));
var parent = "";
If(path.EndsWith(System.IO.Path.DirectorySeparatorChar) || path.EndsWith(System.IO.Path.AltDirectorySeparatorChar))
{
parent = Path.GetDirectoryName(Path.GetDirectoryName(path));
parent = Directory.GetParent(Path.GetDirectoryName(path)).FullName;
}
else
parent = Path.GetDirectoryName(path);
As i commented GetDirectoryName is self collapsing it returns path without tralling slash - allowing to get next directory.Using Directory.GetParent for then clouse is also valid.
Short Answer :)
path = Directory.GetParent(Directory.GetParent(path)).ToString();
Example on the bottom of the page probably will help:
http://msdn.microsoft.com/en-us/library/system.io.path.getdirectoryname(v=vs.110).aspx
using System;
namespace Programs
{
public class Program
{
public static void Main(string[] args)
{
string inputText = #"C:\User\Desktop\Drop\images\";
Console.WriteLine(inputText.Substring(0, 21));
}
}
}
Output:
C:\User\Desktop\Drop\
There is probably some simple way to do this using the File or Path classes, but you could also solve it by doing something like this (Note: not tested):
string fullPath = "C:\User\Desktop\Drop\images\";
string[] allDirs = fullPath.split(System.IO.Path.PathSeparator);
string lastDir = allDirs[(allDirs.length - 1)];
string secondToLastDir= allDirs[(allDirs.length - 2)];
// etc...

The SaveAs method is configured to require a rooted path, and the path 'fp' is not rooted

I am doing Image uploader in Asp.net and I am giving following code under my controls:
string st;
st = tt.PostedFile.FileName;
Int32 a;
a = st.LastIndexOf("\\");
string fn;
fn = st.Substring(a + 1);
string fp;
fp = Server.MapPath(" ");
fp = fp + "\\";
fp = fp + fn;
tt.PostedFile.SaveAs("fp");
But during uploading or saving image the error message comes that The SaveAs method is configured to require a rooted path, and the path 'fp' is not rooted.
So Please help me what is the problem
I suspect the problem is that you're using the string "fp" instead of the variable fp. Here's the fixed code, also made (IMO) more readable:
string filename = tt.PostedFile.FileName;
int lastSlash = filename.LastIndexOf("\\");
string trailingPath = filename.Substring(lastSlash + 1);
string fullPath = Server.MapPath(" ") + "\\" + trailingPath;
tt.PostedFile.SaveAs(fullPath);
You should also consider changing the penultimate line to:
string fullPath = Path.Combine(Server.MapPath(" "), trailingPath);
You might also want to consider what would happen if the posted file used / instead of \ in the filename... such as if it's being posted from Linux. In fact, you could change the whole of the first three lines to:
string trailingPath = Path.GetFileName(tt.PostedFile.FileName));
Combining these, we'd get:
string trailingPath = Path.GetFileName(tt.PostedFile.FileName));
string fullPath = Path.Combine(Server.MapPath(" "), trailingPath);
tt.PostedFile.SaveAs(fullPath);
Much cleaner, IMO :)
Use Server.MapPath():
fileUploader.SaveAs(Server.MapPath("~/Images/")+"file.jpg");
If you want to save the uploaded file to the value of fp, just pass it in, don't put it in quotes:
tt.PostedFile.SaveAs(fp);
When reading the title of the question, I was thinking that it looked like you had put quotation marks around the variable name. Not really believing that it was so, I opened the question to read it, but it really was so...
We cannot use the "SaveAs" method to write directly to an FTP server.
Only local paths and UNC paths are supported for the above method.
To save it to FTP, please use the FtpWebRequest class.
You will get the full details to this in the same type of question answer in social.msdn.
Please go through the link.. and you will be able to solve the issue..
enter link description here
--thanks for the answer by Jesse HouwingXPirit (MCC, Partner, MVP)
I encountered the same problem. The problem is that you did not specify the path of the server that you want the file to be saved. And here is a probably simpler answer:
string fileName = tt.PostedFile.FileName;
string savePath = Server.MapPath("Path/Of/The/Folder/Comes/Here/") + fileName);
tt.PostedFile.SaveAs(savePath);

Categories