Can't get my head round relative path - c#

This is probably something mind-numbingly obvious, but I'm new to c# so be gentle...
I have an application which (in theory) parses a text file into an array. Despite the text file being a peer of the aspx file I can't get the relative path right. Don't know if it makes any difference (I'd assume not) but I'm using code-behind.
My folder structure looks like this:
default.aspx
default.aspx.cs
default.aspx.designer.cs
album.cs
albums.txt
web.config
And this is the code I'm using:
protected void Page_Load(object sender, EventArgs e)
{
string[] allLines = File.ReadAllLines(#"Albums.txt");
Album[] Albums = new Album[allLines.Length];
for (int i = 0; i < allLines.Length; i++)
{
string[] lineSplit = allLines[i].Split(',');
Albums[i] = new Album();
Albums[i].ID = Convert.ToInt32(lineSplit[0]);
Albums[i].title = lineSplit[1];
Albums[i].keyName = lineSplit[2];
}
}
However, when I build it I get an error saying albums.txt can not be found, and it fails.
Any pointers would be greatly appreciated.
Ben

Server.MapPath specifies the relative or virtual path to map to a physical directory.
* Server.MapPath(".") returns the current physical directory of the file (e.g. aspx) being executed
* Server.MapPath("..") returns the parent directory
* Server.MapPath("~") returns the physical path to the root of the application
* Server.MapPath("/") returns the physical path to the root of the domain name (is not necessarily the same as the root of the application)
An example:
Let's say you pointed a web site application (http://www.example.com/) to
C:\Inetpub\wwwroot
and installed your shop application (sub web as virtual directory in IIS, marked as application) in
D:\WebApps\shop
If, for example, you call Server.MapPath in following request:
http://www.example.com/shop/product/GetProduct.aspx?id=2342
then,
* Server.MapPath(".") returns D:\WebApps\shop\products
* Server.MapPath("..") returns D:\WebApps\shop
* Server.MapPath("~") returns D:\WebApps\shop
* Server.MapPath("/") returns C:\Inetpub\wwwroot
* Server.MapPath("/shop") returns D:\WebApps\shop
If Path starts with either a forward (/) or backward slash (), the MapPath method returns a path as if Path were a full, virtual path.
If Path doesn't start with a slash, the MapPath method returns a path relative to the directory of the request being processed.
Note: in C#, # is the verbatim literal string operator meaning that the string should be used "as is" and not be processed for escape sequences.
Server.MapPath("."), Server.MapPath("~"), Server.MapPath(#"\"), Server.MapPath("/"). What is the difference?

Instead of just the filename, use Server.MapPath(filename) to get the full path to the file.
If the file is located in a different directory, you could use Server.MapPath("~/path/to/the/file.txt"), where ~ corresponds to the root folder of your web application.

ReadAllLines takes an absolute path - what you've provided is a relative path. Server.MapPath is used to translate relative paths to absolute ones. Server.MapPath("~/Albums.txt") would give the right value irrespective of where the code resides. Also, by putting the file under ~\App_Data\ you can prevent direct downloads of the file itself as well as insulating the application against repeated updates to that file while the application is running (updates to App_Data contents don't generate File Change Notifications).

Related

C# get absolute path from `~` on Unix-like systems

I'm building a C# app on Mac OS. It receives any path as an input and have to save a file by this path. The problem I faced is with paths relative to user directory, specified as ~.
I'm using following code using var s = File.Create(path); and there are few possibilities path parameter could be:
provided relative path e.g. filename.txt or ../filename.txt - it works and creates this file relative to current working directory.
provided absolute path e.g. /Users/username/Desktop/filename.txt - also works as expected
but providing path relative to user directory e.g. ~/Desktop/filename.txt - does not work. In this case File.Create is trying to combine absolute path like in case 1. It takes current working dir and simply adds my path like this /Users/username/project/~/Desktop/filename.txt. Which does not exist.
I tried to get absolute path from ~/Desktop with Path.GetFullPath("~/Desktop/filename.txt"). It results to the same /Users/username/project/~/Desktop/filename.txt. Same with Path.GetRelativePath("/", "~/Desktop/filename.txt");
Path.GetRelativePath("./", "~/Desktop/filename.txt"); returns not changed result.
Then tried Path.GetPathRoot("~/Desktop/filename.txt"). It gives just an empty string.
So the question, how in C# on Unix like host convert relative path like this ~/Desktop to absolute path like this /Users/username/Desktop?
You have to determine if the path starts with ~/ and, if it does, replace it with the path of the home directory. Here is a method that can do that:
public static string GetPath(string path) =>
(path.Length >= 2 && path.StartsWith("~/"))
? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), path.Substring(2))
: path;
Use it like this: GetPath("~/Desktop/filename.txt"). This will return /Users/username/Desktop/filename.txt (provided that your home directory is /Users/username).

How to locate relative file path when using GetFiles() in C#?

I've found a few related questions but they're not working that well. The image name is a modified GUID like 3c6b4a9b-8e88-4c8e-93da-258acd2c964f_0 but the extension isn't known (.jpg, .gif, ..etc). The GUID will be coming from a gridview so it's not a static string. Below is what I have but I'm having a difficult time getting the path to work correctly.
string fileName = `3c6b4a9b-8e88-4c8e-93da-258acd2c964f`;
DirectoryInfo filePath = new DirectoryInfo(#"/Images");
MessageBox.Show(filePath.ToString());
FileInfo[] fileArray = filePath.GetFiles(fileName + "_0.*");
Keep getting issues with the directory being invalid. Currently the files are stored on my c: drive.
How can I get the relative path without hardcoding it in? I was using DirectoryInfo(Server.MapPath("Images")); which worked temporarily then started giving this error System.ArgumentException: Second path fragment must not be a drive or UNC name. which seems to be from the path having the drive "C:" This doesn't seem to be a permanent solution once the site is launched though.
The actual path is C:\Website\Name\Images\3c6b4a9b-8e88-4c8e-93da-258acd2c964f_0.jpg
Thanks!
You've used filePath as the first parameter to GetFiles, just use the wildcard and invoke the overload of GetFiles with one parameter.
filePath.GetFiles("_0.*");
The problem is that you are getting DirectoryInfo for "C:\Images".
You want to use Server.MapPath to get the physical path to the folder that is in your website (which could be anywhere on any drive).
Using the ~ means to start from the root of the running website.
So this should do the trick:
string fileName = `3c6b4a9b-8e88-4c8e-93da-258acd2c964f`;
DirectoryInfo filePath = new DirectoryInfo(Server.MapPath("~/Images"));
FileInfo[] fileArray = filePath.GetFiles(fileName + "_0.*");

How to get a file full path in c# with Path.GetFullPath

I am trying to get the full path a file by its name only.
I have tried to use :
string fullPath = Path.GetFullPath("excelTest");
but it returns me an incorrect path (something with my project path).
I have read somewhere here a comment which says to do the following:
var dir = Environment.SpecialFolder.ProgramFilesX86;
var path = Path.Combine(dir.ToString(), "excelTest.csv");
but I do not know where the file is saved , therefore I do not know its environment.
can someone help me how to get the full path of a file only by its name?
The first snippet (with Path.GetFullPath) does exactly what you want. It returns something with your project path because the program EXE file is located in the project\Bin\Debug path, which is therefore the "current directory".
If you want to search for a file on a drive, you can use Directory.GetFiles, which will recursively search for a file in a directory given a name pattern.
This returns all xml-files recursively :
var allFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories);
http://msdn.microsoft.com/en-us/library/ms143316%28v=vs.100%29.aspx
http://msdn.microsoft.com/en-us/library/ms143448.aspx#Y252
https://stackoverflow.com/a/9830162/2196124
I guess you're trying to find file (like in windows search), right ?
I'd look into this question - you will find all files that has that string in their filename, and from there you can return full filepath.
var fileList = new DirectoryInfo(#"c:\").GetFiles("*excelTest*", SearchOption.AllDirectories);
And then just use foreach to do you manipulations, e.g.
foreach(string file in fileList)
{
// MessageBox.Show(file);
}
What you're looking for is Directory.GetFiles(), you can read up on it here. The gist of it is, you'll pass in the file path and the file name, and you'll get a string array back. In this instance, you can assume top level with C:\. It should be noted, that if nothing is found, the string array will be empty.
You have passed a relative file name to Path.GetFullPath. Microsoft documentation states:
If path is a relative path, GetFullPath returns a fully qualified path that can be based on the current drive and current directory. The current drive and current directory can change at any time as an application executes. As a result, the path returned by this overload cannot be determined in advance.
You cannot get the same full path name from a relative path unless your current directory is the same each time you invoke the function.

Get absolute path from relative path c#

I have a file in a folder somewhere on my computer and I have a second file where the relative path to the first file is noticed.
Now I want to figure out the absolute path.
GetFullPath doesn't work because the second file is not in the directory where the program runs.
Is there an opportunity to say from which directory the "GetFullPath" function should start, to get the right absolute path?
You can use the static methods of Path to calculate the resulting path:
string fullPathToSecondFile = "c:\\test\\subtestsecond\\secondfile.txt";
string relativePath = "..\\subtestfirst\\firstfile.txt";
string fullPathToFirstFile = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(fullSecondPath), relativePath));
This results in c:\test\subtestfirst\firstfile.txt
What happens is that you combine a relative path to a absolute one. This results in c:\test\subtestsecond\..\subtestfirst\firstfile.txt.
In the second step Path.GetFullPath() normalizes the string to the result shown above.

File.Delete isn't working to delete image from sub folder

In our ASP.NET program a user can upload an image to a folder. The location of the image (including the name of the upload folder which is in the root directory) is stored as a variable called "path", ie. "Uploads/fileName.jpg".
To remove the image:
if (File.Exists("~/" + path))
{
File.Delete("~/" + path);
}
However, it fails to run because it can't verify that the file exists. Through some testing we noticed it's looking for "path" in the "system32" directory. Why would this be?
You need to use Server.Map path to ensure that the Tilde is resolved correctly.
MSDN Article is here -> http://msdn.microsoft.com/en-us/library/ms524632(v=vs.90).aspx
Your code would become
var fixedPath = Server.MapPath("~/" + path);
if (File.Exists(fixedPath))
{
File.Delete(fixedPath);
}
The File class is not aware of the IIS directory mapping, so it won't understand ~ correctly. You have to first use a method to map the app relative path to a local path with Server.MapPath

Categories

Resources