In my application there is a option for where user creates a simple txt file containing some data. I would like to name the file in sequential order like ST1, ST2.... This sequence will be remain same for all users. if user1 creates a file system should name the file ST100 and then if user2 creates a file then system should name the file ST101.
I cant use the application scope as it is ready only and cant be changed at run time where as the user scope will only impact individual user not across the whole application.
I was wondering is there any other solution to achieve this apart from using database table and tacking sequence.
Thanks
You could use a loop and File.Exists:
var dir = #"C:\SampleFolder";
int number = 100; // you want to start at 100
string fileName = String.Format("ST{0}.txt", number.ToString("D3"));
while(File.Exists(Path.Combine(dir, fileName)))
fileName = String.Format("ST{0}.txt", (++number).ToString("D3"));
Finally you will have a new file-name and you get the correct path:
string path = Path.Combine(dir, fileName);
if your application is always on, you can use a global variable for the entire system with the numeric value of the next entry.
if not, you can use a text file as a database with the current number of the file; The problem with this solution is the synchronization, if two users doing the same operation at the same time can give you problems, so it is best to use a database.
I hope it helps you
Related
My code is searchcing inside a loop if a *txt file has been created.
If file will not be created after x time then i will throw an exception.
Here is my code:
var AnswerFile = #"C:\myFile.txt";
for (int i = 0; i <= 30; i++)
{
if (File.Exists(AnswerFile))
break;
await Task.Delay(100);
}
if (File.Exists(AnswerFile))
{
}
else
{
}
After the loop i check my file if has been created or not. Loop will expire in 3 seconds, 100ms * 30times.
My code is working, i am just looking for the performance and quality of my code. Is there any better approach than mine? Example should i use FileInfo class instead this?
var fi1 = new FileInfo(AnswerFile);
if(fi1.Exists)
{
}
Or should i use filewatcher Class?
You should perhaps use a FileSystemWatcher for this and decouple the process of creating the file from the process of reacting to its presence. If the file must be generated in a certain time because it has some expiry time then you could make the expiry datetime part of the file name so that if it appears after that time you know it's expired. A note of caution with the FileSystemWatcher - it can sometimes miss something (the fine manual says that events can be missed if large numbers are generated in a short time)
In the past I've used this for watching for files being uploaded via ftp. As soon as the notification of file created appears I put the file into a list and check it periodically to see if it is still growing - you can either look at the filesystem watcher lastwritetime event for this or directly check the size of the file now vs some time ago etc - in either approach it's probably easiest to use a dictionary to track the file and the previous size/most recent lastwritedate event.
After a minute of no growth I consider the file uploaded completely and I process it. It might be wise for you to implement a similar delay if using a file system watcher and the files are arriving by some slow generating method
Why you don't retrieve a list of files name, then search in the list? You can use Directory.GetFiles to get the files list inside a directory then search in this list.
This would be more fixable for you since you will create the list once, and reuse it across the application, instead of calling File.Exists for each file.
Example :
var path = #"C:\folder\"; // set the folder path, which contains all answers files
var ext = "*.txt"; // set the file extension.
// GET filename list (bare name) and make them all lowercase.
var files = Directory.GetFiles(path, ext).Select(x=> x.Substring(path.Length, (x.Length - path.Length) - ext.Length + 1 ).Trim().ToLower()).ToList();
// Search for this filename
var search = "myFile";
// Check
if(files.Contains(search.ToLower()))
{
Console.WriteLine($"File : {search} is already existed.");
}
else
{
Console.WriteLine($"File : {search} is not found.");
}
I am wondering how to remove the version number from a file path in a Windows Form Application.
Currently I wish to save some users application data to a .xml file located in the roaming user profile settings.
To do this I use:
get
{
return Application.UserAppDataPath + "\\FileName.xml";
}
However this returns the following string:
C:\Users\user\AppData\Roaming\folder\subfolder\1.0.0.0\FileName.xml
and I was wondering if there is a non-hack way to remove the version number from the file path so the file path looks like this:
C:\Users\user\AppData\Roaming\folder\subfolder\FileName.xml
Besides parsing the string looking for the last "\", I do not know what to do.
Thanks
Use Directory.GetParent method for this purpose.
get
{
var dir = Directory.GetParent(Application.UserAppDataPath);
return Path.Combine(dir.FullName, "FileName.xml");
}
Also note that I've used Path.Combine instead of concatenating paths, this method helps you to avoid so many problems. Never concatenate strings to create path.
I am developing an app right now that reads in data from a windows from and generates an XML file based on the input.
I am tasked with creating a new file each time the form is updated (User presses "Submit"). (so far so good)
Here is the catch: The file has to be named after a prominent field input. (If the user types '993388CX' in the text box, the app would rename the pending file 993388CX.xml).
I understand how to actually rename a file in C#, but not how to rename it based on a form's input. Do any classes/methods exist that will dynamically rename the file based on the form input?
Code:
//Reads info1 from user input on the app UI and generates XML statement
XTemp = XDoc.CreateElement("New_Info");
XTemp.InnerText = info1.Text;
Xsource.AppendChild(XTemp);
XDoc.Save(#"C:\oldfile.xml");
I need the new file to be renamed after the string in info1.Text
If the user input was "John5", the file needs renamed to john5.xml
Thank you
Either directly save it with the correct name:
XDoc.Save(String.Format("C:\\{0}.xml",info1.Text));
OR
Rename it afterwards
File.Move("c:\\oldfile.xml", String.Format("C:\\{0}.xml",info1.Text));
XDoc.Save(#"C:\" + info1.Text + ".xml");
File.Move should do what you want.
I am having an xml file like:
<CurrentProject>
// Elements like
// last opened project file to reopen it when app starts
// and more global project independend settings
</CurrentProject>
Now I asked myself wether I should deliver this xml file with above empty elements with the installer for my app or should I create this file on the fly on application start if it does not exist else read the values from it.
Consider also that the user could delete this file and that should my application not prevent from working anymore.
What is better and why?
UPDATE:
What I did felt ok for me so I post my code here :) It just creates the xml + structure on the fly with some security checks...
public ProjectService(IProjectDataProvider provider)
{
_provider = provider;
string applicationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
_projectPath = Path.Combine(applicationPath,#"TBM\Settings.XML");
if (!File.Exists(_projectPath))
{
string dirPath = Path.Combine(applicationPath, #"TBM");
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
using (var stream = File.Create(_projectPath))
{
XElement projectElement = new XElement("Project");
projectElement.Add(new XElement("DatabasePath"));
projectElement.Save(stream, SaveOptions.DisableFormatting);
}
}
}
In a similar scenario, I recently went for creating the initial file on the fly. The main reason I chose this was the fact that I wasn't depending on this file being there and being valid. As this was a file that's often read from/written to, there's a chance that it could get corrupted (e.g. if the power is lost while the file is being written).
In my code I attempted to open this file for reading and then read the data. If anywhere during these steps I encountered an error, I simply recreated the file with default values and displayed a corresponding message to the user.
We are using an application that reads the file and inserts into database. For some reason, we set the creation time to a particular time. and when we create the file the application picks up the file before we even change the creation time. Is there anyway that we can lock the file until we change its creation time.
The error i am getting is at File.SetCreationTime as the file is being used by other process or the file is archived.
//Copy signal file
s = filePath + "s";
newS = targetFullPath2 + "s";
File.Copy(s, newS, true);
//
//new creation ts
dtFileCreation = File.GetCreationTime(s);
//retain creation time
File.SetCreationTime(newS, dtFileCreation);
Please advice.
The common solution to this is to create the file (and set its timestamp) in a different directory or under a different name first, and then move or rename it when it’s ready so the other process can pick it up. The move/rename is an atomic operation on NTFS (unless of course you move files between separate partitions).
For example:
s = filePath + "s";
newS = targetFullPath2 + "s";
File.Copy(s, newS + "_", true); // add the _ so the other process
// doesn’t “see” the file yet
dtFileCreation = File.GetCreationTime(s);
File.SetCreationTime(newS + "_", dtFileCreation);
// We’re done with the file, now rename it to its intended final name
File.Move(newS + "_", newS);
That error indicates someone (it could be you or another program) is locking the file; therefore, I do not think locking the file will solve your problem. What kind of file is it? Is your code reading the file and forgetting to close the stream after it is done?