DirectoryPath = C:\Pics
filePath = C:\Pics\Dogs\dog.PNG
newPath should be: Dogs\dog.PNG
How do I get the newPath?
My code snippet is not right
string directoryPath = "C:\\Pics";
string filePath = "C:\\Pics\\Dogs\\dog.PNG";
if (!directoryPath.EndsWith("\\"))
directoryPath = directoryPath + "\\";
string newPath = filePath.Substring(filePath.LastIndexOf(directoryPath) + 1);
Thanks in advance!
Could you append a backslash to the directory path & then in the filepath replace the directory path with an empty string
newPath = filePath.Replace(DirectoryPath + #"\", string.Empty);
If the directoryPath does not match the start of the filePath, then newPath will be unchanged.
I did post this before you edited your code to show the conditional adding of the backslash - so that can be removed in the above code.
The int Index you get from LastIndexOf() will always starts with the rightmost value, in your case 0. You have also to add the String.Lenght for this.
if (filePath.StartsWith(directoryPath))
{
string newPath =
filePath.Substring(filePath.LastIndexOf(directoryPath) + directoryPath.Length + 1);
}
I would first check if filePath contains DirectoryPath,so i'd do something like this:
var newPath=filePath.Contains(DirectoryPath)?filePath.Substring(DirectoryPath.Length + 1)
:filePath;
Or even better,using StartsWith
var newPath=filePath.StartsWith(DirectoryPath)?filePath.Substring(DirectoryPath.Length + 1)
:filePath;
Related
After the else block Path.Combine method combines every part and gives the file name when Console.WriteLine(result); is used. But it doesn't actually create the file with that name.
I want to get the EmployeeDetails.txt file, make a version of it (i.e. renaming the filename) and saves it to C:\Hitory folder.
How to achieve that?
Using File.Move throws FileNotFoundexception
void ModRec()
{
string filename = #"C:\Current\EmployeeDetails.txt";
string current = #"C:\Current\";
string history = #"C:\History\";
FileInfo fileinfo = new FileInfo(filename);
if (fileinfo.Exists)
{
if (!Directory.Exists(history))
{
Directory.CreateDirectory(history);
}
}
else
{
Console.WriteLine("\t\t\tFile doesn't exist!");
Console.ReadLine();
Menu1();
}
var extension = Path.GetExtension(filename);
var fileNamePart = Path.GetFileNameWithoutExtension(filename);
var path = Path.GetDirectoryName(filename);
var version = 0;
string result;
do
{
version++;
result = Path.Combine(path, fileNamePart + "_" + version + extension);
}
while (File.Exists(result));
//File.Move(current, history);
}
Your loop at the end needs to change slightly, because
result = Path.Combine(path, fileNamePart + "_" + version + extension);
is looking in the directory where the file already is, rather than in the history directory where you want it to be, so you'll be scanning for duplicates in the wrong location. The Path.Combine therefore needs to reference the value of history:
result = Path.Combine(history, fileNamePart + "_" + version + extension);
Secondly, you cannot use Move to move a file to a directory in the same way that you can from the command line, you need to specify the two parameters as filenames, so
File.Move(current, history);
becomes
File.Move(filename, result);
The resulting code at the end of your method should therefore look like this:
do
{
version++;
result = Path.Combine(history, fileNamePart + "_" + version + extension);
}
while (File.Exists(result));
File.Move(filename, result);
Incidentally, where you test whether the file already exists, you simply call Menu1 and then carry on. Can you guarantee that that will ensure that the next thing that the user does will create a valid file? I'm guessing that it most likely cannot guarantee that, so you should exit your method at that point, or perhaps put the remainder of the body inside the fileinfo.Exists block.
That leaves the desirability of invoking a menu from inside this method, but that's a design question outside of the scope of what you've asked here.
Try this instead:
void ModRec()
{
string filename = #"C:\Current\EmployeeDetails.txt";
string current = #"C:\Current\";
string history = #"C:\History\";
FileInfo fileinfo = new FileInfo(filename);
if (fileinfo.Exists)
{
if (!Directory.Exists(history))
{
Directory.CreateDirectory(history);
}
}
else
{
Console.WriteLine("\t\t\tFile doesn't exist!");
Console.ReadLine();
Menu1();
}
var extension = Path.GetExtension(filename);
var fileNamePart = Path.GetFileNameWithoutExtension(filename);
var path = Path.GetDirectoryName(filename);
var version = 0;
string result;
do
{
version++;
result = Path.Combine(history, fileNamePart + "_" + version + extension);
}
while (File.Exists(result));
File.Move(filename, result);
}
Path.Combine() does not touch filesystem at all. No files/folders would be ever crated.
Try File.Move(filename, history);. That is, instead of current, which is a directory, move the file (assuming filename is a full path).
I need to remove a pattern from a string, I think regex could do the job, but I'm having trouble solving this.
The pattern must be in the end of the string.
string fileName = "File (123)";
string pattern = " (0)";
string cleanName = PatternRemover(fileName, pattern);
//Should result in: cleanName == "File"
Edit:
Ok, here is the code that I'm using now after your answers:
public static string GetNextFilePath2(string fullPath, ref uint id, string idFormat)
{
string dir = Path.GetDirectoryName(fullPath);
string ext = Path.GetExtension(fullPath);
string fileNameNoExt = Path.GetFileNameWithoutExtension(fullPath);
if (ext.Length > 0 && ext[0] != '.')
ext = "." + ext;
string baseName = Regex.Replace(fileNameNoExt, #"\s\(\d+\)", "");
string fileName = baseName + " (" + id.ToString(idFormat) + ")" + ext;
string path = Path.Combine(dir, fileName);
while (File.Exists(path))
{
id++;
fileName = baseName + " (" + id.ToString(idFormat) + ")" + ext;
path = Path.Combine(dir, fileName);
}
return path;
}
It works, but:
It always start to count from id, I think it may be better to start
from the file name number.
I was hopping to use something like "(0)" as a method parameter that would indicate the pattern to be removed and also the "(" would be parametrized. I'm doing it "manually" now on this line: string fileName = baseName + " (" + id.ToString(idFormat) + ")" + ext;
You can do that without REGEX like:
string newFileName = new String(fileName
.Where(r => !char.IsDigit(r)
&& r != '('
&& r != ')'
&& r != ' ').ToArray());
This would give you File.jpg
If you only want to get the file name then you can use:
string fileNameWithoutPath = Path.GetFileNameWithoutExtension(newFileName);
// it would give you `File`
Using regex:
var subject = "File (123).jpg";
var fileNameWithExtension = Regex.Replace(subject,#"\s*\(\d+\)","");
var fileNameWithoutPath = Path.GetFileNameWithoutExtension(fileNameWithExtension);
And thanks for #habib, I'd not have come with Path.GetFileNameWithoutExtension in this for stripping the extension.
You could use:
\s\(\d+\)\.jpg
assuming you do actually want the extension removed and the extension is always ".jpg". Otherwise:
\s\(\d+\)
Looks for a set of digits in brackets proceeded by a space.
I am trying to download images. Their link may be image.png or http://www.example.com/image.png.
I made the image.png be added to the host and passed it to a list. So image.png is now http://www.example.com/image.png
But if the other type is used what I get is http://www.example.com//http://www.example.com/image.png
All I need is to get the string after the third slash. Here is some code I am tried to use:
try
{
path = this.txtOutput.Text + #"\" + str4 + etc;
client.DownloadFile(str, path);
}
catch(Exception e)
{
var uri = new Uri(str);
String host = (String) uri.Host;
String pathToFile = "http://" + host + "/";
int len = pathToFile.Length;
String fin = str.Substring(len, str.Length - len);
path = this.txtOutput.Text + #"\" + str4 + etc;
client.DownloadFile(fin, path);
}
What are these variables all about, like str4, etc and so on? Instead of the try catch you could check wheter the string is a valid uri. Give a look here. Try to debug you code line on line and check every single variable, then you will see which line makes the mistake.
EDIT
If I understodd you right, then this would be your solution:
string wrongResult = "example.com//http://www.example.com/image.png";
string shouldResult = "example.com/image.png";
int listIndexOfHttp = wrongResult.LastIndexOf("http:");
string correctResult = wrongResult.Substring(listIndexOfHttp);
When not please describe more specific from where you get this and it is always the same structure? or alaways different?
I am trying to split the string. Here is the string.
string fileName = "description/ask_question_file_10.htm"
I have to remove "description/" and ".htm" from this string. So the result I am looking for "ask_question_file_10". I have to look for "/" and ".htm" I appreciate any help.
You can use the Path.GetFileNameWithoutExtension Method:
string fileName = "description/ask_question_file_10.htm";
string result = Path.GetFileNameWithoutExtension(fileName);
// result == "ask_question_file_10"
string fileName = Path.GetFileNameWithoutExtension("description/ask_question_file_10.htm")
try
string myResult = fileName.SubString (fileName.IndexOf ("/") + 1);
if ( myResult.EndsWith (".htm" ) )
myResult = myResult.SubString (0, myResult.Length - 4);
IF it is really a path then you can use
string myResult = Path.GetFileNameWithoutExtension(fileName);
EDIT - relevant links:
http://msdn.microsoft.com/en-us/library/system.io.path.getfilenamewithoutextension.aspx
http://msdn.microsoft.com/en-us/library/hxthx5h6.aspx
http://msdn.microsoft.com/en-us/library/2333wewz.aspx
http://msdn.microsoft.com/en-us/library/system.string.length.aspx
string fileName = "description/ask_question_file_10.htm";
string name = Path.GetFileNameWithoutExtension(fileName);
My app takes "unclean" file names and "cleans" them up. "Unclean" file names contain characters like #, #, ~, +, %, etc. The "cleaning" process replaces those chars with "". However, I found that if there are two files in the same folder that, after a cleaning, will have the same name, my app does not rename either file. (I.e. ##test.txt and ~test.txt will both be named test.txt after the cleaning).
Therefore, I put in a loop that basically checks to see if the file name my app is trying to rename already exists in the folder. However, I tried running this and it would not rename all the files. Am I doing something wrong?
Here's my code:
public void FileCleanup(List<string> paths)
{
string regPattern = (#"[~#&!%+{}]+");
string replacement = "";
Regex regExPattern = new Regex(regPattern);
List<string> existingNames = new List<string>();
StreamWriter errors = new StreamWriter(#"C:\Documents and Settings\joe.schmoe\Desktop\SharePointTesting\Errors.txt");
StreamWriter resultsofRename = new StreamWriter(#"C:\Documents and Settings\joe.schmoe\Desktop\SharePointTesting\Results of File Rename.txt");
var filesCount = new Dictionary<string, int>();
string replaceSpecialCharsWith = "_";
foreach (string files2 in paths)
try
{
string filenameOnly = Path.GetFileName(files2);
string pathOnly = Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFileName);
if (!System.IO.File.Exists(sanitized))
{
System.IO.File.Move(files2, sanitized);
resultsofRename.Write("Path: " + pathOnly + " / " + "Old File Name: " + filenameOnly + "New File Name: " + sanitized + "\r\n" + "\r\n");
}
else
{
existingNames.Add(sanitized);
foreach (string names in existingNames)
{
string sanitizedPath = regExPattern.Replace(names, replaceSpecialCharsWith);
if (filesCount.ContainsKey(sanitizedPath))
{
filesCount[names]++;
}
else
{
filesCount.Add(sanitizedPath, 1);
}
string newFileName = String.Format("{0},{1}, {2}", Path.GetFileNameWithoutExtension(sanitizedPath),
filesCount[sanitizedPath] != 0
? filesCount[sanitizedPath].ToString()
: "",
Path.GetExtension(sanitizedPath));
string newFilePath = Path.Combine(Path.GetDirectoryName(sanitizedPath), newFileName);
System.IO.File.Move(names, newFileName);
}
}
}
catch (Exception e)
{
//write to streamwriter
}
}
}
Anybody have ANY idea why my code won't rename duplicate files uniquely?
You do foreach (string names in existingNames), but existingNames is empty.
You have your if (System.IO.File.Exists(sanitized)) backwards: it makes up a new name if the file doesn't exist, instead of when it exists.
You make a string newFileName, but still use sanitizedPath instead of newFileName to do the renaming.
The second parameter to filesCount.Add(sanitizedPath, 0) should be 1 or 2. After all, you have then encountered your second file with the same name.
If filesCount[sanitizedPath] equals 0, you don't change the filename at all, so you overwrite the existing file.
In addition to the problem pointed out by Sjoerd, it appears that you are checking to see if the file exists and if it does exist you move it. Your if statement should be
if (!System.IO.File.Exists(sanitized))
{
...
}
else
{
foreach (string names in existingNames)
{
...
}
}
}
Update:
I agree that you should split the code up into smaller methods. It will help you identify which pieces are working and which aren't. That being said, I would get rid of the existingNames list. It is not needed because you have the filesCount Dictionary. Your else clause would then look something like this:
if (filesCount.ContainsKey(sanitized))
{
filesCount[sanitized]++;
}
else
{
filesCount.Add(sanitized, 1);
}
string newFileName = String.Format("{0}{1}.{2}",
Path.GetFileNameWithoutExtension(sanitized),
filesCount[sanitized].ToString(),
Path.GetExtension(sanitized));
string newFilePath = Path.Combine(Path.GetDirectoryName(sanitized), newFileName);
System.IO.File.Move(files2, newFileName);
Please note that I changed your String.Format method call. You had some commas and spaces in there that looked incorrect for building a path, although I could be missing something in your implementation. Also, in the Move I changed the first argument from "names" to "files2".
A good way to make the code less messy would be to split it to methods as logical blocks.
FindUniqueName(string filePath, string fileName);
The method would prefix the fileName with a character, until the fileName is unique withing the filePath.
MoveFile(string filePath, string from, string to);
The method would use the FindUniqueName method if the file already exists.
It would be way easier to test the cleanup that way.
Also you should check if a file actually requires renaming:
if (String.Compare(sanitizedFileName, filenameOnly, true) != 0)
MoveFile(pathOnly, fileNameOnly, sanitizedFileName);
private string FindUniqueName(string fileDirectory, string from, string to)
{
string fileName = to;
// There most likely won't be that many files with the same name to reach max filename length.
while (File.Exists(Path.Combine(fileDirectory, fileName)))
{
fileName = "_" + fileName;
}
return fileName;
}
private void MoveFile(string fileDirectory, string from, string to)
{
to = FindUniqueName(fileDirectory, from, to);
File.Move(Path.Combine(fileDirectory, from), Path.Combine(fileDirectory, to));
}