c# open file, path starting with %userprofile% - c#

I have a simple problem. I have a path to a file in user directory that looks like this:
%USERPROFILE%\AppData\Local\MyProg\settings.file
When I try to open it as a file
ostream = new FileStream(fileName, FileMode.Open);
It spits error because it tries to add %userprofile% to the current directory, so it becomes:
C:\Program Files\MyProg\%USERPROFILE%\AppData\Local\MyProg\settings.file
How do I make it recognise that a path starting with %USERPROFILE% is an absolute, not a relative path?
PS: I cannot use
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Because I need to just open the file by its name. User specifies the name. If user specifies "settings.file", I need to open a file relative to program dir, if user specifies a path starting with %USERPROFILE% or some other thing that converts to C:\something, I need to open it as well!

Use Environment.ExpandEnvironmentVariables on the path before using it.
var pathWithEnv = #"%USERPROFILE%\AppData\Local\MyProg\settings.file";
var filePath = Environment.ExpandEnvironmentVariables(pathWithEnv);
using(ostream = new FileStream(filePath, FileMode.Open))
{
//...
}

Try using ExpandEnvironmentVariables on the path.

Use the Environment.ExpandEnvironmentVariables static method:
string fileName= Environment.ExpandEnvironmentVariables(fileName);
ostream = new FileStream(fileName, FileMode.Open);

I use this in my Utilities library.
using System;
namespace Utilities
{
public static class MyProfile
{
public static string Path(string target)
{
string basePath =
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) +
#"\Automation\";
return basePath + target;
}
}
}
So I can simply use e.g. "string testBenchPath = MyProfile.Path("TestResults");"

You can use the Environment.Username constant as well. Both of the %USERPROFILE% and this Environment variable points the same( which is the currently logged user). But if you choose this way, you have to concatenate the path by yourself.

Related

how to verify if an input read from console is a file name or a file full path

I have a console application in C# and I would like to load an xml file, the path to the file is provided via console.readline(). But, I would like to load the file from the provided path but if the user only provides the name of the file I would like to search for it in the local folder from where the application is running. How can I know when I get only a file name as an input or a file full path.
I managed that using: var isFileNameOnly = ((xmlFilePath.IndexOf("\\")) == -1);
But this ugly and probably very buggy.
Full code:
var xmlFilePath = Console.ReadLine();
var xmlFile = new XmlDocument();
var isFileNameOnly = ((xmlFilePath.IndexOf("\\")) == -1);
try
{
if (isFileNameOnly)
{
xmlFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlFilePath);
}
xmlFile.Load(xmlFilePath);
}
Thx
You can check if the file name entered by user actually exists using Exists() method. If it returns true load the file.
File.Exists(xmlFilePath)
Also XmlDocument.Load() if provided only file name will try to find the file in the BaseDirectory itself. So if file.Exists() return true you can assume XmlDocument.Load will load it whether it is local or absolute path.
This will return false:
bool isFolder = Path.IsPathRooted(#"Text.txt");
This will return true:
bool isFolder = Path.IsPathRooted(#"C:\Text");
Your approach is the same that I would have chosen. If the param doesn't contain any directory delimiter char, then it must be a filename only. Maybe it would be a little more elegant if you did it like this:
bool isFileNameOnly = !xmlFilePath.Contains(Path.DirectorySeparatorChar.ToString());

SSH.NET library encode the file name

I must download a file using SSH.NET library. After I download a file I must delete the remote file.
Everything works but the file name is encoded. I mean that for example, if I have a file named New file, I download/upload a file named New%20file. Now, if I download/upload the new file I obtain New%25%20file and again New%252520file... and so on...
This is very problematic. How can I avoid to change the file name after I download it?
Here the code I am using to download:
string fileName = base.Uri.GetFileName();
string fullPath = Path.Combine(pathFolder, fileName);
using (SftpClient client = new SftpClient(
new PasswordConnectionInfo(
base.Uri.Host, SftpFlowGateway.CONST_PORT_NUMBER,
base.Credential.UserName,
base.Credential.Password))
)
{
client.Connect();
using (FileStream fileStreamToDownload = new FileStream(fullPath, FileMode.Create))
{
client.DownloadFile(base.Uri.LocalPath, fileStreamToDownload);
}
client.Disconnect();
}
EDIT:
base.Uri is just defined as follow:
private Uri _uri;
public Uri Uri
{
get { return _uri; }
protected set { _uri = value; }
}
And the GetFileName method is:
public static string GetFileName(this Uri path)
{
return path.Segments.Last();
}
When I debug, I can see that the properties of the class Uri have the correct value... It is not encoded
Thank you
You are passing a stream you have created yourself (new FileStream) to the SSH.NET. The library does not even know it's a file it is writing to, nor its name. So it's not the library that URL-encodes the file name. It has to be URL-encoded in the fullPath variable already.
It's the Uri.AbsolutePath and Uri.Segments that return URL-encoded path. That's how the System.Uri class works. I assume you use the constructor overload Uri(string uriString).
Use the static method Uri.UnescapeDataString to reverse encoding done by the Uri constructor.
Note the obsoleted constructor overload Uri(string uriString, bool dontEscape).
It looks like the SSH.Net library simply URL encodes the file names.
I suppose you could rename the file after you've downloaded it using the System.Web.UrlDecode method?
Or UrlEncode the filename when you upload.
Unfortunately, I haven't used the library myself but you could help further by letting us know if the name change occurs on download or upload or both.
EDIT:
As martin mentioned, its not the library doing any encoding.
I've just tried it myself.
string fileName = "file with spaces.txt";
using (Stream outputFile = File.OpenWrite(localDir + "\\" + fileName))
{
sftpClient.DownloadFile(fileName, outputFile);
}
The created file is also named "file with spaces.txt" though that would've been the case anyway since it was created via the stream.

File is always named with the Path

My File is always named like the path and my additional informations i want to have in the Filename but why is it like that?
The Path should be the chosen folder and i want to create a folder then, how can i add a folder than and say + that folder path?
The file is also always created 1 layer above the one i want. For example: C:\Test but the file is saved then in C:\ instead of C:\Test.
public static string path= string.Empty;
string fileName = DateTime.Now.ToString("yyyy.MM.dd") + "test.txt";
try
{
FileStream fs = new FileStream(path + fileName, FileMode.CreateNew, FileAccess.ReadWrite);
StreamWriter sw= new StreamWriter(fs);
sw.WriteLine("Test and so on ..");
}
catch(Exception ex) { }
Rather than using string concatenation, use Path.Combine. Aside from anything else, that will be portable if you ever want to use Mono, too.
Oh, and there are simpler ways to create a text file too:
using (var writer = File.CreateText(Path.Combine(path, fileName))
{
writer.WriteLine(...);
}
Finally, I'd strongly advise using - instead of . in your filename, so that anything which looks at the first . and expects the rest to be an extension doesn't get confused:
string fileName = DateTime.ToString("yyyy-MM-dd") + "-test.txt";

Issue in File path

In my project there is a folder and in that folder there is text file. I want to read that text file
string FORM_Path = #"C:\Users\...\Desktop\FormData\Login.txt";
bool first = true;
string line;
try
{
using (StreamReader streamReader = File.OpenText(FORM_Path))
{
line = streamReader.ReadLine();
}
}
but I always get an error - file does not exist. how can i solve the problem in the path of text file.
Make sure your file's properties are set to copy the file to output directory. Then you can use the following line to get full path of your text file:
string FilePath = System.IO.Path.Combine(Application.StartupPath, "FormData\Login.txt");
You path is not in correct format. Use #".\FormData\Login.txt" instead of what you have
You are trying to give relative path instead of physical path. If you can use asp.net use Server.MapPath
string FORM_Path = Server.MapPath("~/FormData/Login.txt");
If the text file is in execution folder then you can use AppDomain.BaseDirectory
string FORM_Path = AppDomain.CurrentDomain.BaseDirectory + "FormData\\Login.txt";
If it is not possible to use some base path then you can give complete path.
Avoid using relative paths. Instead consider using the methods in the Path class.
Path.Combine
Path.GetDirectoryName
Step 1: get absolute path of the executable
var path = (new System.Uri(Assembly.GetEntryAssembly().CodeBase)).AbsolutePath;
Step 2: get the working dir
var dir = Path.GetDirectoryName(path);
Step 3: build the new path
var filePath = Path.Combine(dir , #"FormData\Login.txt");

c# .dat file assign to variable

how can i assign a to a variable, which is located at the same project, for example at my project i created a folder named App_Data and for example the file is file.dat , how can i assign the file at a variable,.. for example:
var file = App_Data/file.dat
I need it to be assigned to a variable because i will be using that variable as a parameter to a method,.. it used to be :
var file= HttpContext.Current.Request.MapPath("/App_Data/file.dat");
but now i want the path to be at the same project
if it should be absolute path it should be fine too
The MapPath should give you the absolute location of the file on disk from a relative url to the root of your website:
var absoluteFileLocation = HostingEnvironment.MapPath("~/App_Data/file.dat");
This should return something like:
c:\inetpub\wwwroot\MyWebSite\App_Data\file.dat
UPDATE:
It looks like you are trying to retrieve the contents of the file, not the location. Here's how this could be done:
var absoluteFileLocation = HostingEnvironment.MapPath("~/App_Data/file.dat");
string fileContents = System.IO.File.ReadAllText(absoluteFileLocation);
You need to read the file using one of the available methods (Streams, Readers, etc).
The easiest would be:
string fileContent = File.ReadAllText(fileNameAndPath);
where the variable fileNameAndPath contains the full path and file name to the file as described by Darin Dimitrov.
Your intention isn't exactly clear, anyway:
if you want file stats:
System.IO.File file = new System.IO.File("~/App_Data/file.dat");
if you want the file content use:
public static string readFileContent(String filename)
{
try
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(filename))
return sr.ReadToEnd();
}
catch { return String.Empty; }
}

Categories

Resources