CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - FILETIME vs. String

FILETIME vs. String

dział ogólny

FILETIME vs. String

Nowy postprzez mckri » poniedziałek, 3 stycznia 2011, 08:46

Witam.
Robię program, który sciaga dane z FTP do przestrzeni lokalnej i dla pobranych plików ustawia datę wg FTP.
Potrzebuje z różnych powodów do ciągu znaków typu String dokleić wartość daty pliku jako typ FILETIME, aby przekazać ją do innej funkcji.
Kompilator odmawia jednak wykonania takiej konwersji.
Przykład kodu:
Kod: Zaznacz cały
WIN32_FIND_DATA  fd;
FILETIME  data_pliku;
...
nazwa_pliku=fd.cFileName
data_pliku=fd.ftLastWriteTime;   

Form1->ListaPlikow->Add(nazwa_pliku+"*"+(String)data_pliku); //tutaj sklejam potrzebne dane o pliku. Kompilator wywala błąd konwersji!


Muszę korzystać z typu WIN32_FIND_DATA, gdyż listuję katalogi z FTP. Typ FILETIME jest mi potrzebny z koleji do tego abym poźniej mógł dla pobranego pliku ustawić datę wg pliku z FTP.

Czy jest jakiś sposób na konwersję wartości FILETIME (np. do String), abym w tej innej funkcji mógł odtworzyć wartość czasu z FTP?

Pozdrawiam.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez Corvis » poniedziałek, 3 stycznia 2011, 11:37

"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: FILETIME vs. String

Nowy postprzez Cyfrowy Baron » poniedziałek, 3 stycznia 2011, 12:39

Nie no Corvis, po Tobie spodziewałbym się czegoś więcej niż linków odsyłających w tak prostej sprawie.



FILETIME to struktura, więc nie możesz jej przypisywać bezpośrednio do żadnej zmiennej. Struktura zawiera dwie zmienne typu DWORD - dwLowDateTime i dwHighDateTime, czyli data krótka i data długa. W celu odczytania daty z tej struktury trzeba posłużyć się funkcją np. FileTimeToSystemTime, która to funkcja dokona konwersji z FILETIME na SYSTEMTIME podając datę w systemie UTC. Dobrze byłoby więc prze-konwertować czas z UTC na czas lokalny, w przeciwnym razie czas będzie pokazywany -1 godzina w stosunku do czasu w Polsce. Konwersji można dokonać za pomocą funkcji SystemTimeToTzSpecificLocalTime. Potem wystarczy już posłużyć się funkcją SystemTimeToDateTime by dokonać konwersji z SYSTEMTIME na TDateTime. Po wszystkim wystarczy dokonać konwersji TDateTime na String z wykorzystaniem funkcji FormatString lub FormatDateTime.
KOD cpp:     UKRYJ  
 /* tylko na potrzeby przykładu, pobieram informacje o pliku lokalnym */
 OFSTRUCT ofStr;
 HANDLE hFile = (THandle *)OpenFile("c:\\plik.txt", &ofStr, OF_READ);


 FILETIME ftCreate, ftAccess, ftWrite;

 if(!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
 {
  ShowMessage("Błąd");
  return;
 }
 /* koniec pobierania informacji o pliku lokalnym, dalej następuje konwersja daty z FILETIME */

 SYSTEMTIME stUTC, stLocal;
 FileTimeToSystemTime(&ftWrite, &stUTC); /* ftWrite - data ostatniego dostępu do pliku */
 SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

 TDateTime fDateTime = SystemTimeToDateTime(stLocal);

 String sData1 = fDateTime.FormatString("dddd dd mmmm yyyy; hh:nn:ss");

 String sData2 = FormatDateTime("dddd dd mmmm yyyy; hh:nn:ss", fDateTime);


A wszystko to jest w pliku pomocy.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
mckri
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: FILETIME vs. String

Nowy postprzez Corvis » poniedziałek, 3 stycznia 2011, 12:43

W tym przypadku chodziło mi o pokazanie, że GOOGLE i HELP nie gryzą. Ok następnym razem podam linki i rozwiązanie.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: FILETIME vs. String

Nowy postprzez mckri » poniedziałek, 3 stycznia 2011, 16:02

Ok, naprowadziliście mnie bo zacząłem zbyt mocno kombinować. Dziękuję.
@Corvis, wierz mi, ze uderzam na forum tylko wtedy gdy już nie wiem jak sobie poradzić. Czasami to wynika z tymczasowej 'zaćmy' lub faktycznej niewiedzy. Podejrzewam, że Tobie też to się zdarza, więc proszę bez tego typu uwag.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez mckri » wtorek, 1 lutego 2011, 00:03

Nie chcę rozpoczynać nowego wątku.
Problem mam taki. Korzystam w programie z 2 funkcji do odczytywania daty pliku. Jedna metoda wchodzi w skład TSearchRec, druga to GetFileTime.
Dlaczego w obu funkcjach (mimo prób konwersji do czasu lokalnego) nie mogę uzyskac spójnego czasu???
W obu funkcjach badam ten sam plik. W Windowsie pokazuje mi czas pliku: 27.10.2010 19:56:00

Kod: Zaznacz cały
//-----------------
//czytanie z filetime
        String local="";
   HANDLE hFile = CreateFile((E1->Text).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
   if(hFile!=0)
   {
    FILETIME ftC, ftA, ftW;
    SYSTEMTIME stutc;
         TIME_ZONE_INFORMATION tziOld;
    GetFileTime(hFile, &ftC, &ftA, &ftW);
    FileTimeToSystemTime(&ftW, &stutc);
         GetTimeZoneInformation(&tziOld);
         SystemTimeToTzSpecificLocalTime(&tziOld, &stutc, &stutc);
         local=SystemTimeToDateTime(stutc).FormatString("dd.MM.yyyy hh:nn:ss");//czas zwiększony o 1 godzine względem windows
    CloseHandle(hFile);
   }


       
        //czytanie z tsearchrec
        String local4, local5;
        TSearchRec sr;
   if(FindFirst(E1->Text,faAnyFile, sr)==0)
   {
          local4=FileDateToDateTime(sr.Time).FormatString("dd.MM.yyyy hh:nn:ss");   //czas zgodny z tym co pokazuje windows
          TDateTime dataplk=FileDateToDateTime(sr.Time);
          SYSTEMTIME stutc2, stlocal2;
          TIME_ZONE_INFORMATION tziOld;
          GetTimeZoneInformation(&tziOld);
          DateTimeToSystemTime(dataplk,stutc2);
          SystemTimeToTzSpecificLocalTime(&tziOld, &stutc2, &stlocal2);
          local5=SystemTimeToDateTime(stlocal2).FormatString("dd.MM.yyyy hh:nn:ss"); //Konwersja do czasu lokalnego. Czas zwiększony o 2 godziny względem tego co pokazuje windows. Nic nie rozumiem.
   }
   FindClose(sr);



I tak. Korzystając z GetFileTime uzyskuje czas dla zmiennej local = 27.10.2010 20:56:00 - zwiększony o 1 godzinę. Z funkcji TSearchRec zmienna local4 = 27.10.2010 19:56:00 - czyli prawidłowo, local5 = 27.10.2010 21:56:00 (konwersja do czasu lokalnego) czyli zwiększony o 2 godziny.
Wydaje się, że metoda TSearchRec (bez konwersji do UTC) działa ok. Jednak czego mi brakuje w funkcji GetFileTime, że jest różnica w odczycie.
Jak zegrać odczyty czasu z przy pomocy tych 2 metod? Co uzyć, aby uzyskać odczyt tych samych wartości daty pliku?
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez Cyfrowy Baron » wtorek, 1 lutego 2011, 12:23

W przypadku funkcji GetFileTime nie stosuje się korekcji czasu w stosunku do UTC, gdyż ta funkcja zawsze stosuje czas lokalny. Ty natomiast wprowadzasz korekcję funkcją SystemTimeToTzSpecificLocalTime, stąd ta różnica. Dziwi mnie, że sam na to nie wpadłeś. Nie wszystkie funkcje wymagają korekcji czasu.

Przykład użycia funkcji GetFileTime:

KOD cpp:     UKRYJ  
 FILETIME aFT, bFT, cFT;
 SYSTEMTIME ST;
 TDateTime DT;

 AnsiString name = "C:\\nazwa_pliku.roz";
 HANDLE hFile = CreateFile(name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);

 GetFileTime(hFile, &aFT, &bFT, &cFT);

 FileTimeToSystemTime(&aFT, &ST);
 DT = SystemTimeToDateTime(ST);

 Label1->Caption = FormatDateTime("dd.mm.yyy  hh:nn:ss", DT);
 CloseHandle(hFile);
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: FILETIME vs. String

Nowy postprzez mckri » wtorek, 1 lutego 2011, 13:15

Baronie, czy porównywałeś wyniki odczytu daty pliku z tych dwóch funkcji?
Jeżeli usunę konwersje z UTC do czasu lokalnego, wtedy odczyt daty poprzez funkcję GetFileTime powoduje wyświetlenie daty -1 godzina względem daty, którą widzę w Windows.
Pytanie nadal aktualne. Jak wyniku działania TSearchRec i GetFileTime uzyskać taką samą datę?
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez Cyfrowy Baron » wtorek, 1 lutego 2011, 14:46

Co się tyczy TSearchRect to nie należy wprowadzać korekty czasu, a czasy będą prawidłowe:

KOD cpp:     UKRYJ  
#include "DateUtils.hpp"

 if(OpenDialog1->Execute())
 {
  AnsiString name = OpenDialog1->FileName;
  TSearchRec sr;
  if(FindFirst(name, faAnyFile, sr) == 0)
  {
   Edit2->Text = FileDateToDateTime(sr.Time).FormatString("dd.MM.yyyy hh:nn:ss");

   TDateTime dataplk = FileDateToDateTime(sr.Time);
   Edit3->Text = FormatDateTime("dd.mm.yyy  hh:nn:ss", dataplk);

   SYSTEMTIME stutc2, stlocal2;
   DateTimeToSystemTime(dataplk, stutc2);

   Edit4->Text = SystemTimeToDateTime(stutc2).FormatString("dd.MM.yyyy hh:nn:ss");
  }
  FindClose(sr);
 }


Co się zaś tyczy GetFileTime, to rzeczywiście korekta jest potrzebna i działa prawidłowo dla daty utworzenia pliku oraz daty ostatniego dostępu dla pliku, ale nie zgadza się dla daty modyfikacji pliku. Trzeba najwyraźniej ręcznie wprowadzić korektę 1 godziny:

KOD cpp:     UKRYJ  
 if(OpenDialog1->Execute())
 {
  FILETIME lpCreationTime, pLastAccessTime, lpLastWriteTime;
  SYSTEMTIME stUTC, stLocal;
  TDateTime DT;

  AnsiString name = OpenDialog1->FileName;
  OFSTRUCT ofStr;
  HANDLE hFile = (THandle *)OpenFile(name.c_str(), &ofStr, OF_READ);

  GetFileTime(hFile, &lpCreationTime, &pLastAccessTime, &lpLastWriteTime);

  FileTimeToSystemTime(&lpLastWriteTime, &stUTC);

  SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stUTC);
  DT = SystemTimeToDateTime(stUTC) - IncHour(1);

  Edit1->Text = FormatDateTime("dd.mm.yyy  hh:nn:ss", DT);
  CloseHandle(hFile);
 }
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: FILETIME vs. String

Nowy postprzez mckri » wtorek, 1 lutego 2011, 23:13

Trochę dziwaczne to odejmowanie godzin. Zauwazyłem, że w Twoim przykładzie funkcja IncHour oprócz tego że odejmuje godzinę, to odejmuje równiez dzień.
Rozwiązałem to w ten sposób.
Kod: Zaznacz cały
EncodeDateTime(stUTC.wYear,stUTC.wMonth,stUTC.wDay,[b]stUTC.wHour-1[/b],stUTC.wMinute,stUTC.wSecond,stUTC.wMilliseconds);

Teraz odejmowana jest tylko godzina. Czas pliku się już zgadza.
Jednak wątpię, aby odejmowanie godzin było tutaj rozwiązaniem własciwym. Dla naszej strefy czasowej pewnie wystarczy.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez Cyfrowy Baron » wtorek, 1 lutego 2011, 23:48

Zauwazyłem, że w Twoim przykładzie funkcja IncHour oprócz tego że odejmuje godzinę, to odejmuje równiez dzień.


Nic podobnego, funkcja IncHour odejmuje tylko godzinę, do odejmowania dnia jest IncDay. U mnie z korektą czas pokazywany jest prawidłowo, w wszystkich trzech przykładach. Nie rozumiem skąd u Ciebie to odejmowanie dnia się wzięło.

Jednak wątpię, aby odejmowanie godzin było tutaj rozwiązaniem własciwym. Dla naszej strefy czasowej pewnie wystarczy.


Jeżeli działa w jednej strefie czasowej to będzie działać we wszystkich, dla tego samego Windowsa. Sądzę, że to jakiś błąd funkcji, gdyż problem dotyczy tylko daty modyfikacji pliku, a jeżeli u Ciebie funkcja IncHour odejmuje również dzień, to coś jest nie tak z bibliotekami.


Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: FILETIME vs. String

Nowy postprzez mckri » środa, 2 lutego 2011, 09:11

Sprawdziłem Twój program. Badałem ten sam plik dla obu przypadków.
Plik u mnie w Windows ma datę ostatniej modyfikacji: 09.10.2010 09:26:00
Stwierdzam, że dla pierwszego buttona odczytywana jest wartość: 08.10.2010 09:26:00, dla drugiego buttona data jest taka sama, czyli 09.10.2010 09:26:00. Sprawdziłem Twój program równiez na innym kompie z systemem Win XP i zachowuje się tak samo.
Źle uzyłeś funkcji IncHour. Zapis powinien wyglądać.
Kod: Zaznacz cały
DT = SystemTimeToDateTime(stUTC) - IncHour(DT,1); //Nie zagłębiałem się '+' czy '-'
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera

Re: FILETIME vs. String

Nowy postprzez Cyfrowy Baron » środa, 2 lutego 2011, 12:44

U mnie dziś też wskazał nieprawidłowe odejmowanie



Źle uzyłeś funkcji IncHour. Zapis powinien wyglądać.


Opis funkcji z pliku pomocy środowiska Embarcadero RAD Studio C++Builder 2010 wskazuje, że powinno być tak jak mówisz, jednak, gdyby było to błędem, to nie dałoby się skompilować, gdyż funkcja oczekuje dwóch argumentów, a ja podałem jeden. Dlaczego program mimo to działa i to tak samo, niezależnie od tego iel tych argumentów podam?
Testy wykazały, że to co Ty zrobiłeś też nie będzie działać dobrze, gdyż jak się okazuje, nie dla każdego pliku wymagana jest korekta. To nie zadziała.



Zadałem sobie trochę trudu i dokładnie przejrzałem plik pomocy. Jak już wiadomo FILETIME jest zapisany w UTC (Universal Time Coordinated), ale konwersji do czasu lokalnego nie można robić z wykorzystaniem funkcji SystemTimeToTzSpecificLocalTime, lecz należy użyć funkcji FileTimeToLocalFileTime, więc tak to powinno wyglądać:

KOD cpp:     UKRYJ  
 if(OpenDialog1->Execute())
 {
  FILETIME lpCreationTime, pLastAccessTime, lpLastWriteTime;
  SYSTEMTIME stUTC, stLocal;
  TDateTime DT;

  AnsiString name = OpenDialog1->FileName;
  OFSTRUCT ofStr;
  HANDLE hFile = (THandle *)OpenFile(name.c_str(), &ofStr, OF_READ);

  GetFileTime(hFile, &lpCreationTime, &pLastAccessTime, &lpLastWriteTime);

  FileTimeToLocalFileTime(&lpLastWriteTime, &lpLastWriteTime);
  FileTimeToSystemTime(&lpLastWriteTime, &stLocal);

  DT = SystemTimeToDateTime(stLocal);

  Edit1->Text = FormatDateTime("dd.mm.yyy  hh:nn:ss", DT);
  CloseHandle(hFile);
 }

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
mckri
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: FILETIME vs. String

Nowy postprzez mckri » środa, 2 lutego 2011, 13:05

Natknąłem się na ta funkcję korzystajac z pomocy, jednak nawyraźniej niewłaściwie z niej korzystałem. Faktycznie teraz odczyt daty modyfikacji w dwóch funkcjach jest taki sam. Dzieki.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows VistaOpera


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 3 gości