Using c# in a Windows Form I need to search a directory "C:\XML\Outbound" for the file that contains an order number 3860457 and return the path to the file that contains the order number so I can then open the file and display the contents to the user in a RickTextBox.
The end user will have the order number but will not know what file contains that order number so that is why I need to search all files till it finds the filecontaining the order number and return the path (e.g. "C:\XML\Outbound\some_file_name_123.txt")
I am somewhat new to c# so I am not even sure where to start with this. Any direction for this?
Sorry the order number is inside the file so I need to search each file contents for the order number and once the file containing the order number is found return the path to that file. Order number is not part of the file name.
Straight answer:
public string GetFileName(string search){
List<string> paths = Directory.GetFiles(#"C:\XML\Outbond","*.txt",SearchOption.AllDirectories).ToList();
string path = paths.FirstOrDefault(p=>File.ReadAllLines(p).Any(line=>line.IndexOf(search)>=0));
return path;
}
Not-so straight answer:
Even though the above function will give you the path for given string (some handling of errors and edge cases may be nice) it will be terribly slow, especially if you have lots of files. If that's the case you need to tell us more about your environment because chances are you're doing it wrong (:
Related
I need to be able to extract the full file path out of this string (without whatever is after the file extension):
$/FilePath/FilePath/KeepsGoing/Folder/Script.sql (CS: 123456)
A simple solution such as the following could would work for this case, however it is only limited to a file extension with 3 characters:
(\$.*\..{3})
However, I find problems with this when the file contains multiple dots:
$/FilePath/FilePath/File.Setup.Task.exe.config (CS: 123456)
I need to be able to capture the full file path (from $ to the end of whatever the file extension is, which can be any number of things). I need to be able to get this no matter how many dots are in the name of the file. In some cases there are spaces in the name of the file too, so I need to be able to incorporate that.
Edit: The ending (CS....) in this case is not standard. All kinds of stuff can follow the path so I cannot predict what will come after the path, but the path will always be first. Sometimes spaces do exist in the file name.
Any suggestions?
Try this:
(\$.*\.[\w.-]+)
But! it will not properly match files with space or special chars in the file extension. If you need to match files that might have special chars in the file extension you'll need to elaborate on the input (is it quoted? is it escaped?).
I have a problem.
I save json from web, in json files on my computer, and the name of this json file, is the web adress of the json.
For that, I get the web json into string, and then I append it in a file, with File.AppendAllText(path, content)
After some time, i also need to read json from this file with File.ReadAllText(path)
My problem is sometimes, two json have a very similar name, for example :
*com/doc/BACr and
*com/doc/BAcr
Problem, the path given in the methods of the class File are note case sensitive, and I end writing twice in the same file, corrupting it.
I've found on the internet solutions for the same problem for the method File.Exists(path), but nothing to replace the methods I use to read or write.
Any of you know a setting, or even another method that would be case sensitive on the path ?
Thank you
Edit : I'm obviously working on windows :(
Edit bis : I can't change the filename, because in some others json, there is reference to web path, and when I play again my local jsons, if the filename is modified, it won't be found. It's the reason I need both write and read with case sensitive path.
You need something that makes your files unique and in the same time something that allows you to rebuild this uniqueness when you want to read back these files.
Suppose that your couple of files is named "BAcr" and "BACr". You can get the HashCode of these two strings and you will get two different values
string file1 = "BAcr";
int file1Hash = file1.GetHashCode(); //742971449
string file2 = "BACr";
int file1Hash = file2.GetHashCode(); //-681949991
Now if you concatenate this hashcode to your filename you will get two different files and you will be able to recalculate the same hashcode for the same input filename
string newFile1 = $"{file1}.{file1Hash}";
string newFile2 = $"{file2}.{file2Hash}";
you will save your data in these two recalculated filenames and when you need to reload them you use the same trick to get the filename used to save the data starting from the same input "BAcr" or "BACr".
But string.GetHashCode doesn't guarantee uniqueness in its results so, still using the same general idea Jeroen Mostert uses this method to get an unique code from the input value
string unique1 = string.Join("", file1.Select(c => char.IsUpper(c) ? "1" : "0"))
string newFileName1 = $"{file1}.{unique1}";
Windows paths are indeed case insensitive, so you cannot have these filenames.
One solution would be to change the filename if it already exists...
For example;
if (File.Exists(fileNameToSaveTo)){
// Note: Your example file names did not have an extension,
// but if they do, you will need to first extract that then add it back on
fileNameToSaveTo = fileNameToSaveTo + "1";
}
If using this solution, you would have to also update whatever identifier your program uses to read back from the file at a later date... as you have not posted any code I cannot guess as to what form this takes, but hopefully you get the idea?
Edit:
Upon re-reading your question... it appears you use AppendAllText... In this case, this should not 'corrupt' the file as you suggest, but should simply add the contents to the end of the file? Is this not what you observe?
Edit2:
After reading comments Iomed - you could use Convert.ToBase64String on the filename in your write before writing the file, the use Convert.FromBase64String on the filename in your read function before reading the file. This will allow the filename to be different based on the capitalization.
Another alternative would be to parse the JSON (the new one AND the existing file) and add the objects to an array, then write that to the file instead, avoiding your 'corruption' issue?
given paths: PathA, patha
for two files, use base64 trick:
string PathToFile(string url) => System.Convert.ToBase64String(Encoding.UTF8.GetBytes(url));
so:
Console.WriteLine(PathToFile("pathA")); //cGF0aEE=
Console.WriteLine(PathToFile("patha")); //cGF0aGE=
I need get last part means the numeric value(318, 319) of the following text (will vary)
C:\Uploads\X\X-1\37\Misc_318.pdf
C:\Uploads\X\X-1\37\Misc_ 319.pdf
C:\Uploads\X\C-1\37\Misc _ 320.pdf
Once I get that value I need to search for the entire folder. Once I find the files name with matching number, I need to remove all spaces and rename the file in that particular folder
Here is What I want
First get the last part of the file(numeric number may vary)
Based upon the number I get search in the folder to get all files names
Once I get the all files name check for spaces with file name and remove the spaces.
Finding the Number
If the naming follows the convention SOMEPATH\SomeText_[Optional spaces]999.pdf, try
var file = System.IO.Path.GetFileNameWithoutExtension(thePath);
string[] parts = file.split('_');
int number = int.Parse(parts[1]);
Of course, add error checking as appropriate. You may want to check that there are 2 parts after the split, and perhaps use int.TryParse() instead, depending on your confidence that the file names will follow that pattern and your ability to recover if TryParse() returns false.
Constructing the New File Name
I don't fully understand what you want to do once you have the number. However, have a look at Path.Combine() to build a new path if that's what you need, and you can use Directory.GetFiles() to search for a specific file name, or for files matching a pattern, in the desired directory.
Removing Spaces
If you have a file name with spaces in it, and you want all spaces removed, you can do
string newFilename = oldFilename.Replace(" ", "");
Here's a solution using a regex:
var s = #"C:\Uploads\X\X-1\37\Misc_ 319.pdf";
var match = Regex.Match(s, #"^.*?(\d+)(\.\w+)?$");
int i = int.Parse(match.Groups[1].Value);
// do something with i
It should work with or without an extension of any length (as long as it's a single extension, not like my file 123.tar.gz).
In my application I build a static string when a user uploads or downloads a file. In that string the filename is passed from the frontend in that string. In this way the user could do things like ..\..\another file.file to tamper and get data from other users. Therefor I need to filter the filename that I get to prevent this. What are the characters that need to be filtered to prevent tampering? I now have the double dot and the back and forward slashes. Is there anything else I should take into consideration? Is there maybe a standard way to do this in C#?
I would suggest using Path.GetInvalidFileNameChars:
public static bool IsValidFileName(string fileName)
{
return fileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
}
.. is typically only dangerous when preceded and/or succeeded by a \ or /, both of which are included in the array returned by GetInvalidFileNameChars. By itself, .. is harmless (unless you’re specifically resolving directory paths), and you shouldn’t forbid it since people might want to introduce ellipses in their filename (e.g. The A...Z of Programming.pdf).
What if different users save a file with the same name? Are you creating a folder for each user?
Most likely what you should be doing is storing the name they provide in a database record, which also contains a pointer to the actual file (which uses a file name which you generate, perhaps a guid). You could also consider using the filestream data type if you'd like to save the document in the database as well.
Nothing good can come from letting your users determine file names on your server :)
I have this situation in c# application
have 2 paths in my windows
C:\Projectos\FrameworkCS\CSoft.Core
C:\Projectos2\CSoft.Core
and i need get related path of second related with first like this:
..\..\Projectos2\CSoft.Core
Exists a way to do this in c# or some one have a function can help me
Try MakeRelativeUri:
Uri first = new Uri(#"C:\Projectos2\CSoft.Core");
Uri second = new Uri(#"C:\Projectos\FrameworkCS\CSoft.Core ");
string relativePath = second.MakeRelativeUri(first).ToString();
Result:
"../../Projectos2/CSoft.Core"
I would probably figure it out by splitting both using the '\' as a separator. I would then count array items that were the same to get my common bond. Then I would build the destination path using the remaining items in the destination array and build the ..\ string by counting the remaining items in the source.
Common path = C:\Projectos\
Remaining destination path = CSoft.Core
Remaining source path has 1 more item (not including the file name itself) giving you ..\
Join the ..\ with the CSoft.Core giving you ..\CSoft.Core
Addendum: I didn't realise you could use the URI.MakeRelativePath() method for this - don't bother reinventing the wheel if it's already been done elsewhere.