Tengo mi smartphone configurado para que las fotografías y vídeos se guarden en una SD. Tras copiar las fotos de una SD a otra de mayor tamaño me llevé la desagradable sorpresa del desorden.
Vi que el problema era que la fecha de creación de archivos había cambiado a la actual, como es lógico en un archivo nuevo, así que decidí dar una solución.
Android coloca en el nombre del archivo la fecha y hora de realización de la fotografía. WhatsApp también lo hace, aunque no pone la hora. Por otro lado, la fecha de modificación del archivo, que coincide con la fecha de creación al tomar la fotografía no suele alterarse al copiarla a otra SD o al HD.
Con este conocimiento hice esta pequeña aplicación que trata de codificar la fecha y hora desde el nombre de archivo, y si no lo consigue toma la fecha y hora de la fecha de última modificación del archivo para colocarla como fecha y hora de creación del mismo. También hace lo mismo con la fecha de las subcarpetas y de sus archivos, pues la búsqueda se hace de un modo recursivo si el usuario lo quiere.
Una advertencia, debe usarse sacando la microSD y conectándola al PC,
La primera versión la hice en Builder C++ y me he decidido traducirlo a delphi7 para compartirlo.
Aquí esta la fuente del programita que subo con el binario.
const FILE_READ_ATTRIBUTES = $0080; FILE_WRITE_ATTRIBUTES = $0100; //--------------------------------------------------------------------------- function EnablePrivilege(name: String; Enable: boolean = true): boolean; var hToken: Cardinal; priv: TOKEN_PRIVILEGES; begin priv.PrivilegeCount:= 1; priv.Privileges[0].Attributes:= 0; if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED; LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid); OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken); AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), nil, PDWORD(nil)^); Result:= (GetLastError = ERROR_SUCCESS); CloseHandle (hToken); end; //--------------------------------------------------------------------------- function FileNameToFileTime(FileName: String): TFILETIME; var ST: TSYSTEMTIME; Name, Data: String; i: integer; begin ZeroMemory(@ST, sizeof(TSYSTEMTIME)); ZeroMemory(@Result, sizeof(TFILETIME)); Name:= ExtractFileName(FileName); // tomo solo dígitos en Data for i:= 1 to Length(Name) do if Name[i] in ['0'..'9'] then Data:= Data + Name[i]; if Length(Name) >= 8 then begin ST.wYear:= StrToIntDef(Copy(Data, 1, 4), 0); ST.wMonth:= StrToIntDef(Copy(Data, 5, 2), 0); ST.wDay:= StrToIntDef(Copy(Data, 7, 2), 0); end; if Length(Name) >= 14 then begin ST.wHour:= StrToIntDef(Copy(Data, 9, 2), 0); ST.wMinute:= StrToIntDef(Copy(Data, 11, 2), 0); ST.wSecond:= StrToIntDef(Copy(Data, 13, 2), 0); end; if Length(Name) >= 8 then SystemTimeToFileTime(ST, Result); end; //--------------------------------------------------------------------------- function ModifyToCreationFile(FileName: String): boolean; var hFile: THANDLE; FileTime: TFILETIME; begin Result:= FALSE; hFile:= CreateFile(PCHAR(FileName), FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES, 0, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); //GENERIC_READ|FILE_GENERIC_WRITE if hFile <> THANDLE(1) then begin FileTime:= FileNameToFileTime(FileName); Result:= boolean(FileTime.dwLowDateTime or FileTime.dwHighDateTime); if(not Result) then Result:= GetFileTime(hFile, nil, nil, @FileTime); if(Result and LocalFileTimeToFileTime(FileTime, FileTime)) then Result:= SetFileTime(hFile, @FileTime, @FileTime, @FileTime); end; CloseHandle(hFile); end; //--------------------------------------------------------------------------- procedure Cambia(Dir: String; SubDir: boolean = true); var sr: TSearchRec; begin if (Dir <> '') and (FindFirst(Dir + '\*.*', faAnyFile, sr) = 0) then repeat begin Application.ProcessMessages(); if (sr.Name <> '.') and (sr.Name <> '..') then begin if (sr.Attr and faDirectory) <> 0 then begin ModifyToCreationFile(Dir); if(SubDir) then Cambia(Dir + '\' + sr.Name, true); end else ModifyToCreationFile(Dir + '\' + sr.Name); end; end; until FindNext(sr) <> 0; FindClose(sr); end; //--------------------------------------------------------------------------- procedure TForm1.FormCreate(Sender: TObject); begin EnablePrivilege('SeBackupPrivilege', true); EnablePrivilege('SeRestorePrivilege', true); end; //--------------------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); begin Button1.Caption:= 'Trabajando'; Button1.Update(); Cambia(Edit1.Text, CheckBox1.Checked); Windows.Beep(1000, 100); Button1.Caption:= 'Go'; Button1.Update(); end;
Espero que os sea tan útil como me fue a mi.
Saludos.