This question already has answers here:
Why Windows sets new created file's "created time" property to old time?
(3 answers)
Closed 5 years ago.
I am attempting to get the creation date of a file. I am using the File.GetCreationTime() method to do this. If the file is a new file, it seems to work fine. If I delete the file though and re-create it, it seems to be giving me the original creation time. Since the file was deleted, it seems weird and even impossible that it is returning the original date and time of the file.
I put together a simple console application to demonstrate the issue:
static void Main(string[] args)
{
const string fileName = #"C:\Temp\dummy.txt";
File.AppendAllText(fileName, "This is a test");
DateTime creationDate = File.GetCreationTime(fileName);
Console.WriteLine(creationDate.ToShortDateString() + " " + creationDate.ToShortTimeString());
System.Threading.Thread.Sleep(120000);
File.Delete(fileName);
File.AppendAllText(fileName, "This is a test");
creationDate = File.GetCreationTime(fileName);
Console.WriteLine(creationDate.ToShortDateString() + " " + creationDate.ToShortTimeString());
}
This program creates a dummy file and appends the text This is a test. It then prints out the creation date and time to the console screen. So far, so good. It then sleeps for 2 minutes. After the 2 minutes have elapsed, it deletes the file and re-creates it. It then, again, prints out the creation date and time to the console screen. I would except the latter output to be 2 minutes later than the original, however, it is pulling the same exact date and time! I have single stepped through the program and I can verify that it is, indeed, deleting the original file from the hard drive.
Actual Output
--------------
5/6/2017 10:25 AM
5/6/2017 10:25 AM
Expected Output
----------------
5/6/2017 10:25 AM
5/6/2017 10:27 AM
Can someone explain to me what is going on here and how to work around the issue?
From the MSDN page
NTFS-formatted drives may cache information about a file, such as file creation time, for a short period of time. As a result, it may be necessary to explicitly set the creation time of a file if you are overwriting or replacing an existing file.
Related
So I made a math problem program that basically reads one number from a text file (only number in that text file) and replaces it with a number+1 if number is not a solution.
Now the issue is, if I only add a text in the next row using
sw.WriteLine(text);
that makes the calculations really fast, doing 100k+ numbers in a few seconds, but it's just adding the number to the text file without deleting previous.
Alternatively I used
string[] lines = File.ReadAllLines("numbers.txt");
foreach (string line in lines)
{
lines[0] = Convert.ToString(biginta);
}
File.WriteAllLines("numbers.txt", lines);
but that made my program run considerably slower.
Is there a way I can replace text in a .txt file by using already open filestream?
I'm new to c# so my whole program is basically a Frankenstein of a code.
I'm using a file to store the next number needed to run because I turn off my pc overnight.
Honestly the quickest solutiion to this is the following: Read the file once, do several (like 100) calculations without saving and then store the current number back into the file.
Tune the interval so that you store the current state once every 5 seconds or so.
That gives you still a good starting point (at most 5 seconds lost work) but also reduces disk IO to the point where it won't slow down the calculation any more.
I am trying to create a script which does something say show a popup after 1 day. As far as I know I can do this using Thread.Stop or using System.Timers or many other ways. But the problem with each is that the computer has to be continuously running for each of these methods to give desired result at the time I want. Basically I want the script to start with installation of my program, wait for exactly 24 hours, then display a message box. If the computer is switched on at that time i.e. after 24 hours it should show the message box on next start up but only if 24 hours or more have passed. Please help, i am unable to find suitable solution for this. any help will be highly appreciated. I think that it may be achieved by getting the dateTime.Now and putting it in a file, and then compare current system time to the time in file every hour or so, and if 24 hours or more have passed, show the message box. Please help
If a message box is what you need to pop up, then you'll need a Windows Forms application. Here is the workflow of how it'll work:
Application will need to save data, either through a database or to a file.
When the application first loads, it will check either the database or the file for a TriggerDate entry.
If the TriggerDate exists, pull this date and compare it to today's date and time. If the current date and time is past our TriggerDate, display the message box. Recreate the TriggerDate with the current date and time plus 24 hours.
If TriggerDate does not exist, create it, filled with the current date and time plus 24 hours (e.g. DateTime.Now.AddHours(24)).
Use Threading.Thread.Sleep() to sleep for 5 minutes.
Jump to step 3 and repeat.
EDIT
Code will be something like this:
private const string TriggerFile = #"C:\TriggerData\trigger.txt";
private DateTime _triggerDate;
if (!File.Exists(TriggerFile))
{
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
}
}
using (StreamReader sr = File.OpenText(TriggerFile))
{
_triggerDate = DateTime.Parse(sr.ReadToEnd());
}
while (true)
{
if (DateTime.Now >= _triggerDate)
{
MessageBox.Show(#"Alert!");
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
_triggerDate = DateTime.Now.AddHours(24);
}
}
System.Threading.Thread.Sleep(60000*5); // Sleep for 5 minutes
}
You may not want to do while(true). You way want to implement a way to get out of the program.
If I understand correctly, what you can use is a way to save the "start date". You can save the start date of the timer and read the value from your script, that way you can calculate if 24 hours or more has passed since the moment you assigned a value to the start date. You can use a simply TXT file to save the value.
I see two ways of achieving this :
Easy way (but not strictly related to C#) is to use the task scheduler and create a task that will run your C# program every 24 hours. One way to do this from an installer would be to use the SchTasks.exe tool. This method allows you to just exit the program after your work is done without having to explicitely wait for the next run.
Harder way: Create a Windows Service, which is a program specifically designed to run permanently on the host computer. These programs are slightly more technical to write though. You can find more explanations about services here. However, you may not want to take this route as service cannot display user interfaces like popups.
Update: The answers from Andrew and Conrad were both equally helpful. The easy fix for the timing issue fixed the problem, and caching the bigger object references instead of re-building them every time removed the source of the problem. Thanks for the input, guys.
I'm working with a c# .NET API and for some reason the following code executes what I feel is /extremely/ slowly.
This is the handler for a System.Timers.Timer that triggers its elapsed event every 5 seconds.
private static void TimerGo(object source, System.Timers.ElapsedEventArgs e)
{
tagList = reader.GetData(); // This is a collection of 10 objects.
storeData(tagList); // This calls the 'storeData' method below
}
And the storeData method:
private static void storeData(List<obj> tagList)
{
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
long timestamp = (long)t.TotalSeconds;
foreach (type object in tagList)
{
string file = #"path\to\file" + object.name + ".rrd";
RRD dbase = RRD.load(file);
// Update rrd with current time timestamp and data.
dbase.update(timestamp, new object[1] { tag.data });
}
}
Am I missing some glaring resource sink? The RRD stuff you see is from the NHawk C# wrapper for rrdtool; in this case I update 10 different files with it, but I see no reason why it should take so long.
When I say 'so long', I mean the timer was triggering a second time before the first update was done, so eventually "update 2" would happen before "update 1", which breaks things because "update 1" has a timestamp that's earlier than "update 2".
I increased the timer length to 10 seconds, and it ran for longer, but still eventually out-raced itself and tried to update a file with an earlier timestamp. What can I do differently to make this more efficient, because obviously I'm doing something drastically wrong...
Doesn't really answer your perf question but if you want to fix the rentrancy bit set your timer.AutoRest to false and then call start() at the end of the method e.g.
private static void TimerGo(object source, System.Timers.ElapsedEventArgs e)
{
tagList = reader.GetData(); // This is a collection of 10 objects.
storeData(tagList); // This calls the 'storeData' method below
timer.Start();
}
Is there a different RRD file for each tag in your tagList? In your pseudo code you open each file N number of times. (You stated there is only 10 objects in the list thought.) Then you perform an update. I can only assume that you dispose your RRD file after you have updated it. If you do not you are keeping references to an open file.
If the RRD is the same but you are just putting different types of plot data into a single file then you only need to keep it open for as long as you want exclusive write access to it.
Without profiling the code you have a few options (I recommend profiling btw)
Keep the RRD files open
Cache the opened files to prevent you from having to open, write close every 5 seconds for each file. Just cache the 10 opened file references and write to them every 5 seconds.
Separate the data collection from data writing
It appears you are taking metric samples from some object every 5 seconds. If you do not having something 'tailing' your file, separate the collection from the writing. Take your data sample and throw it into a queue to be processed. The processor will dequeue each tagList and write it as fast as it can, going back for more lists from the queue.
This way you can always be sure you are getting ~5 second samples even if the writing mechanism is slowed down.
Use a profiler. JetBrains is my personal recommendation. Run the profiler with your program and look for the threads / methods taking the longest time to run. This sounds very much like an IO or data issue, but that's not immediately obvious from your example code.
I was doing window services where I'm generating txt files in target path based on some details from a database but I have a problem the service is running too fast!
I was getting same file name in the place of sec variation required so that i can avoid duplicates over there.
code :
using (transactionscope scope = new transactionscope )
{
string nowtime = datetime.now.today.tostring(HHMMss) // it was working fine
}
file should be generates by specific file naming convention !! ex:hhmmss >>> no millisecond
can any one give me exclusive ideas how to face this part?
You can add milliseconds to the filename:
string nowtime = datetime.Now.Today.ToString("HHmmssfff");
See Custom Date and Time Format Strings.
A few notes about the code you posted:
MM is for months, not minutes. You should use lower case mm.
The parameter that ToString takes is a string.
Your code wouldn't compile as it is not correctly cased. Please use code that can be directly used in the future.
Update:
Seeing as you have to use this format, the only other choice is to "slow down" the service.
Adding a:
Thread.Wait(1000);
In the right place (end of loop?) could do the trick.
Alternatively, you can change your code to append to a file if you are still within the same second.
If you are saying that you are creating multiple files with the same name (multiple files in the same second), then I would take the time out to the milliseconds. You can do this with:
DateTime.Today.ToString("HHmmssfff");
The fff denotes the three places to the right of the decimal (thousandths of a second).
I am trying to copy files from one directory to another and test based upon the file creation date.
File.Copy(fileName, directory + fileNameOnly, true);
The problem occurs later in my program when I checked the creation date to ensure it is no more than 5 days old.
FileInfo file = new FileInfo(fileName);
if (file.CreationTime.AddHours(120) < DateTime.Now) {}
I have seen that the creation date when copied back is set to 1980-01-01. This is not useful for my requirements as I would like maintain the creation date from the original file. Is there another method of comparing the dates or is it the copy that loses the creation date value.
I guess my question is, how can I maintain the Creation Date?
Use the File.SetCreationTime method after you copy the file.
You can get the source file's creation time with File.GetCreationTime