I remember there was a WinAPI function which copied the "date modified" property of the previous file which was replaced with it or something like that? Perhaps anyone can tell me about it?
The problem occured when you used that function very frequently.
This is ReplaceFile (Windows 2000 and up):
The ReplaceFile function combines
several steps within a single
function. An application can call
ReplaceFile instead of calling
separate functions to save the data to
a new file, rename the original file
using a temporary name, rename the new
file to have the same name as the
original file, and delete the original
file. Another advantage is that
ReplaceFile not only copies the new
file data, but also preserves the
following attributes of the original
file:
Creation time
Short file name
Object identifier
DACLs
Encryption
Compression
Named streams not already
in the replacement file
Not too clear exactly what you want, but it seems your after SetFileTime to edit and GetFileTime to copy, combining the two you can do exactly as 'described/wanted'
Related
Trying this I have found a strange problem:
Delete an old file.
Create a new file and name it the same as the old file.
Then the "created time" property of the new file is set to the "created time" of the old file. Why does that happen? And how?
It's due to file system tunnelling, as explained by Raymond Chen:
"Why does tunneling exist at all?
When you use a program to edit an existing file, then save it, you expect the original creation timestamp to be preserved, since you're editing a file, not creating a new one. But internally, many programs save a file by performing a combination of save, delete, and rename operations (such as the ones listed in the linked article), and without tunneling, the creation time of the file would seem to change even though from the end user's point of view, no file got created.
As another example of the importance of tunneling, consider that file "File with long name.txt", whose short name is say "FILEWI~1.TXT". You load this file into a program that is not long-filename-aware and save it. It deletes the old "FILEWI~1.TXT" and creates a new one with the same name. Without tunnelling, the associated long name of the file would be lost. Instead of a friendly long name, the file name got corrupted into this thing with squiggly marks. Not good."
The NT file system does not delete a file when you think it does. When you delete a file on an NT file system the operating system simply marks the disk space that file occupied as available. The file will not be truly deleted until another file is written to that location on disk.
As to why Windows would think it was the same exact file I believe this is due to the fact that the file was empty when you deleted it so creating a new file in the same location with the same name and the same (empty) contents makes Windows think it is in fact the same file. I would consider this to be a bug.
As a side note, the fact that Windows handles file deletes in this way is the very reason that you are able to use file-recovery utilities to recover deleted files.
You can update creation time with this command manually:
powershell (ls YourFile.txt).CreationTime = Get-Date
... and the same in a batch file:
call powershell "(ls YourFile.txt).CreationTime = Get-Date"
Seems like it must be easy, but I just can't figure it out. How do you delete the very last character of a file using Ruby IO?
I took a look at the answer for deleting the last line of a file with Ruby but didn't fully understand it, and there must be a simpler way.
Any help?
There is File.truncate:
truncate(file_name, integer) → 0
Truncates the file file_name to be at most integer bytes long. Not available on all platforms.
So you can say things like:
File.truncate(file_name, File.size(file_name) - 1)
That should truncate the file with a single system call to adjust the file's size in the file system without copying anything.
Note that not available on all platforms caveat though. File.truncate should be available on anything unixy (such as Linux or OSX), I can't say anything useful about Windows support.
I assume you are referring to a text file. The usual way of changing such is to read it, make the changes, then write a new file:
text = File.read(in_fname)
File.write(out_fname, text[0..-2])
Insert the name of the file you are reading from for in_fname and the name of the file you are writing to for 'out_fname'. They can be the same file, but if that's the intent it's safer to write to a temporary file, copy the temporary file to the original file then delete the temporary file. That way, if something goes wrong before the operations are completed, you will probably still have either the original or temporary file. text[0..-2] is a string comprised of all characters read except for the last one. You could alternatively do this:
File.write(out_fname, File.read(in_fname, File.stat(in_fname).size-1))
Is the ReplaceFile Windows API a convenience function only, or does it achieve anything beyond what could be coded using multiple calls to MoveFileEx?
I'm currently in the situation where I need to
write a temporary file and then
rename this temporary file to the original filename, possibly replacing the original file.
I thought about using MoveFileEx with MOVEFILE_REPLACE_EXISTING (since I don't need a backup or anything) but there is also the ReplaceFile API and since it is mentioned under Alternatives to TxF.
This got me thinking: Does ReplaceFile actually do anything special, or is it just a convenience wrapper for MoveFile(Ex)?
I think the key to this can be found in this line from the documentation (my emphasis):
The replacement file assumes the name of the replaced file and its identity.
When you use MoveFileEx, the replacement file has a different identity. Its creation date is not preserved, the creator is not preserved, any ACLs are not preserved and so on. Using ReplaceFile allows you to make it look as though you opened the file, and modified its contents.
The documentation says it like this:
Another advantage is that ReplaceFile not only copies the new file data, but also preserves the following attributes of the original file:
Creation time
Short file name
Object identifier
DACLs
Security resource attributes
Encryption
Compression
Named streams not already in the replacement file
For example, if the replacement file is encrypted, but the
replaced file is not encrypted, the resulting file is not
encrypted.
Any app that wants to update a file by writing to a temp and doing the rename/rename/delete dance (handling all the various failure scenarios correctly), would have to change each time a new non-data attribute was added to the system. Rather than forcing all apps to change, they put in an API that is supposed to do this for you.
So you could "just do it yourself", but why? Do you correctly cover all the failure scenarios? Yes, MS may have a bug, but why try to invent the wheel?
NB, I have a number of issues with the programming model (better to do a "CreateUsingTemplate") but it's better than nothing.
I got some problem with using FindFirstFile/FindNextFile. As I know it returns a handle but I'm not capable to use it with CreateFileMapping/ReadFile because value of returned handle is different than returned from CreateFile. First question: What's the difference between these two handles and the second: is it possible to convert this handle? My only idea is to get the file name and than use CreateFile.
Regards
What's the difference between these two handles
The first one is search handle. Underneath, there's an iterator reading the directory entry in the file system.
The second one is an iterator reading the file content. The file may even be on another volume than the directory entry you've used to locate it. To learn more about that, google "B-Tree" and then "NTFS"
get the file name and than use CreateFile
Yes, but you need to combine directory + file name. I usually call PathAppend API (CPathT::Append, to be precise) to do that.
Trying this I have found a strange problem:
Delete an old file.
Create a new file and name it the same as the old file.
Then the "created time" property of the new file is set to the "created time" of the old file. Why does that happen? And how?
It's due to file system tunnelling, as explained by Raymond Chen:
"Why does tunneling exist at all?
When you use a program to edit an existing file, then save it, you expect the original creation timestamp to be preserved, since you're editing a file, not creating a new one. But internally, many programs save a file by performing a combination of save, delete, and rename operations (such as the ones listed in the linked article), and without tunneling, the creation time of the file would seem to change even though from the end user's point of view, no file got created.
As another example of the importance of tunneling, consider that file "File with long name.txt", whose short name is say "FILEWI~1.TXT". You load this file into a program that is not long-filename-aware and save it. It deletes the old "FILEWI~1.TXT" and creates a new one with the same name. Without tunnelling, the associated long name of the file would be lost. Instead of a friendly long name, the file name got corrupted into this thing with squiggly marks. Not good."
The NT file system does not delete a file when you think it does. When you delete a file on an NT file system the operating system simply marks the disk space that file occupied as available. The file will not be truly deleted until another file is written to that location on disk.
As to why Windows would think it was the same exact file I believe this is due to the fact that the file was empty when you deleted it so creating a new file in the same location with the same name and the same (empty) contents makes Windows think it is in fact the same file. I would consider this to be a bug.
As a side note, the fact that Windows handles file deletes in this way is the very reason that you are able to use file-recovery utilities to recover deleted files.
You can update creation time with this command manually:
powershell (ls YourFile.txt).CreationTime = Get-Date
... and the same in a batch file:
call powershell "(ls YourFile.txt).CreationTime = Get-Date"