I want to name my file after the current time in miliseconds since 1970.
At the moment I just have a counter and increment it after every new file. But when the app restarts the counter goes back to zero and I overwrite the files when I start saving them again.
So I was thinking if I just use the time in seconds or miliseconds then I wont have this problem.
So my question is how to I get the time in miliseconds on windows mobile.
This is what I am currently doing to generate my file names.
string fileName = savedCounter + ".jpg";
You can use Ticks
A single tick represents one hundred nanoseconds or one ten-millionth
of a second. There are 10,000 ticks in a millisecond.
DateTime unixEpoch = new DateTime(1970, 1, 1);
DateTime currentDate = DateTime.Now;
long totalMiliSecond = (currentDate.Ticks - unixEpoch.Ticks) /10000;
Console.WriteLine(totalMiliSecond);
string fileName = string.Concat(totalMiliSecond,".jpg");
Console.WriteLine(fileName);
Are you just using the milliseconds to generate a unique filename? If so, you might be much better using Guid.NewGuid().ToString()
DateTime.UtcNow gives you the current Utc time
new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc) gives you 1970
So you could use:
var savedCounter = Math.Round((DateTime.UtcNow - new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc)).TotalSeconds);
Some alternative naming strategies include:
Given that not many copies of your app were around in 1970, you could probably use a baseline date like new DateTime(2012,1,1,0,0,0)
You could also use a DateTime.ToString format like yyyyMMddhhmmss to achieve a string based on a date - and this might be easier for a human to read (e.g. using the debugger or the isolated storage explorer)
Aside - for performance reasons be aware that you shouldn't create too many files in one directory - http://appangles.com/blogs/mickn/wp7/how-many-files-are-too-many-files-for-windows-phone-7-isolated-storage-performance/ - at some point it makes sense to use a single file instead (e.g. a database)
Either use Time or even better with your current Architecture, save the current Counter into the IsolatedStorageSettings. Its easy to use: http://msdn.microsoft.com/en-us/library/cc221360(v=vs.95).aspx
Even if you use a timestamp to generate the name of the file, if multiple instances of your application can run concurrently, then there's still a chance of conflicts. Regardless of whether or not you use a timestamp, you may want to do something like the following:
Initialize a counter to 0
Generate a name for the file, incorporating the counter into its name.
Try to create the file, opening it for exclusive R/W access and requiring that the file not already exist.
If the file creation failed for some reason, increment the counter and repeat steps 2-4.
In fact, this is most likely what routines like System.IO.Path.GetTempFileName() do.
it will be better to use Guid instead of DateTime.
string fileName = System.Guid.NewGuid() + ".jpg";
Related
This question already has answers here:
How to Generate unique file names in C#
(20 answers)
Closed 4 years ago.
I have this code here that take base 64 string and creates bytes, next I create a file name for these bytes.
byte[] bytes = System.Convert.FromBase64String(landingCells.imageBytes);
var filePath = landingCells.jobNo + DateTime.Now.ToString("yyyyMMddHHmmssffffff");
next I have save these bytes:
System.IO.File.WriteAllBytes("C:/app/Images/" + filePath + ".jpg", bytes);
The problem I am having is I am calling these lines of code in a loop via an iOS app and sometimes the yyyyMMddHHmmssffffff is the same as the previous item in the loop. My question, how can I make the file names more unique so this does not happen.
Try This by using Guid.NewGuid():
var uniquecode=Guid.NewGuid();
var filePath = landingCells.jobNo + DateTime.Now.ToString("yyyyMMddHHmmssffffff")+uniquecode;
Using a date-based name will limit your file creation rate to the frequency of the system clock (and is also not threadsafe) which is why you are seeing duplicate file names when you complete iterations of your loop too quickly. You have several options to make it more unique that depend on what your requirements are:
Add an incrementing counter suffix to the file name when the date is the same as the date of the last file written
Incorporate a GUID into the file name. This will be less readable than the counter suffix but will guarantee uniqueness even across a distributed system and won't require you to maintain a counter.
Incorporate some other original information about the file or its metadata into the name that when combined with the date will be unique
Come up with some custom name generation algorithm that will generate unique names for every (even repeated) input. How you do this depends on the domain you're working within and the data you're dealing with.
I'm not sure what kind app you're building, but it's worth reevaluating whether you actually need to write that many images to disk per second and if you do whether a video would be better. Throttling the writes would probably not be a bad idea and it would also solve the naming problem.
I was thinking of changing system's local time to server's time and then use it but I bet there are other ways to do this. I've been trying to find something like a clock in c#, but couldnt find anything. I'm receiving server's time in a DateTime format.
edit:
I need my application to use while working same time server does. I just want to get server's time once and after that, make my application work in a while loop using the time I've obtained from the server. There might be a difference between my system's time and server's time (even 5 seconds) and that's why I want to do this.
It's not entirely clear what you mean, but you could certainly create your own IClock interface which you'd use everywhere in code, and then write an implementation of that which is regularly synchronized with your server (or with NTP).
My Noda Time project already uses the idea of an injectable clock - not for synchronization purposes, but for testability. (A time service is basically a dependency.) Basically the idea is workable :) You may well not find anything which already does this, but it shouldn't be too hard to write. You'll want to think about how to adjust time though - for example, if the server time gets ahead of your "last server time + local time measurements" you may want to slew it gradually rather than having a discrete jump.
This is always assuming you do want it to be local to your application, of course. Another alternative (which may well not be appropriate, depending on your context) is to require that the host runs a time synchronization client (I believe Windows does by default these days) and simply start failing if the difference between your server and the client gets too large. (It's never going to be exactly in sync anyway, or at least not for long - you'll need to allow for some leeway.)
The answer #JonSkeet's provided to synch the times looks good, I just wanted to point out some things.
As #Alexei already said, users require admin privileges to be able to change their local time (in Windows as least), but there may also be other issues that can cause the time to be out of synch (bad internet connection, hacks etc.). This means there is no guarantee that the client time is indeed the same as the server time, so you will at least need to check the time the request was received serverside anyway. Plus there might also be a usability issue at hand here, would I want an application to be able change the time of my own local machine? Hell no.
To sum things up:
Check the time of the request serverside at least
Don't change the time of the client machine but show some kind of indicator in your application
How to handle the indicator in your application can be done in various ways.
Show a clock in your application (your initial idea) that is periodically synched with the server
Show some kind of countdown ("you can submit after x seconds.."), push a resetCountdown request to the clients when a request is received.
Enable a 'send button' or what ever you have, this would work kind of similar to the countdown.
Just remember, it's nearly impossible validate a request such as this clientside. So you have to build in some checks serverside!
I actually wanted to write a comment but it got kind of long.. :)
Okay a bit of necromancy as this is 6 years old, but had to deal with a similar problem for a network game.
Employed a technique I referred to as "marco-polo" for reasons that will be obvious soon. It requires the two clocks to be able to exchange messages, and its accuracy is dependent on how fast they can do that.
Disclaimer: I am fairly certain I am not the first to do this, and that this is the most rudimentary way to synchronize two clocks. Still I didn't find a documented way of doing so.
At Clock B (The clock we're trying to synchronize) we do the following ::
// Log the timestamp
localTime_Marco_Send = DateTime.UtcNow;
// Send that to clock A
SendSyncRequest();
// Wait for an answer
Sleep(..);
At Clock A (the reference clock) we have the following handler ::
// This is triggered by SendSyncRequest
OnReceiveSyncRequest()
{
// We received "Marco" - Send "Polo"
SendSyncReply(DateTime.UtcNow);
}
And back at Clock B ::
// This is triggered by SendSyncReply
OnReceiveSyncReply(DateTime remoteHalfTime)
{
// Log the time we received it
DateTime localTime_Polo_Receive = DateTime.UtcNow;
// The remote time is somewhere between the two local times
// On average, it will be in the middle of the two
DateTime localHalfTime = localTime_Marco_Send +
(localTime_Polo_Receive - localTime_Marco_Send) / 2;
// As a result, the estimated dT from A to B is
TimeSpan estimatedDT_A_B = localHalfTime - remoteHalfTime;
}
As a result we now have access to a nifty TimeSpan we can subtract from our current local time to estimate the remote time
DateTime estimatedRemoteTime = DateTime.UtcNow - estimatedDT_A_B;
The accuracy of this estimate is subject to the Round Trip Time of send-receive-send-receive, and you should also account for Clock drift (you should be doing this more than once):
Round-trip-time. If it were instant, you'd have the exact dT. If it takes 1 second to come and return, you don't know if the delay was on the sending or the receiving. As a result, your error is 0 < e < RTT, and on average will be RTT/2. If you know send (or receive) takes more than the other, use that to your advantage - the time you received is not the half-time, but is shifted relatively to how long each leg takes
Clock drift. CPU clocks drift, maybe 1s per day. So poll again once potential drift may play an important role.
Your server should always save the time in UTC mode.
You save time in UTC like this in the server:
DateTime utcTime = new DateTime(0, DateTimeKind.Utc);
or:
DateTime utcTimeNow = DateTime.UtcNow;
In the client, when you get the time which is stored in utc you can sonvert it to local time like this:
public DateTime ToLocalTime(DateTime utcTime)
{
//Assumes that even if utcTime kind is no properly deifned it is indeed UTC time
DateTime serverTime= new DateTime(utcTime.Ticks, DateTimeKind.Utc);
return TimeZoneInfo.ConvertTimeFromUtc(serverTime, m_localTimeZone);
}
If You want to change your local time zone , here is a code example on how to read time zone to use from config:
string localTimeZoneId = sysParamsHelper.ReadString(LOCAL_TIME_ZONE_ID_KEY, LOCAL_TIME_ZONE_DEFAULT_ID);
ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
foreach (TimeZoneInfo timeZoneInfo in timeZones)
{
if(timeZoneInfo.Id.Equals(localTimeZoneId))
{
m_localTimeZone = timeZoneInfo;
break;
}
}
if (m_localTimeZone == null)
{
m_logger.Error(LogTopicEnum.AMR, "Could not find time zone with id: " + localTimeZoneId + " . will use default time zone (UTC).");
m_localTimeZone = TimeZoneInfo.Utc;
}
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How can I display the Build number and/or DateTime of last build in my app?
I want to append the last DateTime of when my app was built to the titlebar. But this code:
DateTime lastWriteTime = File.GetLastWriteTime(Assembly.GetExecutingAssembly().GetName().ToString());
this.Text = String.Format("Platypi R Us; Built on {0}", lastWriteTime);
...claims that was over 400 years ago (in the year 1600); I find that unlikely.
The problem is that you've called GetLastWriteTime using something which isn't a filename. Print out Assembly.GetExecutingAssembly().GetName().ToString() and you'll see what I mean.
The documentation for File.GetLastWriteTime calls this out specifically:
If the file described in the path parameter does not exist, this method returns 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC), adjusted to local time.
So, either use Application.ExecutablePath as per Clay's suggestion, or for a specific assembly (or to avoid a WinForms dependency), you could use Application.ManifestModule and get the FullyQualifiedName, like this:
using System;
using System.Reflection;
class Test
{
static void Main()
{
string file = typeof(Test).Assembly
.ManifestModule
.FullyQualifiedName;
Console.WriteLine(file);
DateTime lastWriteTime = File.GetLastWriteTime(file);
Console.WriteLine(lastWriteTime);
}
}
Of course, that only gets the last write time of the module containing the assembly manifest - it's possible to have multi-module assemblies. It's rare though, and my guess is that this will do you fine.
It's a shame that there isn't a concept of a build time embedded within Assembly itself, but such is life :(
This works:
FileInfo fileInfo = new FileInfo(Application.ExecutablePath);
DateTime lastWriteTime = fileInfo.LastWriteTime;
this.Text = String.Format("Platypi R Us; Built on {0}", lastWriteTime);
'GetName()' returns the display name of the assembly. You want Assembly.Location
Also, I'm not sure this will work. If you copy the file to a different location then the file time is out-of-sync with the actual last build time. Maybe manually update it every time you put out a new release?
I need to build a unique filename in a multithreaded application which is serializing some data on the disk.
What approach could I use to ensure a unique name.
The app was not multithreaded before and was using Ticks. When using multiple threads, it failed much faster than I expected.
I now added the CurrentThreadId to the filename, and that should do it
string.Format("file_{0}_{1}.xml", DateTime.Now.Ticks, Thread.CurrentThread.ManagedThreadId)
Is there any "smarter" way of doing this?
What about Guid.NewGuid() instead of the thread id?
string.Format("file_{0}_{1:N}.xml", DateTime.Now.Ticks, Guid.NewGuid())
By keeping the ticks as part of the name, the names will still be in approximate date order if ordering is important.
The {1:N} gets rid of the curly braces and dashes in the guid.
Also, consider using DateTime.UtcNow.Ticks, so as to guarantee incremental ticks when daylight saving time kicks in.
Depending on your needs you can try:
System.IO.Path.GetTempFileName();
This creates a uniquely named temporary file in the %temp% directory. I suppose you can copy the file to your target location before or after writing to it.
To actually reserve the filename you will have to create the file immediately and check for exceptions.
Another option would be to include a Guid value in your filename.
How about
Guid.NewGuid().ToString()
every time i create a FileInfo object and access it's lastaccesstime property, it's always a few minutes off. the file property window remains constant, however the application shows that it is usually a few minutes after the property window time.
Also, i noticed that if i drag the file to the cmd window to pass the filename as an argument, the access time updates most of the time, but not always.
What could be causing this ?
below is an example:
static void Main(string[] args)
{
if (args.Length > 0)
{
FileInfo fi = new FileInfo(args[0].ToString());
Console.WriteLine(args[0]);
if (fi.Exists)
{
Console.Write("Current: " + DateTime.Now + "\n");
Console.Write("LAT: " + fi.LastAccessTime + "\n");
Console.Write("LWT: " + fi.LastWriteTime + "\n");
Console.Write("CT: " + fi.CreationTime + "\n");
}
Console.ReadKey();
}
}
alt text http://img407.imageshack.us/img407/4728/propertiesox6.png
alt text http://img380.imageshack.us/img380/7752/appgt0.png
In my experience, last access time is notoriously unreliable. According to http://technet.microsoft.com/en-us/library/cc781134.aspx...
The Last Access Time on disk is not always current because NTFS looks for a one-hour interval before forcing the Last Access Time updates to disk. NTFS also delays writing the Last Access Time to disk when users or programs perform read-only operations on a file or folder, such as listing the folder’s contents or reading (but not changing) a file in the folder.
Apparently, the in-memory copy will be correct, but in my experience, you may get a cached value which may be out of date. Also, note that last access time may be turned off by the user, and is turned off by default in Vista and 2008.
The MSDN article with basic info about file times has this to say about file time resolution and Last Access times:
For example, on FAT, create time has a resolution of 10 milliseconds, write time has a resolution of 2 seconds, and access time has a resolution of 1 day (really, the access date). NTFS delays updates to the last access time for a file by up to one hour after the last access.
This would imply that on both FAT and NTFS, the Last Write Time will generally not be very precise, although I'm not sure the exact values they quote are correct.
Hmm, possibly this from MSDN:
When first called, FileSystemInfo
calls Refresh and returns the cached
information on APIs to get attributes
and so on. On subsequent calls, you
must call Refresh to get the latest
copy of the information.
But you are seeing the LAT always being a few minutes in the [future|past]?