نمایش نتایج 1 تا 2 از 2

نام تاپیک: راه جایگزین برای تابع SetFileTime

  1. #1
    کاربر دائمی آواتار persia_hrn
    تاریخ عضویت
    آذر 1390
    محل زندگی
    شیراز
    پست
    142

    راه جایگزین برای تابع SetFileTime

    سلام خدمت همه اساتید عزیز

    سوال اصلی من اینه که آیا راه جایگزینی بجای استفاده از تابع SetFileTime جهت تغییر تاریخهای موجود در فایلها (CreationTime, LastAccessTime, LastWriteTime) وجود دارد ؟

    علت این خواسته اینه که قبل از استفاده از این تابع ، مجبوریم زمان رو با تابع DateTimeToFileDate به Integer در 2 رنج Hi , Lo که هرکدوم 16بیته تبدیل کنیم :
    function DateTimeToFileDate(DateTime: TDateTime): Integer;
    var
    Year, Month, Day, Hour, Min, Sec, MSec: Word;
    begin
    DecodeDate(DateTime, Year, Month, Day);
    if (Year < 1980) or (Year > 2099) then Result := 0 else
    begin
    DecodeTime(DateTime, Hour, Min, Sec, MSec);
    LongRec(Result).Lo := (Sec shr 1) or (Min shl 5) or (Hour shl 11);
    LongRec(Result).Hi := Day or (Month shl 5) or ((Year - 1980) shl 9);
    end;
    end;


    همینجور که می بینید در اینجا میلی ثانیه از دست میره و همچنین ثانیه تقسیم بر 2 میشه (Sec Shr 1) که خودش یه مشکل ایجاد میکنه (مثلا اگر شما 35 ثانیه رو در نظر بگیرید بعد از تبدیل میشه 34 ثانیه چون تقسیم بر 2 این عدد صحیح نیست و اعشارش از دست میره).

    و در نهایت با دستورات زیر میشه تاریخ یک فایل رو تغییر داد :
    function MyFileSetDate(Handle: Integer; Age: Integer): Integer;
    var
    LocalFileTime, FileTime: TFileTime;
    begin
    Result := 0;
    if DosDateTimeToFileTime(LongRec(Age).Hi, LongRec(Age).Lo, LocalFileTime) and
    LocalFileTimeToFileTime(LocalFileTime, FileTime) and
    SetFileTime(Handle, @FileTime, @FileTime, @FileTime) then Exit;
    Result := GetLastError;
    end;


    خب حالا برای جلوگیری از اینکه میلی ثانیه از دست بره و ثانیه تقسیم به 2 نشه ما میتونیم تابعی بنویسیم که Int64 رو برگردونه ، به اینصورت :
    function MyDateTimeToFileDate(DateTime: TDateTime): Int64;
    var
    Year, Month, Day, Hour, Min, Sec, MSec: Word;
    begin
    DecodeDate(DateTime, Year, Month, Day);
    if (Year < 1980) or (Year > 2099) then Result := 0 else
    begin
    DecodeTime(DateTime, Hour, Min, Sec, MSec);
    Int64Rec(Result).Lo := Msec or (Sec shl 10) or (Min shl 16) or (Hour shl 22);
    Int64Rec(Result).Hi := Day or (Month shl 5) or ((Year - 1980) shl 9);
    end;
    end;


    و به اینصورت استفادش کنیم :
    function MyFileSetDate(Handle: Integer; Age: Int64): Integer;
    var
    LocalFileTime, MyFileTime: TFileTime;
    begin
    Result := 0;
    LocalFileTime.dwHighDateTime:=Int64Rec(Age).Hi;
    LocalFileTime.dwLowDateTime:=int64rec(Age).Lo;
    if LocalFileTimeToFileTime(LocalFileTime, MyFileTime) and SetFileTime(Handle, @MyFileTime, @MyFileTime, @MyFileTime) then
    Exit;
    Result := GetLastError;
    end;


    ولی در نهایت به دلیل ساختار تابع SetFileTime تلاشمون نیمه کاره میمونه . چرا که این کار در درایوهایی با FAT32 ارور میده و در درایوهای NTFS انجام میشه ولی تاریخ و ساعتش خیلی اشکال داره !

    طبق توضیحات مایکروسافت که لینکشم پایین میذارم ، این تابع 2 متغیر dwLowDateTime و dwHighDateTime از نوع DWord داره .
    https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfiletime

    این رو میدونم که خود ویندوز زمان ساخته شدن فایل میلی ثانیه رو هم در ساختار فایل درنظر میگیره :

    فایل ساخته شده در درایو FAT32 :
    FAT32.jpg

    فایل ساخته شده در درایو NTFS :
    NTFS.jpg

    از شما اساتید محترم تقاضا دارم اگر ایرادی در کار من هست بهم اطلاع بدید و یا اگر راه دیگه ای میشناسید که میلی ثانیه رو از دست نده ممنون میشم راهنماییم کنید .
    عکس های ضمیمه عکس های ضمیمه


  2. #2

    نقل قول: راه جایگزین برای تابع SetFileTime

    با سلام،
    میتونید از یونیت IOUtils و قابلیتهای اون استفاده کنید. این یونیت از زمان دلفی 2010 اضافه شده. اگر به این یونیت نگاه کنید رکورد TFile را میبینید که شامل متدهای مختلفی است که برای مسئله ای که مطرح کردید میتوانید از متدهایی که در زیر لیست کرده ام استفاده نمایید:
        class procedure SetCreationTime(const Path: string; const CreationTime: TDateTime); inline; static;    class procedure SetCreationTimeUtc(const Path: string; const CreationTime: TDateTime); inline; static;
    class procedure SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime); inline; static;
    class procedure SetLastAccessTimeUtc(const Path: string; const LastAccessTime: TDateTime); inline; static;
    class procedure SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime); inline; static;
    class procedure SetLastWriteTimeUtc(const Path: string; const LastWriteTime: TDateTime); inline; static;


    موفق و سربلند باشید

تاپیک های مشابه

  1. پاسخ: 7
    آخرین پست: شنبه 26 مرداد 1392, 01:34 صبح
  2. سوال: چگونه توسط ASP در #C یک تست چهار گزینه ای بسازیم؟
    نوشته شده توسط Black Shadow در بخش C#‎‎
    پاسخ: 4
    آخرین پست: دوشنبه 16 اردیبهشت 1392, 15:32 عصر
  3. پاسخ: 4
    آخرین پست: سه شنبه 14 شهریور 1391, 17:39 عصر
  4. پاسخ: 0
    آخرین پست: دوشنبه 02 مرداد 1391, 05:44 صبح
  5. پاسخ: 3
    آخرین پست: پنج شنبه 04 تیر 1388, 22:35 عصر

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •